
Android で Twitter4J を使用し、Twitter の OAuth 処理を行うクラスを作成しました。
特徴としては、動的に WebView を作成し、コールバックページのフックをソースコードで記述しているため、
リソースファイルや AndroidManifest.xml への独自スキーマのための定義が不要であり、
本クラス(1ファイル)を導入するだけで認証できるようになります。
※もちろん AndroidManifest.xml への Activity の追加は必要です^^;
※Android 1.5 以降 + twitter4j-android-2.2.2 で確認済
使い方
- 呼び出し方法
OAuth画面をさせるには、自アプリ用のコールバック文字列、認証用文字列をインテントに設定して呼び出すだけ。
Intent intent = new Intent(this, OAuthActivity.class); intent.putExtra(OAuthActivity.CALLBACK, CALLBACK); intent.putExtra(OAuthActivity.CONSUMER_KEY, CONSUMER_KEY); intent.putExtra(OAuthActivity.CONSUMER_SECRET, CONSUMER_SECRET); startActivityForResult(intent, REQUEST_OAUTH);
- 結果の取得方法
認証結果は、呼び出し元のonActivityResult()でインテントにセットして返されますので、必要な情報を取得するだけ。
long userId = data.getLongExtra(OAuthActivity.USER_ID, 0); String screenName = data.getStringExtra(OAuthActivity.SCREEN_NAME); String token = data.getStringExtra(OAuthActivity.TOKEN); String tokenSecret = data.getStringExtra(OAuthActivity.TOKEN_SECRET);
OAuth 認証コード(一部)
さて、(何故か)ここでお題。。。
認証処理で必要な処理のうち、getOAuthRequestToken() と getOAuthAccessToken() メソッドは、
呼び出しに時間のかかる処理であり、メイン(UI)スレッドでは呼び出してはいけない処理です。
以下では、AsyncTask で実装しましたが、コードも長くなり、いささか気持ち悪いです。
他にも Thread + Handler などの実装方法が考えられますが、もっとスマートな書き方はないでしょうか?
もっといい書き方あるよ!という方は、Twitter で(ry...
※6/5追記:環境によってはshouldOverrideUrlLoading()でフックできない場合があるようです(謎)。
その場合、onPageStarted()で代替できますので、そちらをお使いください。。。
public class OAuthActivity extends Activity {
// Activity開始時のインテントパラメータ
public static final String CALLBACK = "callback";
public static final String CONSUMER_KEY = "consumer_key";
public static final String CONSUMER_SECRET = "consumer_secret";
// Activity終了時のインテントパラメータ
public static final String USER_ID = "user_id";
public static final String SCREEN_NAME = "screen_name";
public static final String TOKEN = "token";
public static final String TOKEN_SECRET = "token_secret";
private static final String OAUTH_VERIFIER = "oauth_verifier";
private WebView mWebView;
private String mCallback;
private Twitter mTwitter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setResult(Activity.RESULT_CANCELED);
// プログレス表示
requestWindowFeature(Window.FEATURE_PROGRESS);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
// Viewのセットアップ
mWebView = new WebView(this);
WebSettings webSettings = mWebView.getSettings();
webSettings.setSavePassword(false);
mWebView.setWebChromeClient(mWebChromeClient);
mWebView.setWebViewClient(mWebViewClient);
setContentView(mWebView);
// TwitterのOAuth認証画面で毎回ユーザ名、アカウントを入力させるために必要
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(false);
Intent intent = getIntent();
mCallback = intent.getStringExtra(CALLBACK);
String consumerKey = intent.getStringExtra(CONSUMER_KEY);
String consumerSecret = intent.getStringExtra(CONSUMER_SECRET);
if ((mCallback == null) || (consumerKey == null)
|| (consumerSecret == null)) {
finish();
}
mTwitter = new TwitterFactory().getInstance();
mTwitter.setOAuthConsumer(consumerKey, consumerSecret);
PreTask preTask = new PreTask();
preTask.execute();
}
// 前処理
public class PreTask extends AsyncTask<Void, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
setProgressBarIndeterminateVisibility(true);
}
@Override
protected String doInBackground(Void... params) {
String authorizationUrl = null;
try {
// 非同期処理が必要なメソッドの呼び出し
RequestToken requestToken = mTwitter.getOAuthRequestToken();
if (requestToken != null) {
authorizationUrl = requestToken.getAuthorizationURL();
}
} catch (TwitterException e) {
e.printStackTrace();
}
return authorizationUrl;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
setProgressBarIndeterminateVisibility(false);
if (result != null) {
mWebView.loadUrl(result);
} else {
finish();
}
}
}
private WebChromeClient mWebChromeClient = new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
setProgress(newProgress * 100);
}
};
private WebViewClient mWebViewClient = new WebViewClient() {
// 特定のページをフック
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
boolean result = true;
if ((url != null) && (url.startsWith(mCallback))) {
Uri uri = Uri.parse(url);
String oAuthVerifier = uri.getQueryParameter(OAUTH_VERIFIER);
PostTask postTask = new PostTask();
postTask.execute(oAuthVerifier);
} else {
result = super.shouldOverrideUrlLoading(view, url);
}
return result;
}
};
// 後処理
public class PostTask extends AsyncTask<String, Void, AccessToken> {
@Override
protected void onPreExecute() {
super.onPreExecute();
setProgressBarIndeterminateVisibility(true);
}
@Override
protected AccessToken doInBackground(String... params) {
AccessToken accessToken = null;
if (params != null) {
try {
// 非同期処理が必要なメソッドの呼び出し
accessToken = mTwitter.getOAuthAccessToken(params[0]);
} catch (TwitterException e) {
e.printStackTrace();
}
}
return accessToken;
}
@Override
protected void onPostExecute(AccessToken result) {
super.onPostExecute(result);
setProgressBarIndeterminateVisibility(false);
if (result != null) {
long userId = result.getUserId();
String screenName = result.getScreenName();
String token = result.getToken();
String tokenSecret = result.getTokenSecret();
Intent intent = new Intent();
intent.putExtra(USER_ID, userId);
intent.putExtra(SCREEN_NAME, screenName);
intent.putExtra(TOKEN, token);
intent.putExtra(TOKEN_SECRET, tokenSecret);
setResult(Activity.RESULT_OK, intent);
}
finish();
}
}
}































