OAuth in Android

Posted on Apr 30, 2011 (2 years ago). Seen 21,804 times. 32 comments. Permalink Feed
Photo Marko Gargenta
@MarkoGargenta
Member since Jan 19, 2007
Location: San Francisco
Stream Posts: 42
Tagged as: Android

Here's a simple example that uses OAuth to authorize your app with Twitter. I use Jamba-modified JTwitter library here. The source code is included, but you must get your own OAuth key from Twitter by going to https://dev.twitter.com/apps/new.

You should enter something like this when registering your app:




MainActivity.java

Note that I use SignPost and JTwitter libraries with this code (provided in source). Also, the key to this code is the callback from the browser back to the app. You need to see the Manifest file down below to get the whole picture.

Code:

package com.marakana.oauth;

import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import winterwell.jtwitter.OAuthSignpostClient;
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
private static final String TAG = "OAuthDemo";
private static final String OAUTH_KEY = "YOUR_KEY_GOES_HERE";
private static final String OAUTH_SECRET = "YOUR_SECRET_GOES_HERE";
private static final String OAUTH_CALLBACK_SCHEME = "x-marakana-oauth-twitter";
private static final String OAUTH_CALLBACK_URL = OAUTH_CALLBACK_SCHEME
+ "://callback";
private static final String TWITTER_USER = "YOUR_EMAIL_GOES_HERE";

private OAuthSignpostClient oauthClient;
private OAuthConsumer mConsumer;
private OAuthProvider mProvider;
private Twitter twitter;
SharedPreferences prefs;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// mConsumer = new DefaultOAuthConsumer(OAUTH_KEY, OAUTH_SECRET);
mConsumer = new CommonsHttpOAuthConsumer(OAUTH_KEY, OAUTH_SECRET);
mProvider = new DefaultOAuthProvider(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize");

// Read the prefs to see if we have token
prefs = PreferenceManager.getDefaultSharedPreferences(this);
String token = prefs.getString("token", null);
String tokenSecret = prefs.getString("tokenSecret", null);
if (token != null && tokenSecret != null) {
// We have token, use it
mConsumer.setTokenWithSecret(token, tokenSecret);
// Make a Twitter object
oauthClient = new OAuthSignpostClient(OAUTH_KEY, OAUTH_SECRET, token,
tokenSecret);
twitter = new Twitter(TWITTER_USER, oauthClient);
}
}

/* Callback once we are done with the authorization of this app with Twitter. */
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, "intent: " + intent);

// Check if this is a callback from OAuth
Uri uri = intent.getData();
if (uri != null && uri.getScheme().equals(OAUTH_CALLBACK_SCHEME)) {
Log.d(TAG, "callback: " + uri.getPath());

String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
Log.d(TAG, "verifier: " + verifier);

new RetrieveAccessTokenTask().execute(verifier);
}

}

public void onClickAuthorize(View view) {
new OAuthAuthorizeTask().execute();
}

public void onClickTweet(View view) {
if (twitter == null) {
Toast.makeText(this, "Authenticate first", Toast.LENGTH_LONG).show();
return;
}

EditText status = (EditText) findViewById(R.id.status);
new PostStatusTask().execute(status.getText().toString());
}

public void onClickGetStatus(View view) {
if (twitter == null) {
Toast.makeText(this, "Authenticate first", Toast.LENGTH_LONG).show();
return;
}
new GetStatusTask().execute();
}

/* Responsible for starting the Twitter authorization */
class OAuthAuthorizeTask extends AsyncTask<Void, Void, String> {

@Override
protected String doInBackground(Void... params) {
String authUrl;
String message = null;
try {
authUrl = mProvider.retrieveRequestToken(mConsumer, OAUTH_CALLBACK_URL);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl));
startActivity(intent);
} catch (OAuthMessageSignerException e) {
message = "OAuthMessageSignerException";
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
message = "OAuthNotAuthorizedException";
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
message = "OAuthExpectationFailedException";
e.printStackTrace();
} catch (OAuthCommunicationException e) {
message = "OAuthCommunicationException";
e.printStackTrace();
}
return message;
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null) {
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
}
}

