How to know whether a Bluetooth device is still connected to a laptop or not before passing data? I wrote a java program using blue-cove lib to discover and pass the data through the laptop. After passing data for the first time, how can I check whether the device is still connected to laptop before passing data in the next time ?
I saw a similar question like this. But they have asked how to check the Bluetooth device status connected to the android.
You can follow a serie of steps and create an async task to verify the connection while is searching and sharing files between devices.
The functions deviceDiscovered() and inquiryCompleted() are the ones exeuted when a device is found and when the inquiry is finished.
If the device is disconnected, you would get a notify from the method inqueryCompleted and Handle it in the line:
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
In the InterruptedException you can handle the error.
package bt;
import java.io.OutputStream;
import java.util.ArrayList;
import javax.bluetooth.DataElement;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.obex.ClientSession;
import javax.obex.HeaderSet;
import javax.obex.Operation;
import javax.obex.ResponseCodes;
import bt.BTListener.MyDeviceListenerFilter;
public class MyDiscoveryListener implements DiscoveryListener{
private static Object lock=new Object();
public ArrayList<RemoteDevice> devices;
public MyDiscoveryListener() {
devices = new ArrayList<RemoteDevice>();
}
public static void main(String[] args) {
MyDiscoveryListener listener = new MyDiscoveryListener();
try{
LocalDevice localDevice = LocalDevice.getLocalDevice();
DiscoveryAgent agent = localDevice.getDiscoveryAgent();
agent.startInquiry(DiscoveryAgent.GIAC, listener);
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
return;
}
System.out.println("Device Inquiry Completed. ");
UUID[] uuidSet = new UUID[1];
uuidSet[0]=new UUID(0x1105); //OBEX Object Push service
int[] attrIDs = new int[] {
0x0100 // Service name
};
for (RemoteDevice device : listener.devices) {
agent.searchServices(
attrIDs,uuidSet,device,listener);
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
return;
}
System.out.println("Service search finished.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass arg1) {
String name;
try {
name = btDevice.getFriendlyName(false);
} catch (Exception e) {
name = btDevice.getBluetoothAddress();
}
devices.add(btDevice);
System.out.println("device found: " + name);
}
#Override
public void inquiryCompleted(int arg0) {
synchronized(lock){
lock.notify();
}
}
#Override
public void serviceSearchCompleted(int arg0, int arg1) {
synchronized (lock) {
lock.notify();
}
}
#Override
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
for (int i = 0; i < servRecord.length; i++) {
String url = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
if (url == null) {
continue;
}
DataElement serviceName = servRecord[i].getAttributeValue(0x0100);
if (serviceName != null) {
System.out.println("service " + serviceName.getValue() + " found " + url);
if(serviceName.getValue().equals("OBEX Object Push")){
sendMessageToDevice(url);
}
} else {
System.out.println("service found " + url);
}
}
}
private static void sendMessageToDevice(String serverURL){
try{
System.out.println("Connecting to " + serverURL);
ClientSession clientSession = (ClientSession) Connector.open(serverURL);
HeaderSet hsConnectReply = clientSession.connect(null);
if (hsConnectReply.getResponseCode() != ResponseCodes.OBEX_HTTP_OK) {
System.out.println("Failed to connect");
return;
}
HeaderSet hsOperation = clientSession.createHeaderSet();
hsOperation.setHeader(HeaderSet.NAME, "Hello.txt");
hsOperation.setHeader(HeaderSet.TYPE, "text");
//Create PUT Operation
Operation putOperation = clientSession.put(hsOperation);
// Send some text to server
byte data[] = "Hello World !!!".getBytes("iso-8859-1");
OutputStream os = putOperation.openOutputStream();
os.write(data);
os.close();
putOperation.close();
clientSession.disconnect(null);
clientSession.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
so I am developing an app to take in a file and upload it to an FTP server, but i keep getting android.os.NetworkOnMainThreadException. Any ideas on how to fix this?
This is my code
public void sendData() throws Exception {
FTPUploader stuff = new FTPUploader("xxx","xxx","xxx");
stuff.doInBackground();
}
FTPUploader Class:
import android.os.AsyncTask;
import org.apache.commons.net.ftp.FTPClient;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetAddress;
public class FTPUploader extends AsyncTask<String, Void, Void> {
//#Override
protected Void doInBackground(String... params) {
FTPClient con = new FTPClient();
try {
con.connect(InetAddress.getByName(params[0]));
if (con.login(params[1], params[2])) {
con.enterLocalPassiveMode();
String data = params[3];
ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes());
boolean result = con.storeFile(params[4], in);
in.close();
if (result) {
System.out.println("upload result: " + result);
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
con.logout();
con.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
You would need to call from your main activity or class instead of doInBackground ()
new FTPUploader().execute(param1,param2,param3);
I am trying to create a p2p android wallet for bitcoin using bitcoinj.
I created an address and added it as a wachedAddress in the wallet.
When I add some coins from http://tpfaucet.appspot.com/ my listener shows me that 0.02 coins have been added to my address but when I try to see the balance in my app is shows me 0 BTC. What am I missing?
Here is the code of my listener:
public class WalletListener extends AbstractWalletEventListener {
public static final String TAG = "WalletListener";
private WalletState walletState;
private Wallet wallet;
#Override
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
Log.d(TAG, "-----> coins resceived: " + tx.getHashAsString());
Log.d(TAG, "received: " + tx.getValue(wallet));
walletState = WalletState.getInstantce();
wallet = walletState.getReadyWallet();
Log.d(TAG, "The balance is: " + wallet.getBalance().toFriendlyString());
}
}
and here is the code for my WalletState class
package com.tools;
import android.os.AsyncTask;
import android.util.Log;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.mybitcoinwallet.WalletActivity;
import com.mybitcoinwallet.adapter.MyPagerAdapter;
import com.mybitcoinwallet.fragment.WalletFragment;
import com.mybitcoinwallet.listeners.WalletListener;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.BlockChain;
import org.bitcoinj.core.CheckpointManager;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.InsufficientMoneyException;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.PeerGroup;
import org.bitcoinj.core.ScriptException;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.Wallet;
import org.bitcoinj.crypto.KeyCrypterException;
import org.bitcoinj.net.discovery.DnsDiscovery;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.SPVBlockStore;
import org.bitcoinj.store.UnreadableWalletException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* Created by Mihail on 5/23/15.
*/
public class WalletState {
public static final String TAG = "WalletState";
private NetworkParameters network = TestNet3Params.get();
private Wallet wallet;
private Address address;
private MyPagerAdapter pagerAdapter;
private static WalletState walletState;
private PeerGroup peerGroup;
private BlockStore blockStore;
private File walletFile;
private WalletState() {
}
public void initiate() {
new BackgroundTask().execute();
}
public static WalletState getInstantce() {
if (walletState == null) {
walletState = new WalletState();
}
return walletState;
}
public static Wallet getWallet(NetworkParameters netParams) {
File walletFile = new File(WalletActivity.getMainActivity().getFilesDir().getPath().toString()
+ "my_wallet_file");
Log.i(TAG, WalletActivity.getMainActivity().getFilesDir().getPath().toString()
+ "my_wallet_file");
Wallet wallet;
try {
wallet = Wallet.loadFromFile(walletFile);
} catch (UnreadableWalletException e) {
wallet = new Wallet(netParams);
ECKey key = new ECKey();
wallet.addKey(key);
try {
wallet.saveToFile(walletFile);
} catch (IOException a) {
Log.e(TAG, "Caught IOException: ", a);
}
}
return wallet;
}
public class BackgroundTask extends AsyncTask {
public static final String TAG = "BackgroundTask";
#Override
protected Object doInBackground(Object[] params) {
try {
Log.d(TAG, "Started");
wallet = getWallet(network);
wallet.addEventListener(new WalletListener());
ECKey key = wallet.getImportedKeys().iterator().next();
File file = new File(WalletActivity.getMainActivity().getFilesDir().getPath()
+ "my_wallet_file" + ".spvchain");
boolean chainExistedAlready = file.exists();
blockStore = new SPVBlockStore(network, file);
if (!chainExistedAlready) {
File checkpointsFile = new File("checkpoints");
if (checkpointsFile.exists()) {
FileInputStream stream = new FileInputStream(checkpointsFile);
CheckpointManager.checkpoint(network, stream, blockStore, key.getCreationTimeSeconds());
}
}
BlockChain chain = new BlockChain(network, wallet, blockStore);
// Connect to the localhost node. One minute timeout since we won't try any other peers
Log.i(TAG, "Connecting ...");
peerGroup = new PeerGroup(network, chain);
peerGroup.setUserAgent("PingService", "1.0");
peerGroup.addPeerDiscovery(new DnsDiscovery(network));
peerGroup.addWallet(wallet);
peerGroup.startAsync();
peerGroup.awaitRunning();
Log.i(TAG, "Peers are fully synchronized! ");
address = wallet.currentReceiveAddress();
Log.i(TAG, "currentReceiveAddress: " + address);
wallet.addWatchedAddress(address);
ECKey ecKey = wallet.currentReceiveKey();
// Making sure that everything is shut down cleanly!
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
System.out.print("Shutting down ... ");
peerGroup.stopAsync();
peerGroup.awaitTerminated();
wallet.saveToFile(walletFile);
blockStore.close();
System.out.print("done ");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
} catch (Exception e) {
Log.e(TAG, "AAAAAA Exception!!!!!!", e);
}
return null;
}
#Override
protected void onPostExecute(Object o) {
Log.i(TAG, "onPostExecute! finally and the Key is: " + address.toString());
pagerAdapter = WalletActivity.getMainActivity().getPagerAdapter();
WalletFragment fragment = pagerAdapter.getFragment();
fragment.setmTextView(address.toString());
Coin balance = wallet.getBalance();
fragment.setBalanceText(balance.toFriendlyString());
Log.i(TAG, "The balance is " + balance.toFriendlyString());
fragment.setWallet_progressBar_visibility();
}
}
public void sendCoins(final Wallet wallet, Transaction tx) {
// It's impossible to pick one specific identity that you receive coins from in Bitcoin as there
// could be inputs from many addresses. So instead we just pick the first and assume they were all
// owned by the same person.
try {
Coin value = tx.getValueSentToMe(wallet);
TransactionInput input = tx.getInputs().get(0);
Address from = input.getFromAddress();
final Wallet.SendResult sendResult = wallet.sendCoins(peerGroup, from, value);
System.out.println("Sending ...");
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>() {
public void onSuccess(Transaction transaction) {
System.out.println("Sent coins back! Transaction hash is " + sendResult.tx.getHashAsString());
// The wallet has changed now, it'll get auto saved shortly or when the app shuts down.
}
public void onFailure(Throwable throwable) {
System.err.println("Failed to send coins :(");
throwable.printStackTrace();
}
});
} catch (ScriptException e) {
// If we didn't understand the scriptSig, just crash.
throw new RuntimeException(e);
} catch (KeyCrypterException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (InsufficientMoneyException e) {
e.printStackTrace();
}
}
public Wallet getReadyWallet() {
if (wallet != null) {
Log.i(TAG, "The ready wallet was returned");
return wallet;
}
return getWallet(network);
}
}
i have my code that sucessfuly send my client message to server.. can anyone help pls ? i'm new in socket programming. i want to establish a server that sends the message of my android client to other android client... here is my code
CLIENT ANDROID :
package com.example.websocketclient;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class Chatroom extends Activity {
public static String msgToServer = null;
TextView uname;
EditText in;
Button snd;
TextView out;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chatroom);
uname = (TextView) findViewById(R.id.textViewmynam);
in = (EditText) findViewById(R.id.editTextInput);
snd = (Button) findViewById(R.id.buttonSend);
out = (TextView) findViewById(R.id.textViewOutput);
Bundle bundle = getIntent().getExtras();
String urname = bundle.getString("myname");
uname.setText(urname);
MyClientTask clientTask = new MyClientTask();
clientTask.execute();
}
public class MyClientTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
connect();
return null;
}
}
public void connect() {
Socket sock;
int[] allports = {1111,1919,2020};
int portnum;
for(int i=1;i<allports.length;i++) {
try {
portnum = allports[i];
boolean socketno = Middleware.available(portnum);
String ad = "192.168.149.1";
if(socketno = true) {
sock = new Socket(ad,portnum);
while(socketno) {
sendmsg(sock);
}//while
// sock.close();
}//if
}catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void sendmsg (final Socket s) {
snd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
//boolean listening = true;
String inmsg = ""+in.getText().toString();
String response = "";
msgToServer = inmsg;
//out.append("you:"+msgToServer+"\n");
try {
DataOutputStream outToServer = new DataOutputStream(s.getOutputStream());
DataInputStream inToServer = new DataInputStream(s.getInputStream());
if(outToServer != null){
outToServer.writeBytes(msgToServer+"\n");
}
}
catch (Exception e) {
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.chatroom, menu);
return true;
}
}
Here is my PC Server side :
package Server;
import java.net.*;
import java.io.*;
import java.util.Scanner;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.*;
public class SocketServer extends Thread {
final static int _portNumber = 1919; //Arbitrary port number
public static void main(String[] args)
{
try {
new SocketServer().startServer();
} catch (Exception e) {
System.out.println("I/O failure: " + e.getMessage());
}
}
public void startServer() throws Exception {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(_portNumber);
} catch (IOException e) {
System.err.println("Could not listen on port: " + _portNumber);
System.exit(-1);
}
while (listening) {
System.out.println("Huwat huwat kang client..!");
handleClientRequest(serverSocket);
}
serverSocket.close();
}
private void handleClientRequest(ServerSocket serverSocket) {
try {
new Thread(new ConnectionRequestHandler(serverSocket.accept())).start();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Handles client connection requests.
*/
public class ConnectionRequestHandler implements Runnable{
private Socket _socket;
private PrintWriter _out;
private BufferedReader _in;
public ConnectionRequestHandler(Socket socket) {
_socket = socket;
}
public void run() {
String info;
int maxid;
System.out.println("Client connected to socket: " + _socket.toString());
info = _socket.toString();
//incrementing the msg_id
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
_socket.getOutputStream()));
_in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
String inputLine;
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/finalclient","root","");
PreparedStatement st = con.prepareStatement("select *from msgs order by msg_id desc");
ResultSet r1 = st.executeQuery();
r1.first(); // or r1.next()
maxid = r1.getInt("msg_id") + 1;
while ((inputLine = _in.readLine()) != null) {
System.out.println("Message from Client: "+inputLine);
out.write(inputLine);
try {
PreparedStatement st1=con.prepareStatement("insert into msgs values(?,?,?)");
st1.setInt(1,maxid);
st1.setString(2,info);
st1.setString(3,inputLine);
int count = st1.executeUpdate ();
System.out.println (count + " rows were inserted to Database");
}
catch (Exception e) {
System.out.println("Failed to Insert from DB"+e);
}
}
}
catch (Exception e) {
System.out.println("Failed to Select from DB"+e);
}
}
}
}
I am trying to write a twitter application on Android target 2.2 (using some sample code that I found on the net and using Marko Gargenta's O'Reilly text). I am stuck with the problem as in the log below. The source code is given first followed by the log. Any idea what's going wrong here ? Also does anyone have or can point to a sample jtwitter code working on Android.
Thanks,
Ravi
protected String doInBackground(String... statuses) {
try {
//Autho information
/*OAuthSignpostClient oauthclient = new OAuthSignpostClient(cons_key,
cons_secret, access_token, access_secret);*/
OAuthSignpostClient oauthclient = new OAuthSignpostClient(access_token, access_secret,"oob");
//***POSTING TO TWITTER CURRENTLY DOES NOT WORK WITH THIS INTERFACE
twitter = new Twitter(mytwitterusername, oauthclient);
//twitter.setAPIRootUrl("http://learningandroid.status.net/api");
//***POSTING TO TWITTER CURRENTLY DOES NOT WORK WITH THIS INTERFACE
Log.i(Logtag, "Status currently is " + statuses[0]);
Twitter.Status status = twitter.updateStatus(statuses[0]);
//return status.text;
return statuses[0];
} catch (TwitterException e) {
Log.e(Logtag, e.toString());
e.printStackTrace();
return "Failed to post to Twitter";
}
}
Log file:
E/dalvikvm( 719): Could not find method javax.swing.JOptionPane.showInputDialog, referenced from method winterwell.jtwi
tter.OAuthSignpostClient.askUser
W/dalvikvm( 719): VFY: unable to resolve static method 443: Ljavax/swing/JOptionPane;.showInputDialog (Ljava/lang/Objec
t;)Ljava/lang/String;
W/dalvikvm( 719): VFY: rejecting opcode 0x71 at 0x0000
W/dalvikvm( 719): VFY: rejected Lwinterwell/jtwitter/OAuthSignpostClient;.askUser (Ljava/lang/String;)Ljava/lang/Strin
g;
W/dalvikvm( 719): Verifier rejected class Lwinterwell/jtwitter/OAuthSignpostClient;
W/dalvikvm( 719): threadid=17: thread exiting with uncaught exception (group=0x4000fe70)
E/AndroidRuntime( 719): Uncaught handler: thread AsyncTask #1 exiting due to uncaught exception
E/AndroidRuntime( 719): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime( 719): at android.os.AsyncTask$3.done(AsyncTask.java:200)
E/AndroidRuntime( 719): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:234)
E/AndroidRuntime( 719): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:258)
E/AndroidRuntime( 719): at java.util.concurrent.FutureTask.run(FutureTask.java:122)
E/AndroidRuntime( 719): at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648)
E/AndroidRuntime( 719): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673)
E/AndroidRuntime( 719): at java.lang.Thread.run(Thread.java:1058)
E/AndroidRuntime( 719): Caused by: java.lang.VerifyError: winterwell.jtwitter.OAuthSignpostClient
E/AndroidRuntime( 719): at com.ravi.tweeto.StatusActivity$PostToTwitter.doInBackground(StatusActivity.java:81)
E/AndroidRuntime( 719): at com.ravi.tweeto.StatusActivity$PostToTwitter.doInBackground(StatusActivity.java:1)
E/AndroidRuntime( 719): at android.os.AsyncTask$2.call(AsyncTask.java:185)
E/AndroidRuntime( 719): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256)
E/AndroidRuntime( 719): ... 4 more
I/Process ( 585): Sending signal. PID: 719 SIG: 3
I/dalvikvm( 719): threadid=7: reacting to signal 3
I/dalvikvm( 719): Wrote stack trace to '/data/anr/traces.txt'
----
Basically the JTwitter library has calls to Java swing classes that are not in the Android SDK as it does not use swing. I had to get the source for JTwitter and remove the swing code for my application to work. Hope this helps.
Might be worth looking at using the Twitter4J library as an alternative. I've had no issues using it within an Android application.
I found most of the code I use somewhere on GitHub (can't find the exact link right now)
A few searches on snippets of the code send me here, but I don't think that was the exact site I got it from.
But this is what I have in my semi-working code.
OAUTH.java
import junit.framework.Assert;
import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class OAUTH extends Activity {
private static final String TAG = "OAUTH";
public static final String USER_TOKEN = "user_token";
public static final String USER_SECRET = "user_secret";
public static final String REQUEST_TOKEN = "request_token";
public static final String REQUEST_SECRET = "request_secret";
public static final String TWITTER_REQUEST_TOKEN_URL = "http://twitter.com/oauth/request_token";
public static final String TWITTER_ACCESS_TOKEN_URL = "http://twitter.com/oauth/access_token";
public static final String TWITTER_AUTHORIZE_URL = "http://twitter.com/oauth/authorize";
private static final Uri CALLBACK_URI = Uri.parse("gpsagenda://twitt");
public static final String PREFS = "MyPrefsFile";
private OAuthConsumer mConsumer = null;
private OAuthProvider mProvider = null;
SharedPreferences mSettings;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// We don't need to worry about any saved states: we can reconstruct the state
mConsumer = new CommonsHttpOAuthConsumer(
"myKey",
"mySecret");
mProvider = new CommonsHttpOAuthProvider (
TWITTER_REQUEST_TOKEN_URL,
TWITTER_ACCESS_TOKEN_URL,
TWITTER_AUTHORIZE_URL);
// It turns out this was the missing thing to making standard Activity launch mode work
mProvider.setOAuth10a(true);
mSettings = this.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
Intent i = this.getIntent();
if (i.getData() == null) {
try {
// This is really important. If you were able to register your real callback Uri with Twitter, and not some fake Uri
// like I registered when I wrote this example, you need to send null as the callback Uri in this function call. Then
// Twitter will correctly process your callback redirection
String authUrl = mProvider.retrieveRequestToken(mConsumer, CALLBACK_URI.toString());
saveRequestInformation(mSettings, mConsumer.getToken(), mConsumer.getTokenSecret());
this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)));
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
}
}
}
#Override
protected void onResume() {
super.onResume();
Uri uri = getIntent().getData();
if (uri != null && CALLBACK_URI.getScheme().equals(uri.getScheme())) {
String token = mSettings.getString(OAUTH.REQUEST_TOKEN, null);
String secret = mSettings.getString(OAUTH.REQUEST_SECRET, null);
Intent i = new Intent(this, DetailsContainer.class); // Currently, how we get back to main activity.
try {
if(!(token == null || secret == null)) {
mConsumer.setTokenWithSecret(token, secret);
}
String otoken = uri.getQueryParameter(OAuth.OAUTH_TOKEN);
String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
// We send out and save the request token, but the secret is not the same as the verifier
// Apparently, the verifier is decoded to get the secret, which is then compared - crafty
// This is a sanity check which should never fail - hence the assertion
Assert.assertEquals(otoken, mConsumer.getToken());
// This is the moment of truth - we could throw here
mProvider.retrieveAccessToken(mConsumer, verifier);
// Now we can retrieve the goodies
token = mConsumer.getToken();
secret = mConsumer.getTokenSecret();
OAUTH.saveAuthInformation(mSettings, token, secret);
// Clear the request stuff, now that we have the real thing
OAUTH.saveRequestInformation(mSettings, null, null);
i.putExtra(USER_TOKEN, token);
i.putExtra(USER_SECRET, secret);
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
} finally {
startActivity(i); // we either authenticated and have the extras or not, but we're going back
finish();
}
}
}
public static void saveRequestInformation(SharedPreferences settings, String token, String secret) {
// null means to clear the old values
SharedPreferences.Editor editor = settings.edit();
if(token == null) {
editor.remove(OAUTH.REQUEST_TOKEN);
Log.d(TAG, "Clearing Request Token");
}
else {
editor.putString(OAUTH.REQUEST_TOKEN, token);
Log.d(TAG, "Saving Request Token: " + token);
}
if (secret == null) {
editor.remove(OAUTH.REQUEST_SECRET);
Log.d(TAG, "Clearing Request Secret");
}
else {
editor.putString(OAUTH.REQUEST_SECRET, secret);
Log.d(TAG, "Saving Request Secret: " + secret);
}
editor.commit();
}
public static void saveAuthInformation(SharedPreferences settings, String token, String secret) {
// null means to clear the old values
SharedPreferences.Editor editor = settings.edit();
if(token == null) {
editor.remove(OAUTH.USER_TOKEN);
Log.d(TAG, "Clearing OAuth Token");
}
else {
editor.putString(OAUTH.USER_TOKEN, token);
Log.d(TAG, "Saving OAuth Token: " + token);
}
if (secret == null) {
editor.remove(OAUTH.USER_SECRET);
Log.d(TAG, "Clearing OAuth Secret");
}
else {
editor.putString(OAUTH.USER_SECRET, secret);
Log.d(TAG, "Saving OAuth Secret: " + secret);
}
editor.commit();
}
}
DetailsTwitter.java (my "implementation")
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.gpsagenda.OAUTH;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class DetailsTwitter extends Activity {
public SharedPreferences mSettings;
private LinkedList<UserStatus> mHomeStatus = new LinkedList<UserStatus>();
public String mToken;
public String mSecret;
private OAuthConsumer mConsumer = null;
private HttpClient mClient;
private EditText mEditor;
private TextView mLast;
private CheckBox mCB;
private Button mButton;
private TextView mUser;
private int ID;
public static final String VERIFY_URL_STRING = "http://twitter.com/account/verify_credentials.json";
public static final String PUBLIC_TIMELINE_URL_STRING = "http://twitter.com/statuses/public_timeline.json";
public static final String USER_TIMELINE_URL_STRING = "http://twitter.com/statuses/user_timeline.json";
public static final String HOME_TIMELINE_URL_STRING = "http://api.twitter.com/1/statuses/home_timeline.json";
public static final String FRIENDS_TIMELINE_URL_STRING = "http://api.twitter.com/1/statuses/friends_timeline.json";
public static final String STATUSES_URL_STRING = "http://twitter.com/statuses/update.json";
ProgressDialog postDialog = null;
public static final String TWITTER_REQUEST_TOKEN_URL = "http://twitter.com/oauth/request_token";
public static final String TWITTER_ACCESS_TOKEN_URL = "http://twitter.com/oauth/access_token";
public static final String TWITTER_AUTHORIZE_URL = "http://twitter.com/oauth/authorize";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detailstwittertab);
HttpParams parameters = new BasicHttpParams();
HttpProtocolParams.setVersion(parameters, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(parameters, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(parameters, false);
HttpConnectionParams.setTcpNoDelay(parameters, true);
HttpConnectionParams.setSocketBufferSize(parameters, 8192);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
ClientConnectionManager tsccm = new ThreadSafeClientConnManager(parameters, schReg);
mClient = new DefaultHttpClient(tsccm, parameters);
mCB = (CheckBox) this.findViewById(R.id.enable);
mCB.setChecked(false);
mEditor = (EditText) this.findViewById(R.id.editor);
mButton = (Button) this.findViewById(R.id.post);
mUser = (TextView) this.findViewById(R.id.user);
mLast = (TextView) this.findViewById(R.id.last);
mSettings = getSharedPreferences(OAUTH.PREFS, Context.MODE_PRIVATE);
mConsumer = new CommonsHttpOAuthConsumer(
"myKey",
"mySecret");
}
public void PostTweet(View v) {
String postString = mEditor.getText().toString();
if (postString.length() == 0) {
Toast.makeText(this, getText(R.string.tweet_empty), Toast.LENGTH_SHORT).show();
} else {
BitlyAndroid bitly = new BitlyAndroid("iarwain01", "R_1bffd0176aa731a27e5b2d23cf043199");
String shortUrl = "";
// Try to get the corresponding ID of the POI
try
{
ID = getIntent().getExtras().getInt("id");
} catch (NullPointerException e)
{
e.printStackTrace();
}
try {
shortUrl = bitly.getShortUrl("http://gpsagenda.ikdoeict.be/projecten2/index.php?module=places&id=" + ID);
} catch (Exception e) {
Log.e("Debug", "Link shortening failed!");
e.printStackTrace();
}
new PostTask().execute(postString + " " + shortUrl);
}
}
protected void onFinish() {
mClient.getConnectionManager().shutdown();
}
public void ConnectWithTwitter(View v)
{
if(mCB.isChecked()) {
Intent i = new Intent(this, OAUTH.class);
startActivity(i);
} else {
OAUTH.saveAuthInformation(mSettings, null, null);
mButton.setEnabled(false);
mEditor.setEnabled(false);
mCB.setChecked(false);
mUser.setText("");
}
mCB.setChecked(false); // the oauth callback will set it to the proper state
}
#Override
public void onResume()
{
super.onResume();
// We look for saved user keys
if(mSettings.contains(OAUTH.USER_TOKEN) && mSettings.contains(OAUTH.USER_SECRET)) {
mToken = mSettings.getString(OAUTH.USER_TOKEN, null);
mSecret = mSettings.getString(OAUTH.USER_SECRET, null);
if(!(mToken == null || mSecret == null)) {
mConsumer.setTokenWithSecret(mToken, mSecret);
}
}
new GetCredentialsTask().execute();
}
// These parameters are needed to talk to the messaging service
public HttpParams getParams() {
// Tweak further as needed for your app
HttpParams params = new BasicHttpParams();
// set this to false, or else you'll get an Expectation Failed: error
HttpProtocolParams.setUseExpectContinue(params, false);
return params;
}
//----------------------------
// This task posts a message to your message queue on the service.
private class PostTask extends AsyncTask<String, Void, JSONObject> {
ProgressDialog postDialog;
#Override
protected void onPreExecute() {
postDialog = ProgressDialog.show(DetailsTwitter.this,
getText(R.string.tweet_progress_title),
getText(R.string.tweet_progress_text),
true, // indeterminate duration
false); // not cancel-able
}
#Override
protected JSONObject doInBackground(String... params) {
JSONObject jso = null;
try {
HttpPost post = new HttpPost("http://twitter.com/statuses/update.json");
LinkedList<BasicNameValuePair> out = new LinkedList<BasicNameValuePair>();
out.add(new BasicNameValuePair("status", params[0]));
post.setEntity(new UrlEncodedFormEntity(out, HTTP.UTF_8));
post.setParams(getParams());
// sign the request to authenticate
mConsumer.sign(post);
String response = mClient.execute(post, new BasicResponseHandler());
jso = new JSONObject(response);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
}
return jso;
}
// This is in the UI thread, so we can mess with the UI
protected void onPostExecute(JSONObject jso) {
postDialog.dismiss();
if(jso != null) { // authorization succeeded, the json object contains the user information
mEditor.setText("");
mLast.setText(getCurrentTweet(jso));
} else {
mLast.setText(getText(R.string.tweet_error));
}
}
}
// Get stuff from the two types of Twitter JSONObject we deal with: credentials and status
private String getCurrentTweet(JSONObject status) {
return status.optString("text", getString(R.string.bad_value));
}
//----------------------------
// This task is run on every onResume(), to make sure the current credentials are valid.
// This is probably overkill for a non-educational program
private class GetCredentialsTask extends AsyncTask<Void, Void, JSONObject> {
ProgressDialog authDialog;
#Override
protected void onPreExecute() {
authDialog = ProgressDialog.show(DetailsTwitter.this,
getText(R.string.auth_progress_title),
getText(R.string.auth_progress_text),
true, // indeterminate duration
false); // not cancel-able
}
#Override
protected JSONObject doInBackground(Void... arg0) {
JSONObject jso = null;
HttpGet get = new HttpGet(VERIFY_URL_STRING);
try {
mConsumer.sign(get);
String response = mClient.execute(get, new BasicResponseHandler());
jso = new JSONObject(response);
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jso;
}
// This is in the UI thread, so we can mess with the UI
protected void onPostExecute(JSONObject jso) {
authDialog.dismiss();
mCB.setChecked(jso != null);
mButton.setEnabled(jso != null);
mEditor.setEnabled(jso != null);
mUser.setText(jso != null ? getUserName(jso) : getString(R.string.userhint));
mLast.setText(jso != null ? getLastTweet(jso) : getString(R.string.userhint));
if(jso != null) {
TimelineSelector ss = new TimelineSelector(HOME_TIMELINE_URL_STRING);
new GetTimelineTask().execute(ss);
}
}
}
private String getLastTweet(JSONObject credentials) {
try {
JSONObject status = credentials.getJSONObject("status");
return getCurrentTweet(status);
} catch (JSONException e) {
e.printStackTrace();
return getString(R.string.tweet_error);
}
}
private String getUserName(JSONObject credentials) {
return credentials.optString("name", getString(R.string.bad_value));
}
private class TimelineSelector extends Object {
public String url; // the url to perform the query from
// not all these apply to every url - you are responsible
public Long since_id; // ids newer than this will be fetched
public Long max_id; // ids older than this will be fetched
public Integer count; // # of tweets to fetch Max is 200
public Integer page; // # of page to fetch (with limits)
public TimelineSelector(String u) {
url = u;
max_id = null;
since_id = null;
count = null;
page = null;
}
#SuppressWarnings("unused")
public TimelineSelector(String u, Long since, Long max, Integer cnt, Integer pg) {
url = u;
max_id = max;
since_id = since;
count = cnt;
page = pg;
}
}
private class UserStatus {
JSONObject mStatus;
#SuppressWarnings("unused")
JSONObject mUser;
public UserStatus(JSONObject status) throws JSONException {
mStatus = status;
mUser = status.getJSONObject("user");
}
#SuppressWarnings("unused")
public long getId() {
return mStatus.optLong("id", -1);
}
/*public String getUserName() {
return mUser.optString("name", getString(R.string.bad_value));
}
public String getText() {
return getCurrentTweet(mStatus);
}
public String getCreatedAt() {
#SuppressWarnings("unused")
Time ret1 = new Time();
return mStatus.optString("created_at", getString(R.string.bad_value));
}*/
}
private class GetTimelineTask extends AsyncTask<TimelineSelector, Void, JSONArray> {
#Override
protected JSONArray doInBackground(TimelineSelector... params) {
JSONArray array = null;
try {
for(int i = 0; i < params.length; ++i) {
Uri sUri = Uri.parse(params[i].url);
Uri.Builder builder = sUri.buildUpon();
if(params[i].since_id != null) {
builder.appendQueryParameter("since_id", String.valueOf(params[i].since_id));
} else if (params[i].max_id != null) { // these are mutually exclusive
builder.appendQueryParameter("max_id", String.valueOf(params[i].max_id));
}
if(params[i].count != null) {
builder.appendQueryParameter("count", String.valueOf((params[i].count > 200) ? 200 : params[i].count));
}
if(params[i].page != null) {
builder.appendQueryParameter("page", String.valueOf(params[i].page));
}
HttpGet get = new HttpGet(builder.build().toString());
mConsumer.sign(get);
String response = mClient.execute(get, new BasicResponseHandler());
array = new JSONArray(response);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
}
return array;
}
// This is in the UI thread, so we can mess with the UI
protected void onPostExecute(JSONArray array) {
if(array != null) {
try {
for(int i = 0; i < array.length(); ++i) {
JSONObject status = array.getJSONObject(i);
UserStatus s = new UserStatus(status);
mHomeStatus.add(s);
}
//mAA.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
} else {
}
}
}
}
My AndroidManifest.xml
<activity android:name="DetailsTwitter" />
<activity android:name="OAUTH" >
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="gpsagenda" android:host="twitt" />
</intent-filter>
</activity>
This should be enough to get you going, I hope.
If something is wrong in here, pleas do comment.
Regards,
iarwain