views:

226

answers:

4

Anybody can please help in Android + Twitter Integration using OAuth.

I already worked on http://github.com/brione/Brion-Learns-OAuth and getting the error listed below, when I am posting status update...

WARN/System.err(190): org.apache.http.client.HttpResponseException: Unauthorized WARN/System.err(190): at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:71) WARN/System.err(190): at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:59) WARN/System.err(190): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657) WARN/System.err(190): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627) WARN/System.err(190): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616) WARN/System.err(190): at com.test.twitter.BLOA$PostTask.doInBackground(BLOA.java:343) WARN/System.err(190): at com.test.twitter.BLOA$PostTask.doInBackground(BLOA.java:1) WARN/System.err(190): at android.os.AsyncTask$2.call(AsyncTask.java:185) WARN/System.err(190): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256) WARN/System.err(190): at java.util.concurrent.FutureTask.run(FutureTask.java:122) WARN/System.err(190): at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648) WARN/System.err(190): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673) WARN/System.err(190): at java.lang.Thread.run(Thread.java:1060)

I succeed with OAuth Authentication and getting user_secret and user_token and stored in preferences...

So the issue is with http posting using OAuth header...

and My Http Post Method is as :

private class PostTask extends AsyncTask<String, Void, JSONObject> {

  ProgressDialog postDialog;

  @Override
  protected void onPreExecute() {
   postDialog = ProgressDialog.show(BLOA.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));
   }
  }
 }
+1  A: 

Although you are received the user_secret and user_token successfully in onResume(), are you sure your original objects are still the same? I had this problem in my Android app. I would create the objects, but when onResume() was called it was a totally new instance of the Activity because it was free'd from memory when the browser launched. So when I tried to set the returned secret/token pair it wouldn't work. This is more likely to happen on a device with limited memory. Some people choose to persist the necessary info between calls and others decide to not launch the default browser intent, but rather host an embedded webview so their original signpost-oauth objects don't go out of scope.

http://stackoverflow.com/questions/1965568/oauth-instance-state-in-android

Not sure if this is the issue, but maybe worth a look.

GrkEngineer
A: 

I have 2 tutorials for 2 different Java libs. First one (dated) is here, and 2nd one here with Scribe. It's for LinkedIn but it would be very easy to switch to Twitter. I would go with #2

DroidIn.net
+1  A: 

You need to add the oauth information to the headers of the http request using post.addHeader(). To know which things to add to the headers, take a look here: http://dev.twitter.com/pages/auth

Moncader
My code is as written above.. can you please explain in detail? or give me an example ?
Vishal
You are using signpost library which simplifies interaction using OAuth protocol, so no manual setting of headers is required. Please answer my questions below and I'll try to help you, I am using signpost library in my project too.
shaman.sir
A: 

Please describe what Client/Consumer/Provider you are using, they must be DefaultHttpClient/CommonsHttpOAuthConsumer/CommonsHttpOAuthProvider to work properly for sure.

Ensure you call consumer.setTokenWithSecret(oToken, oTokenSecret); before calling this code.

Also, is post.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false); exists in your post params?

What's the reason for using empty BasicResponseHandler, it handles nothing and it can be omitted in execute call, I suppose.

And, may be a dumb question, may be you are overwriting params when calling setParams(...) after setEntity(...)

shaman.sir