/* Responsible for retrieving access tokens from twitter */
class RetrieveAccessTokenTask extends AsyncTask<String, Void, String> {

@Override
protected String doInBackground(String... params) {
String message = null;
String verifier = params[0];
try {
// Get the token
Log.d(TAG, "mConsumer: " + mConsumer);
Log.d(TAG, "mProvider: " + mProvider);
mProvider.retrieveAccessToken(mConsumer, verifier);
String token = mConsumer.getToken();
String tokenSecret = mConsumer.getTokenSecret();
mConsumer.setTokenWithSecret(token, tokenSecret);

Log.d(TAG, String.format("verifier: %s, token: %s, tokenSecret: %s",
verifier, token, tokenSecret));

// Store token in prefs
prefs.edit().putString("token", token).putString("tokenSecret",
tokenSecret).commit();

// Make a Twitter object
oauthClient = new OAuthSignpostClient(OAUTH_KEY, OAUTH_SECRET, token,
tokenSecret);
twitter = new Twitter("MarkoGargenta", oauthClient);

Log.d(TAG, "token: " + token);
} catch (OAuthMessageSignerException e) {
message = "OAuthMessageSignerException";
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
message = "OAuthNotAuthorizedException";
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
message = "OAuthExpectationFailedException";
e.printStackTrace();
} catch (OAuthCommunicationException e) {
message = "OAuthCommunicationException";
e.printStackTrace();
}
return message;
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null) {
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
}
}

/* Responsible for getting Twitter status */
class GetStatusTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
return twitter.getStatus().text;
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
}

/* Responsible for posting new status to Twitter */
class PostStatusTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
try {
twitter.setStatus(params[0]);
return "Successfully posted: " + params[0];
} catch (TwitterException e) {
return "Error connecting to server.";
}
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}

}
}

AndroidManifest.xml

The key here is the intent filter that serves as a callback to our main activity to complete the authentication process.

Code:

<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.marakana.oauth"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="11" />
<uses-permission
android:name="android.permission.INTERNET" />


<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- Used for OAuth callback -->
<intent-filter>
<action
android:name="android.intent.action.VIEW" />
<category
android:name="android.intent.category.DEFAULT" />
<category
android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="x-marakana-oauth-twitter"
android:host="callback" />
</intent-filter>

</activity>

</application>
</manifest>

main.xml Layout

Nothing special here, just basic UI stuff.

Code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="50sp"
android:gravity="center" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Authenticate"
android:onClick="onClickAuthorize"
android:textSize="40sp"></Button>
<EditText
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/status"
android:textSize="40sp"
android:hint="What's up?"></EditText>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tweet"
android:onClick="onClickTweet"
android:textSize="40sp"></Button>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get Status"
android:textSize="40sp"
android:onClick="onClickGetStatus"></Button>

</LinearLayout>

Source code is here:
https://github.com/marakana/OAuthDemo

Comments

Posted on May 16, 2011
Photo Piyush Mishra
Meomyo
Member since May 16, 2011
Hi Marko, I learned a lot from your examples and i am still learning, i download your this example but its not working, even i created a new project and just copied all the things with sincerity but it shows Application require API version 11 and i am trying to make it on API level 8, any suggestion.
Posted on May 16, 2011
Photo Marko Gargenta
@MarkoGargenta
Member since Jan 19, 2007
Location: San Francisco
You can probably just change the API level for the app to 8. But I haven't tested it on 8.
Posted on May 16, 2011
Photo Piyush Mishra
Meomyo
Member since May 16, 2011
Yah i changed it to 8. But whenever i tried to run it, it want API level 11, but i just want to see the things in your code thats it. I saw your videos and you explain the things very nicely. Now i have an working example i just want to ask if i have token and token secret than what changes i can do, So that Oauth page didn't come again, i stored the things in shared preferences but how could i use it to not login again. Got my answer to see your code again using Twitter i can do that, thanks for all.
Posted on May 18, 2011
Photo Marcio Valenzuela
Santiapps
Member since May 16, 2011
I'm about to try it on 8. I saw the post about the stored preferences Piyush posted. Did you try it on the emulator? Because maybe it won't work, only on the device.
Posted on May 19, 2011
Photo Marcio Valenzuela
Santiapps
Member since May 16, 2011
btw, is there a video for this? Because i think the youtube video covers the basicauth only.
Posted on May 28, 2011
Photo Marko Gargenta
@MarkoGargenta
Member since Jan 19, 2007
Location: San Francisco
There's no video for this one yet. Btw, I think the set of libraries that this example assumes works with Honeycomb but not older versions of Android. I haven't done much testing for those older versions - Honeycomb's been the focus.
Marko
Posted on May 28, 2011
Photo Marcio Valenzuela
Santiapps
Member since May 16, 2011
I've been working on your example.

