Marc_V
Marc_V

Reputation: 191

Twitter api me callback not calling my app back

I'm developping an app that is authentifying to twitter using OAuth (via twitter api me). This is my code :

public final static String CALLBACK_URL = "twittappmarc://twitter";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    WebView webView = new WebView(this);
    setContentView(webView);

    WebViewOAuthDialogWrapper pageWrapper =
        new WebViewOAuthDialogWrapper(webView,CONSUMER_KEY,CONSUMER_SECRET,CALLBACK_URL,this);
    pageWrapper.setEnableCustomResultPages(false);
    pageWrapper.login();    
}

public void onAuthorize(Token accessToken) {
    Intent i = new Intent();
    i.setClass(this,FriendListActivity.class);
    i.putExtra("TOKEN_STRING", accessToken.toString());
    startActivity(i);
}
...

Though my code seems to be working (I can login and get the token back), I don't know how to deal with the callback URL. I thought my app would automaticaly be called back with the "onAuthorize" method, but this is what happens:

1 : I successfully connect to Twitter in my webview

2 : The webview tries and fails to load twittappmarc://twitter?%token%

3 : onAuthorize method is called with a correct token, launching my FriendListActivity

What should I do for step 2 not to happen anymore? Isn't my callback url correct? Should I use an intent filter to redirect the call of that url to my app? I tried many things without success...

Upvotes: 0

Views: 1008

Answers (2)

jfcogato
jfcogato

Reputation: 3439

Sunshirond idea, works perfect for me, and I made some changes in http://www.android10.org/index.php/articleslibraries/291-twitter-integration-in-your-android-application source code. The main activity to login and twitt will be something like that:

public class PrepareRequestTokenActivity extends Activity {

final String TAG = getClass().getName();

private OAuthConsumer consumer; 
private OAuthProvider provider;
private  WebView webView;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_webview);

    try {
        this.consumer = new CommonsHttpOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
        this.provider = new CommonsHttpOAuthProvider(Constants.REQUEST_URL,Constants.ACCESS_URL,Constants.AUTHORIZE_URL);
    } catch (Exception e) {
        Log.e(TAG, "Error creating consumer / provider",e);
    }

    Log.i(TAG, "Starting task to retrieve request token.");

    webView = (WebView) findViewById(R.id.mywebview);
    webView.setWebViewClient(new MyWebViewClient(getApplicationContext(), PreferenceManager.getDefaultSharedPreferences(this)));
    webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

    WebSettings webSettings = webView.getSettings();

    webSettings.setSavePassword(false);                
    webSettings.setSupportZoom(false);
    webSettings.setSaveFormData(false);
    webSettings.setJavaScriptEnabled(true);
    webSettings .setCacheMode(WebSettings.LOAD_NO_CACHE);
    try {
        final String url = provider.retrieveRequestToken(consumer, Constants.OAUTH_CALLBACK_URL);
        webView.loadUrl(url);
    }
    catch (Exception e) {
        webView.clearHistory();
        webView.clearFormData();
        webView.clearCache(true);
        finish();
    }        

}

private class MyWebViewClient extends WebViewClient {

    private Context context;
    private SharedPreferences prefs;

    public MyWebViewClient(Context context, SharedPreferences prefs) {
        this.context = context;
        this.prefs = prefs;
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.contains(Constants.OAUTH_CALLBACK_SCHEME)) {
            Uri uri = Uri.parse(url);
            new RetrieveAccessTokenTask(context,consumer,provider,prefs).execute(uri);
            finish();
            return true;
        }
        return false;
    }
}


public class RetrieveAccessTokenTask extends AsyncTask<Uri, Void, Void> {

    private Context context;
    private OAuthProvider provider;
    private OAuthConsumer consumer;
    private SharedPreferences prefs;

    public RetrieveAccessTokenTask(Context context, OAuthConsumer consumer,OAuthProvider provider, SharedPreferences prefs) {
        Log.d("hi there", "im gonna make the twitt");
        this.context = context;
        this.consumer = consumer;
        this.provider = provider;
        this.prefs=prefs;
    }


    /**
     * Retrieve the oauth_verifier, and store the oauth and oauth_token_secret 
     * for future API calls.
     */
    @Override
    protected Void doInBackground(Uri...params) {
        final Uri uri = params[0];
        final String oauth_verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);

        try {
            provider.retrieveAccessToken(consumer, oauth_verifier);

            final Editor edit = prefs.edit();
            edit.putString(OAuth.OAUTH_TOKEN, consumer.getToken());
            edit.putString(OAuth.OAUTH_TOKEN_SECRET, consumer.getTokenSecret());
            edit.commit();

            String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
            String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");

            consumer.setTokenWithSecret(token, secret);
            //context.startActivity(new Intent(context,AndroidTwitterSample.class));

            executeAfterAccessTokenRetrieval();

            Log.i(TAG, "OAuth - Access Token Retrieved");

        } catch (Exception e) {
            Log.e(TAG, "OAuth - Access Token Retrieval Error", e);
        }

        return null;
    }


    private void executeAfterAccessTokenRetrieval() {
        String msg = getIntent().getExtras().getString("tweet_msg");
        try {
            TwitterUtils.sendTweet(prefs, msg);
        } catch (Exception e) {
            Log.e(TAG, "OAuth - Error sending to Twitter", e);
        }
    }
}   

}

If you have some problems make it work, mail me... may I upload the projecto to google code.

Note- here is the XML for the webview:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<WebView
    android:id="@+id/mywebview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

Upvotes: 1

Marc_V
Marc_V

Reputation: 191

I found out the best way to do this is by overriding the shouldOverrideUrlLoading of your WebviewClient.

WebView webView = (WebView) findViewById(R.id.webview);
webView.setWebViewClient(new WebViewClient() {
    @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (url.contains(Const.CALLBACK_URL)) {
                Uri uri = Uri.parse(url);
                mIntent.setData(uri);
                setResult(RESULT_OK, mIntent);
                finish();
                return true;
            }
            return false;
        }
    });

Take care though, shouldOverrideUrlLoading will only be called if the url form is something like "string1://string2" where string1 and 2 are strings without special characters (example : myappname://callback).

Upvotes: 0

Related Questions