Reputation: 191
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
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
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