I configured my twitter app as browser and put in "www.mysite.com" as the callback URL. I have my key and secret.

The only thing I haven't gotten clear is your scheme and callback URL values. Where do you get them from?

I've tried your app with your values provided and it works. The minute I put my key/secret it fails with an:

Error Connecting to Server
OAuthCommunicationException

Full details here:


http://stackoverflow.com/questions/6163111/twitter-api-not-accepting-callback-url-for-android-app
Posted on May 28, 2011
Photo Marko Gargenta
@MarkoGargenta
Member since Jan 19, 2007
Location: San Francisco
The callback URL is something you make up. Basically, your app is going to call twitter.com via the browser. When done, browser will tell your app do open up a callback URL. This URL should in turn trigger your app so that user gets back to where he came from.

To do this, it is important that the callback you pass on in Java file matches the intent filter you declare in your Manifest file. In my case, my Java uses:

Code:


private static final String OAUTH_CALLBACK_SCHEME = "x-marakana-oauth-twitter";
private static final String OAUTH_CALLBACK_URL = OAUTH_CALLBACK_SCHEME
+ "://callback";


and that matches my Manifests intent filter:

Code:


<!-- Used for OAuth callback -->
<intent-filter>
<action
android:name="android.intent.action.VIEW" />
<category
android:name="android.intent.category.DEFAULT" />
<category
android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="x-marakana-oauth-twitter"
android:host="callback" />
</intent-filter>


I hope this helps. Took me a while to figure this one out initially. OAuth was designed for the web, not Android.
Posted on May 28, 2011
Photo Marcio Valenzuela
Santiapps
Member since May 16, 2011
If u can see from my code:


public class MainActivity extends Activity {
  private static final String TAG = "OAuthDemo";
  //private static final String OAUTH_KEY = "o1omK33TMwHMFC6yOqtmiA";
  private static final String OAUTH_KEY = "2a5GTsOZLwFa3k2g5oiAg";
  //private static final String OAUTH_SECRET = "RNzgT21uzzsb9T49eo1suqOIpVuLdx2yYAPahWSEs";
  private static final String OAUTH_SECRET = "e1dq7EeIKMyODCn2GRRLmOWIwmXuFBzHkK3T7MX1Y";
  private static final String OAUTH_CALLBACK_SCHEME = "1Android";
  private static final String OAUTH_CALLBACK_URL = OAUTH_CALLBACK_SCHEME + "://callback";
  private static final String TWITTER_USER = "info@nrgea.com";

Found at https://gist.github.com/996219

I AM using 1Android://callback and I configured the browser app with www.santiapps.com as the callback_URL.

In the manifest I have:

android scheme:1Android
android host:callback

But it still doesn't work :(
Posted on May 28, 2011
Photo Marko Gargenta
@MarkoGargenta
Member since Jan 19, 2007
Location: San Francisco
Why don't you try a callback similar to one I'm using? I'm not sure what restrictions are but that one does work.
Posted on May 28, 2011
Photo Marcio Valenzuela
Santiapps
Member since May 16, 2011
OK I got it working! Thank you so much. BTW, if you guys ever wish to come to Central America to give an Android Bootcamp lemme know!
Posted on May 30, 2011
Photo D-J Harrison
Senior Analyst Programmer
ISS
Member since May 30, 2011
Marko,
I guess this article is related to Chapter 6 of your book Learning Android, but I am not 100% sure. Ok, so the code in your book:

twitter = new Twitter("student", "password");
twitter.setAPIRootUrl("http://yamba.thenewcircle.com/api");

doesn't work because we can't call Twitter with userid/password. I get that. I also get we have to use OAuth or something similar. Oh, I also got where you commented above that OAuth was designed for the web, not Android.

But that's all I get. I am still at a loss on what you are telling us to do. Can you (or have you) written a clear, easy-to-understand replacement for the above two lines that walks us through this part of your book?

A step-by-step walk-through, just as you were doing the book, would greatly help us who are trying to follow your example.

Is all the code in MainActivity.java above supposed to replace the two lines in your book?! Please help.
Posted on May 30, 2011
Photo Marcio Valenzuela
Santiapps
Member since May 16, 2011
DJHarrison...These are 2 diffnt things. Oauth is for the twitter-api. The original marakana code is sufficient for yamba.thenewcircle.com "twitter-like"-api.

This OAuth code is geared to creating a twitter-client for android...whereas the Yamba tutorial is geared to creating a yamba-client for android.

So if what you want to do is create a twitter-client for android, the OAuth code presented here is basically the heart of the app. As you can see in MainActivity.java you have:

onCreate - required for setup
onNewIntent - for the new intent created
onClickAuthorize - for authorize button
onClickTweet - for tweet button
onClickGetStatus - for timeline button

class OAuthAuthorizeTask extends AsyncTask ... (not sure, kinda new 2 java) i guess its a class within a class...
with methods...
String doInBackground - which tries new intent and returns errors...
onPostExecute - which toasts to a job well done or not...

class RetrieveAccessTokenTask extends AsyncTask ... (again, i guess its a class within a class)...
with methods...
String doInBackground - which actually creates the twitter object and tries to post...i think...its kinda confusing
onPostExecute - which toasts to a job well done or not...

class GetStatusTask extends AsyncTask ... which gets the timeline i think...
with methods...
String doInBackground
onPostExecute

class PostStatusTask extends AsyncTask ...
String doInBackground ... success posting...
onPostExecute ... toasts

sorry if its a bit sketchy...as i said, im new to java and the classes inside the same file throw me off... im used to objC and a simpler way of coding every class in separate files...
Posted on May 31, 2011
Photo Marcio Valenzuela
Santiapps
Member since May 16, 2011
Marko

What would be the best way to import this MainActivity.java into our MyTwitter project? MyTwitter has a MyTwitter.java class which I believe is the actual MainActivity.java. I would have to import MainActivity.java and replace the MyTwitter.java class. And more importantly make sure all the connections from the newly imported MainActivity.java class are correctly linked to:

res/layout/main.xml
res/values/strings.xml
and the AndroidManifest.xml

files...

Does eclipse have a easy-way to do this?
Posted on Jun 6, 2011
Photo Kavitha Chandramohan
Software Engineer
Seven Networks
Member since Jun 6, 2011
Very useful example , thank you.. it worked like charm with api level 4 too :)
Posted on Jun 6, 2011
Photo Marcio Valenzuela
Santiapps
Member since May 16, 2011
Marko

