title: Persistent OAuth using Android and Twitter4J
body: <p>So I am trying to get a grip around this <code>OAuth</code> for twitter using the <code>Twitter4J</code> library.</p>
  
  <p>I will give a little bit of background. </p>
  
  <p>I set up my Twitter developer account using the Browser method and callbacks (that I have set up as an intent-filter) in my <code>AndroidManifest.xml</code>.</p>
  
  <p>I have an activity that entirely handles my twitter authentication.</p>
  
  <pre><code>@Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  
      //set up the datahelper
      dh = new DataHelper(this, null);
      tae = dh.GetAuthenticationObject();
      setContentView(R.layout.main);
  }
  
  @Override
  protected void onResume() {
      super.onResume();
      selectOption(getIntent());
  }
  
  public void selectOption(Intent intent) {
      Uri uri = intent.getData();
      if (uri != null &amp;&amp; uri.toString().startsWith(CALLBACKURL) &amp;&amp; tae.hasBeenAuthenticatedTwitter()) {           
          completeAuth(intent);           
      } else {
          doOauth();
      }
  }
  
  private void doOauth() {
      try {
          consumer = new CommonsHttpOAuthConsumer(Enums.TWITTER_APPLICATION_KEY,
                  Enums.TWITTER_APPLICATION_SECTRET);
  
          provider = new DefaultOAuthProvider(
                  Enums.TWITTER_REQUEST_TOKEN_URL,
                  Enums.TWITTER_ACCESS_TOKEN_URL,
                  Enums.TWITTER_AUTHORIZE_URL);
  
          String authUrl = provider.retrieveRequestToken(
                  consumer, CALLBACKURL);
  
          tae.TwitterToken =  consumer.getToken();
          tae.TwitterTokenSecret = consumer.getTokenSecret();
          dh.SaveAuthenticationObject(tae);
  
          this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
                  .parse(authUrl)));
      } catch (Exception e) {
          Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
      }
  }
  
  /**
   * After use authorizes this is the function where we get back callbac with
   * user specific token and secret token. You might want to store this token
   * for future use.
   */
  
  public void completeAuth(Intent intent) {
      Uri uri = intent.getData();
      if (uri != null &amp;&amp; uri.toString().startsWith(CALLBACKURL)) {
  
          tae = dh.GetAuthenticationObject();
          String verifier = uri
                  .getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER);
          tae.TwitterVerifier = verifier;
          dh.SaveAuthenticationObject(tae);   
      }
  
      Intent settingsIntent = new Intent(this, com.undetowdevelopment.kontakt.Settings.class);
      settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
      settingsIntent.putExtra("REQUEST_CODE", Enums.REQUEST_CODE_TWITTER_LOGIN);
      settingsIntent.putExtra("RESULT_CODE", Activity.RESULT_OK);
      startActivity(settingsIntent);  
  }
  </code></pre>
  
  <p>This class does exactly what I expect. It opens up the Twitter authentication page, returns to the activity and I save the <code>Token &amp; Secret</code> to my Shared Preferences.</p>
  
  <p>My <code>AndroidManifest.xml</code> looks like: </p>
  
  <pre><code>    &lt;activity android:name=".TwitterSuccess" android:label="@string/app_name" android:launchMode="singleTop"&gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.VIEW"&gt;&lt;/action&gt;
              &lt;category android:name="android.intent.category.DEFAULT"&gt;&lt;/category&gt;
              &lt;category android:name="android.intent.category.BROWSABLE"&gt;&lt;/category&gt;
              &lt;data android:scheme="myapp" android:host="mainactivity"/&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
  </code></pre>
  
  <p>When my application launches however, I would like to check if the person is authenticated and not have to ask the user to authenticate again all the time.</p>
  
  <p>From all my activities, I have a method that returns a Twitter object that I would like to use to set the status or to get the friends of the user.</p>
  
  <p>I use the following method to do this:</p>
  
  <pre><code>public Twitter getTwitterObject()
  {
  
      AuthenticationEntity ae = GetAuthenticationObject();
  
      CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(Enums.TWITTER_APPLICATION_KEY, Enums.TWITTER_APPLICATION_SECTRET); 
      //Set the requestToken and the tokenSecret that you got earlier by calling retrieveRequestToken.
      consumer.setTokenWithSecret(ae.TwitterToken, ae.TwitterTokenSecret);
  
      //The provider object is lost, too, so instantiate it again.
      DefaultOAuthProvider provider = new DefaultOAuthProvider(
              Enums.TWITTER_REQUEST_TOKEN_URL,
              Enums.TWITTER_ACCESS_TOKEN_URL,
              Enums.TWITTER_AUTHORIZE_URL);
  
      //Now that's really important. Because you don't perform the retrieveRequestToken method at this moment, the OAuth method is not detected automatically (there is no communication with Twitter). So, the default is 1.0 which is wrong because the initial request was performed with 1.0a.
      provider.setOAuth10a(true);
  
  
      try {
          provider.retrieveAccessToken(consumer, ae.TwitterVerifier);
      } catch (Exception e) {
          Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_LONG).show();
          e.printStackTrace();
      }
  
      Twitter twitter = new TwitterFactory().getInstance();
      twitter.setOAuthConsumer(Enums.TWITTER_APPLICATION_KEY, Enums.TWITTER_APPLICATION_SECTRET);
      twitter.setOAuthAccessToken(new AccessToken(consumer.getToken(), consumer.getTokenSecret()));
      return twitter;
  
  }
  </code></pre>
  
  <p>Now this works fine if the user has just logged in, but if I launch the application again (which should not matter because I use only data from my static variables and Shared Preferences), I cannot authenticate and I get the following exception:</p>
  
  <pre><code>01-24 11:41:54.075: WARN/System.err(14612): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: http://twitter.com/oauth/access_token
  01-24 11:41:54.075: WARN/System.err(14612):     at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
  01-24 11:41:54.075: WARN/System.err(14612):     at oauth.signpost.AbstractOAuthProvider.retrieveAccessToken(AbstractOAuthProvider.java:97)
  01-24 11:41:54.075: WARN/System.err(14612):     at com.undetowdevelopment.kontakt.helpers.DataHelper.getTwitterObject(DataHelper.java:129)
  01-24 11:41:54.075: WARN/System.err(14612):     at com.undetowdevelopment.kontakt.Settings.checkTwitterStatus(Settings.java:118)
  01-24 11:41:54.075: WARN/System.err(14612):     at com.undetowdevelopment.kontakt.Settings.setUIComponents(Settings.java:60)
  01-24 11:41:54.075: WARN/System.err(14612):     at com.undetowdevelopment.kontakt.Settings.onCreate(Settings.java:39)
  01-24 11:41:54.075: WARN/System.err(14612):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1069)
  01-24 11:41:54.085: WARN/System.err(14612):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2751)
  01-24 11:41:54.085: WARN/System.err(14612):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2803)
  01-24 11:41:54.085: WARN/System.err(14612):     at android.app.ActivityThread.access$2300(ActivityThread.java:135)
  01-24 11:41:54.085: WARN/System.err(14612):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
  01-24 11:41:54.085: WARN/System.err(14612):     at android.os.Handler.dispatchMessage(Handler.java:99)
  01-24 11:41:54.085: WARN/System.err(14612):     at android.os.Looper.loop(Looper.java:144)
  01-24 11:41:54.085: WARN/System.err(14612):     at android.app.ActivityThread.main(ActivityThread.java:4937)
  01-24 11:41:54.085: WARN/System.err(14612):     at java.lang.reflect.Method.invokeNative(Native Method)
  01-24 11:41:54.085: WARN/System.err(14612):     at java.lang.reflect.Method.invoke(Method.java:521)
  01-24 11:41:54.085: WARN/System.err(14612):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
  01-24 11:41:54.085: WARN/System.err(14612):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
  01-24 11:41:54.085: WARN/System.err(14612):     at dalvik.system.NativeStart.main(Native Method)
  01-24 11:41:54.085: WARN/System.err(14612): Caused by: java.io.FileNotFoundException: http://twitter.com/oauth/access_token
  01-24 11:41:54.085: WARN/System.err(14612):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:1162)
  01-24 11:41:54.085: WARN/System.err(14612):     at oauth.signpost.basic.HttpURLConnectionResponseAdapter.getContent(HttpURLConnectionResponseAdapter.java:18)
  01-24 11:41:54.085: WARN/System.err(14612):     at oauth.signpost.AbstractOAuthProvider.handleUnexpectedResponse(AbstractOAuthProvider.java:228)
  01-24 11:41:54.085: WARN/System.err(14612):     at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:189)
  01-24 11:41:54.085: WARN/System.err(14612):     ... 18 more
  01-24 11:41:54.885: WARN/System.err(14612): http://api.twitter.com/1/account/verify_credentials.json?include_entities=falseRelevant discussions can be on the Internet at:
  01-24 11:41:54.885: WARN/System.err(14612):     http://www.google.co.jp/search?q=2486d84d or
  01-24 11:41:54.885: WARN/System.err(14612):     http://www.google.co.jp/search?q=0d00203c
  01-24 11:41:54.885: WARN/System.err(14612): TwitterException{exceptionCode=[2486d84d-0d00203c 175a68e8-9303e317], statusCode=-1, retryAfter=0, rateLimitStatus=null, version=2.1.12-SNAPSHOT(build: e7bec3eec13cedc774926ee24f4c5368d218c9d4)}
  01-24 11:41:54.885: WARN/System.err(14612):     at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:214)
  01-24 11:41:54.885: WARN/System.err(14612):     at twitter4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:75)
  01-24 11:41:54.885: WARN/System.err(14612):     at twitter4j.internal.http.HttpClientWrapper.get(HttpClientWrapper.java:103)
  01-24 11:41:54.885: WARN/System.err(14612):     at twitter4j.Twitter.verifyCredentials(Twitter.java:1397)
  01-24 11:41:54.885: WARN/System.err(14612):     at twitter4j.Twitter.getScreenName(Twitter.java:191)
  01-24 11:41:54.885: WARN/System.err(14612):     at com.undetowdevelopment.kontakt.Settings.checkTwitterStatus(Settings.java:120)
  01-24 11:41:54.885: WARN/System.err(14612):     at com.undetowdevelopment.kontakt.Settings.setUIComponents(Settings.java:60)
  01-24 11:41:54.885: WARN/System.err(14612):     at com.undetowdevelopment.kontakt.Settings.onCreate(Settings.java:39)
  01-24 11:41:54.885: WARN/System.err(14612):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1069)
  01-24 11:41:54.885: WARN/System.err(14612):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2751)
  01-24 11:41:54.885: WARN/System.err(14612):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2803)
  01-24 11:41:54.885: WARN/System.err(14612):     at android.app.ActivityThread.access$2300(ActivityThread.java:135)
  01-24 11:41:54.885: WARN/System.err(14612):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
  01-24 11:41:54.885: WARN/System.err(14612):     at android.os.Handler.dispatchMessage(Handler.java:99)
  01-24 11:41:54.885: WARN/System.err(14612):     at android.os.Looper.loop(Looper.java:144)
  01-24 11:41:54.885: WARN/System.err(14612):     at android.app.ActivityThread.main(ActivityThread.java:4937)
  01-24 11:41:54.885: WARN/System.err(14612):     at java.lang.reflect.Method.invokeNative(Native Method)
  01-24 11:41:54.885: WARN/System.err(14612):     at java.lang.reflect.Method.invoke(Method.java:521)
  01-24 11:41:54.885: WARN/System.err(14612):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
  01-24 11:41:54.885: WARN/System.err(14612):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
  01-24 11:41:54.885: WARN/System.err(14612):     at dalvik.system.NativeStart.main(Native Method)
  01-24 11:41:54.885: WARN/System.err(14612): Caused by: java.io.FileNotFoundException: http://api.twitter.com/1/account/verify_credentials.json?include_entities=false
  01-24 11:41:54.885: WARN/System.err(14612):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:1162)
  01-24 11:41:54.885: WARN/System.err(14612):     at twitter4j.internal.http.HttpResponseImpl.&lt;init&gt;(HttpResponseImpl.java:47)
  01-24 11:41:54.895: WARN/System.err(14612):     at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:178)
  01-24 11:41:54.895: WARN/System.err(14612):     ... 20 more
  01-24 11:41:54.995: WARN/InputManagerService(99): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@46113ee8 (uid=10060 pid=14093)
  </code></pre>
  
  <p>Like I mentioned, when I have just completed authentication, everything works fine, but If I launch my application again, I get this message.</p>
  
  <p>I am using an <code>HTC Incredible</code>, running Android 2.2. The application is being developed for Android 1.6+.</p>
  
  <p>Any comments or help will be greatly appreciated!</p>
  
  <p>Best,</p>
  
  <p>Ignus</p>