I was telling you that I took your OAuth demo code and used it in the MyTwitter app code on your site.

What I did was comment out the Default Activity java code in MyTwitter.java and pasted in the MainActivity.java from the OAuth demo code. I fixed the editStatus EditTextView name and replaced the MyTwitter class references for the MainActivity class references and it all worked fine.

But then I got an error in DBHelper.java because of this:

DbHelper.java line 54...ret.put..."the method in type ContentValues is not Applicable for the arguments (String,BigInteger)"

This is because the method calls for a String,String and you are inserting a String and then a statusId which is an integer. How can I fix this?
Posted on Jun 9, 2011
Photo Harwinder Singh
AndroidDeveloper
CopperLabs
Member since Jun 9, 2011
hey Marko Gargenta, Actually I am following your tutorial to implement oauth... it working fine in Emulator.. but when I run it in device it show a toast OAuthCommunicationException.



error:


W/System.err( 1227): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: Received authentication challenge is null
W/System.err( 1227): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
W/System.err( 1227): at oauth.signpost.AbstractOAuthProvider.retrieveRequestToken(AbstractOAuthProvider.java:69)
W/System.err( 1227): at com.twitter.MainActivity$OAuthAuthorizeTask.doInBackground(MainActivity.java:114)
W/System.err( 1227): at com.twitter.MainActivity$OAuthAuthorizeTask.doInBackground(MainActivity.java:1)
W/System.err( 1227): at android.os.AsyncTask$2.call(AsyncTask.java:185)
W/System.err( 1227): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
W/System.err( 1227): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
W/System.err( 1227): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
W/System.err( 1227): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
W/System.err( 1227): at java.lang.Thread.run(Thread.java:1096)
W/System.err( 1227): Caused by: java.io.IOException: Received authentication challenge is null
W/System.err( 1227): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequestInternal(HttpURLConnectionImpl.java:1694)
W/System.err( 1227): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequest(HttpURLConnectionImpl.java:1649)
W/System.err( 1227): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:1374)
W/System.err( 1227): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:117)
W/System.err( 1227): at oauth.signpost.basic.HttpURLConnectionResponseAdapter.getStatusCode(HttpURLConnectionResponseAdapter.java:22)
W/System.err( 1227): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:178)
W/System.err( 1227): ... 9 more
Posted on Jun 19, 2011
Photo Giorgio Denegri
Student
Member since Jun 19, 2011
Marko, thank you for your example, it was really helpful. I just have a question, Why it doesn't work when I used the twitter APIs with https:// but it works with http://.I am a newbie so I really don't know why changing this made it worked.
Posted on Jun 30, 2011
Photo Sanoop Yadav
Student
Member since Apr 5, 2011
Hi All,


When I run the application on Emulator i got below error with the toast "OAuthCommunicationException".


06-30 21:27:04.029: WARN/System.err(690): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: https://api.twitter.com/oauth/request_token
06-30 21:27:04.029: WARN/System.err(690): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
06-30 21:27:04.034: WARN/System.err(690): at oauth.signpost.AbstractOAuthProvider.retrieveRequestToken(AbstractOAuthProvider.java:69)
06-30 21:27:04.034: WARN/System.err(690): at com.sanoop.MainActivity$OAuthAuthorizeTask.doInBackground(MainActivity.java:114)
06-30 21:27:04.054: WARN/System.err(690): at com.sanoop.MainActivity$OAuthAuthorizeTask.doInBackground(MainActivity.java:1)
06-30 21:27:04.054: WARN/System.err(690): at android.os.AsyncTask$2.call(AsyncTask.java:252)
06-30 21:27:04.064: WARN/System.err(690): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
06-30 21:27:04.075: WARN/System.err(690): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
06-30 21:27:04.075: WARN/System.err(690): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
06-30 21:27:04.075: WARN/System.err(690): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:574)
06-30 21:27:04.094: WARN/System.err(690): at java.lang.Thread.run(Thread.java:1020)
06-30 21:27:04.094: WARN/System.err(690): Caused by: java.io.FileNotFoundException: https://api.twitter.com/oauth/request_token
06-30 21:27:04.124: WARN/System.err(690): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:532)
06-30 21:27:04.124: WARN/System.err(690): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:283)
06-30 21:27:04.135: WARN/System.err(690): at oauth.signpost.basic.HttpURLConnectionResponseAdapter.getContent(HttpURLConnectionResponseAdapter.java:18)
06-30 21:27:04.135: WARN/System.err(690): at oauth.signpost.AbstractOAuthProvider.handleUnexpectedResponse(AbstractOAuthProvider.java:228)
06-30 21:27:04.155: WARN/System.err(690): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:189)


Help Me Please.
Posted on Jun 30, 2011
Photo Giorgio Denegri
Student
Member since Jun 19, 2011
http instead of https... that worked for me.
Posted on Jul 1, 2011
Photo Sanoop Yadav
Student
Member since Apr 5, 2011
Hi All,

Issue resolved, I used Client instead of Browser while registering the application on twitter.

It should be browser.

But as I see Facebook Application on my mobile it doesn't like a browser application.


Does Twitter, Facebook, yahoo IM, MSN IM all are should be registered as Browser if we want to use then in our applications?

Or there is another way to develop these kind of applications in Android?

Does the callback URL should be mine site URL or I can give another sites URL like http://www.google.co.in/ OR the callback URL can be same as the Social Network we are accessing like http://www.facebook.com/, http://twitter.com/ etc...


Any suggestion and help is appreciated.
Posted on Jul 7, 2011
Photo Kevin L
Student
Student
Member since Jul 7, 2011
Hi everyone,

Getting an "OAuthExpectationFailedException" after the callback redirects me back to my app.
In debug mode i see the message
"Request token or token secret not set in server reply. The service
provider you use is probably buggy".

What could be the issue?


Kevin L.
Posted on Aug 11, 2011
Photo Brajabasi Padhy
Samsung
Member since Aug 11, 2011
Hi Everyone,
I'm able to build the app.But while debuging facing this issue...

String token = prefs.getString("token", null);
String tokenSecret = prefs.getString("tokenSecret", null);
if (token != null && tokenSecret != null) {
// We have token, use it
mConsumer.setTokenWithSecret(token, tokenSecret);
// Make a Twitter object
oauthClient = new OAuthSignpostClient(OAUTH_KEY, OAUTH_SECRET, token, tokenSecret);
twitter = new Twitter(TWITTER_USER, oauthClient);
}
toklen and tokenSecret is returning NULL
Is it fine?
Not able to authenticate..
Thanks with regards,
Braj
Posted on Aug 16, 2011
Photo Leondria Barbee
No Organizaion
Member since Aug 16, 2011
Hello Everyone,

I'm having some trouble with a bug in this program. I'm able to get the program to run fine. However, after you authenticate the user, leave the text field empty and click on tweet, the app crashes. Please see screencast. If you have seen this before or know of a solution, Please post it here. I've tried several ways of fixing this issue but none of them worked.

Screencast:
http://screencast.com/t/VamOmYCXYXsa

Is this an active bug? :
https://bugs.launchpad.net/collectionista/+bug/760333
http://code.google.com/p/android/issues/detail?id=4684

Error Log:

08-16 16:24:30.654: ERROR/AndroidRuntime(348): FATAL EXCEPTION: AsyncTask #2
08-16 16:24:30.654: ERROR/AndroidRuntime(348): java.lang.RuntimeException: An error occured while executing doInBackground()
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at android.os.AsyncTask$3.done(AsyncTask.java:200)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.lang.Thread.run(Thread.java:1019)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): Caused by: java.lang.NullPointerException
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.lang.String$CaseInsensitiveComparator.compare(String.java:88)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.lang.String$CaseInsensitiveComparator.compare(String.java:70)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.TreeMap.find(TreeMap.java:277)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.TreeMap.findByObject(TreeMap.java:351)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.TreeMap.get(TreeMap.java:177)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.Collections$UnmodifiableMap.get(Collections.java:1324)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at winterwell.jtwitter.URLConnectionHttpClient.processError(URLConnectionHttpClient.java:366)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at winterwell.jtwitter.OAuthSignpostClient.post(OAuthSignpostClient.java:129)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at winterwell.jtwitter.Twitter.updateStatus(Twitter.java:3411)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at winterwell.jtwitter.Twitter.updateStatus(Twitter.java:3352)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at winterwell.jtwitter.Twitter.setStatus(Twitter.java:3088)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at com.leobee.yamba.StatusActivity$PostStatusTask.doInBackground(StatusActivity.java:225)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at com.leobee.yamba.StatusActivity$PostStatusTask.doInBackground(StatusActivity.java:1)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at android.os.AsyncTask$2.call(AsyncTask.java:185)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
08-16 16:24:30.654: ERROR/AndroidRuntime(348): ... 4 more





code:

Code:


package com.leobee.yamba;

import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import winterwell.jtwitter.OAuthSignpostClient;
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class StatusActivity extends Activity {
private static final String TAG = "OAuthDemo";
private static final String OAUTH_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXX";
private static final String OAUTH_SECRET = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
private static final String OAUTH_CALLBACK_SCHEME = "x-leobee-oauth-twitter";
private static final String OAUTH_CALLBACK_URL = OAUTH_CALLBACK_SCHEME
+ "://callback";
private static final String TWITTER_USER = "xxxxxxxxxxx@gmail.com";

private OAuthSignpostClient oauthClient;
private OAuthConsumer mConsumer;
private OAuthProvider mProvider;
private Twitter twitter;
SharedPreferences prefs;


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.status);
// mConsumer = new DefaultOAuthConsumer(OAUTH_KEY, OAUTH_SECRET);
mConsumer = new CommonsHttpOAuthConsumer(OAUTH_KEY, OAUTH_SECRET);
mProvider = new DefaultOAuthProvider(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize");

// Read the prefs to see if we have token
prefs = PreferenceManager.getDefaultSharedPreferences(this);
String token = prefs.getString("token", null);
String tokenSecret = prefs.getString("tokenSecret", null);
if (token != null && tokenSecret != null) {
// We have token, use it
mConsumer.setTokenWithSecret(token, tokenSecret);
// Make a Twitter object
oauthClient = new OAuthSignpostClient(OAUTH_KEY, OAUTH_SECRET, token,
tokenSecret);
twitter = new Twitter(TWITTER_USER, oauthClient);
}
}

/* Callback once we are done with the authorization of this app with Twitter. */
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, "intent: " + intent);

// Check if this is a callback from OAuth
Uri uri = intent.getData();
if (uri != null && uri.getScheme().equals(OAUTH_CALLBACK_SCHEME)) {
Log.d(TAG, "callback: " + uri.getPath());

String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
Log.d(TAG, "verifier: " + verifier);

new RetrieveAccessTokenTask().execute(verifier);
}

}

public void onClickAuthorize(View view) {
new OAuthAuthorizeTask().execute();

}

public void onClickTweet(View view) {

if (twitter == null) {
Toast.makeText(this, "Authenticate first", Toast.LENGTH_LONG).show();
return;
}

EditText status = (EditText) findViewById(R.id.status);
new PostStatusTask().execute(status.getText().toString());

}

public void onClickGetStatus(View view) {
if (twitter == null) {
Toast.makeText(this, "Authenticate first", Toast.LENGTH_LONG).show();
return;
}
new GetStatusTask().execute();
}

/* Responsible for starting the Twitter authorization */
class OAuthAuthorizeTask extends AsyncTask<Void, Void, String> {

@Override
protected String doInBackground(Void... params) {
String authUrl;
String message = null;
try {
authUrl = mProvider.retrieveRequestToken(mConsumer, OAUTH_CALLBACK_URL);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl));
startActivity(intent);
} catch (OAuthMessageSignerException e) {
message = "OAuthMessageSignerException";
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
message = "OAuthNotAuthorizedException";
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
message = "OAuthExpectationFailedException";
e.printStackTrace();
} catch (OAuthCommunicationException e) {
message = "OAuthCommunicationException";
e.printStackTrace();
}
return message;
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null) {
Toast.makeText(StatusActivity.this, result, Toast.LENGTH_LONG).show();
}
}
}

/* Responsible for retrieving access tokens from twitter */
class RetrieveAccessTokenTask extends AsyncTask<String, Void, String> {

@Override
protected String doInBackground(String... params) {
String message = null;
String verifier = params[0];
try {
// Get the token
Log.d(TAG, "mConsumer: " + mConsumer);
Log.d(TAG, "mProvider: " + mProvider);
mProvider.retrieveAccessToken(mConsumer, verifier);
String token = mConsumer.getToken();
String tokenSecret = mConsumer.getTokenSecret();
mConsumer.setTokenWithSecret(token, tokenSecret);

Log.d(TAG, String.format("verifier: %s, token: %s, tokenSecret: %s",
verifier, token, tokenSecret));

// Store token in prefs
prefs.edit().putString("token", token).putString("tokenSecret",
tokenSecret).commit();

// Make a Twitter object
oauthClient = new OAuthSignpostClient(OAUTH_KEY, OAUTH_SECRET, token,
tokenSecret);
twitter = new Twitter("MarkoGargenta", oauthClient);

Log.d(TAG, "token: " + token);
} catch (OAuthMessageSignerException e) {
message = "OAuthMessageSignerException";
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
message = "OAuthNotAuthorizedException";
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
message = "OAuthExpectationFailedException";
e.printStackTrace();
} catch (OAuthCommunicationException e) {
message = "OAuthCommunicationException";
e.printStackTrace();
}
return message;
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null) {
Toast.makeText(StatusActivity.this, result, Toast.LENGTH_LONG).show();
}
}
}

/* Responsible for getting Twitter status */
class GetStatusTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
return twitter.getStatus().text;
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(StatusActivity.this, result, Toast.LENGTH_LONG).show();
}
}

/* Responsible for posting new status to Twitter */
class PostStatusTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
try {
twitter.setStatus(params[0]);
return "Successfully posted: " + params[0];
} catch (TwitterException e) {
return "Error connecting to server.";
}
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(StatusActivity.this, result, Toast.LENGTH_LONG).show();
}

}
}
Posted on Sep 6, 2011
Photo Dan Shneider
SW Engineer
Pegasus Technologies
Member since Sep 6, 2011
Just an update:
Question#1 resolved.
The problem was that I didn't add launchMode="singleInstance" to the activity (in manifest xml).
So, each time is was called back, onCreate was called, and not onNewIntent.

Question #2 remains. any idea?

Thanks,
Dan

Dear Marko Gargenta,
I am trying, for the 1st time, to use twitter API on our apps. (We have facebook already)
What I need to ask are 2 questions:
Using your AMAZING demo, after changing (https to http) I'm able to authenticate and tweet. all is working as expected.
Using the same methods you have on my app, I can't. I always get OAuthCommunicationException.
I did add a new application to twitter account and got Consumer key & Consumer secret which I used in the code.
Can you please give a hint what am I doing wrong?

The 2nd question, can I upload a picture using the API? if so, how?

Thanks a lot, Dan
Posted on Nov 3, 2011
Photo Punit Gadenkanahalli
Software Engineer
TTS
Member since Nov 3, 2011
Location: Bangalore
[edit: THe below issue was solved. It was a matter of bad internet connection. Once I restarted the emulator, it worked past this error. To encounter the next error :P ]

I am trying to run the demo uploaded. I have done everything as mentioned. Infact I have been trying to integrate Twitter in my android app since four days. also when I created an app in Twitter developer page, there was no "browser" "application-type" ( I have seen many people talking about it).

I have tried with https and http both for the URLs. Still got the same error (error below).

I have been getting this error:

W/System.err( 1185): oauth.signpost.exception.OAuthCommunicationException: Communication with the service prov
ider failed: Host is unresolved: api.twitter.com:80
W/System.err( 1185): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
W/System.err( 1185): at oauth.signpost.AbstractOAuthProvider.retrieveRequestToken(AbstractOAuthProvider.jav
a:69)
W/System.err( 1185): at com.marakana.oauth.MainActivity$OAuthAuthorizeTask.doInBackground(MainActivity.java
:129)
W/System.err( 1185): at com.marakana.oauth.MainActivity$OAuthAuthorizeTask.doInBackground(MainActivity.java
:1)
W/System.err( 1185): at android.os.AsyncTask$2.call(AsyncTask.java:185)
W/System.err( 1185): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
W/System.err( 1185): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
W/System.err( 1185): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
W/System.err( 1185): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
W/System.err( 1185): at java.lang.Thread.run(Thread.java:1096)
W/System.err( 1185): Caused by: java.net.UnknownHostException: Host is unresolved: api.twitter.com:80
W/System.err( 1185): at java.net.Socket.connect(Socket.java:1038)
W/System.err( 1185): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpCo
nnection.java:62)
W/System.err( 1185): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpC
onnectionPool.java:88)
W/System.err( 1185): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHTT
PConnection(HttpURLConnectionImpl.java:927)
W/System.err( 1185): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connec
t(HttpURLConnectionImpl.java:909)
W/System.err( 1185): at oauth.signpost.basic.DefaultOAuthProvider.sendRequest(DefaultOAuthProvider.java:48)

W/System.err( 1185): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:177)


Please help me how to go about it.
Posted on Nov 3, 2011
Photo Punit Gadenkanahalli
Software Engineer
TTS
Member since Nov 3, 2011
Location: Bangalore
[edit: this issue was resolved by changing "https" URLs to "http". Excuse me for multiple posts]

Hi Kevin,

I am facing the same error.

" W/System.err( 487): oauth.signpost.exception.OAuthExpectationFailedException: Request token or token secret not set in server reply. The service provider you use is probably buggy. "

If you have solved the issue , could you please share the solution with me.
Posted on Nov 14, 2011
Photo Oanca Mihai
Home
Member since Nov 14, 2011
I have the same problem like Punit, "Communication with the service provider failed". I already used http, https, but no luck. I don't understand why when i am creating the application, there is no such thing as application type. I'm trying to make an android app that uses twitter(i used twitter4j, jtwitter, scribe), and i didn't succeded, on google there are a lot of useless old tutorials.
Posted on Nov 15, 2011
Photo Oanca Mihai
Home
Member since Nov 14, 2011
So the solution is to put a callback url to twitter app page, it doesn't matter what is that url. If you put that there it doesn't matter if you use https or http. Thanx Marakana.
Posted on Apr 11, 2012
Photo Selo T
Freelance
Member since Apr 3, 2012
Hi Guys,

This code is using winterwell.jtwitter.OAuthSignpostClient class which does not take place in the jtwitter-yamba.jar provided in Yamba source code.

How can i get it?

thanks
Posted on Jul 4, 2013
Photo Rahul Pandey
IT
Member since Jul 4, 2013
when you communicating with oauth make sure the device date should be cuurent data

Thoes who problem with http:// or https:// they can try
this example
https://github.com/rahulpandey/Android-Twitter-oauth-exmaple
I have use the twiiter4j library
Posted on Sep 4, 2013
Photo Nikita Gurwani
NotionInk.org
Member since Sep 4, 2013
hello
after running above code its giving me-

You have searched for androidmyapp//callback? oauth token = " something"&oauth verifier = "something"
did not find any results


Can any one help me why it is showing me like this?