譯者註:原文中使用Twitter4j3.0.3,由於官方api的不斷更新,該版本使用起來會有問題,就像原文評論當中提到的nullpointerexception。我測試最新的4.0.1沒有問題,我會將該壓縮包的附在文章最後。
------------------------------------------------------------------------------------------------------------------------------------------
接入社交網路沒準兒會讓你的應用程式顯得別具一格。今天我將和大家分享一個在Android應用中接入Twitter的demo。demo當中我們使用oAuth協議讓使用者對Twitter授權,如果授權成功,使用者可以通過我們的demo發布tweet。首先你得在Twitter上面註冊一個應用,開啟https://dev.twitter.com/apps,登入並建立一個應用如所示:
由於我們將要在android應用當中整合Twitter,所以callback URL你大可以隨便填寫,當然,你的應用首頁會是一個不錯的主意。然後到設定頁面修改許可權為“Read, Write and Access direct messages”,具體路徑為“Application Type –> Access section”。這些選項必須啟用,這樣你的手機才可以直接發布訊息。請千萬確認剛剛的設定確實已經成功,因為我設定了3次才搞定,傷不起。
如果你讀過我的上一篇博文“Google Cloud Messaging, ASP.NET Web Api and Android client”,你就會知道我們需要一個key來完成一系列的接入工作。Twitter的工作方式也非常類似,我們也需要一個key,你懂的。那麼到applications –> Details 下面找到你的Consumer key和secret,記下來,待會兒你就知道怎麼回事了。
(譯者註:我在測試的時候看到的是api key和api secret,進入你建立的應用之後,你可以在api keys選項卡下面看到這些內容。
)
好的,現在就是萬事具備,只欠東風了。你可以將Twitter的api封裝成一個Library,不過為了節省時間,我決定使用http://twitter4j.org/en/提供的開源庫Twitter4j來調用Twitter的api。Twitter4j並不是官方Library,所以做好思想準備哈。
With Twitter4J, you can easily integrate your Java application with the Twitter service.
Twitter4J is featuring:
? 100% Pure Java – works on any Java Platform version 5 or later
? Android platform and Google App Engine ready
? Zero dependency : No additional jars required
? Built-in OAuth support
? Out-of-the-box gzip support
? 100% Twitter API 1.1 compatible (From twitter4j.org)
下載,並把Twitterrj-core-3.0.3.jar拷到libs目錄下面(譯者:你需要把它引入你的buildpath,不過目測eclipse可以自動幫你把這件事搞定)。我們只是想發布一個tweet,所以core Library就足夠了,如果你有更多的需求,請看Twitter4j的其他jar包。
我們的demo只有兩個簡單的activity,MainActivity只有一個按鈕“Log in to Twitter”
另一個是TwitterActivity,這個Activity是用來發tweet的。
在主介面當中,當你啟動你的app,程式會檢查你的網路可用性(譯者:其實國內還需要科學上網,你懂的),並且檢查你的consumer key和secret。
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); if (!OSUtil.IsNetworkAvailable(getApplicationContext())) { AlertMessageBox.Show(MainActivity.this, Internet connection, A valid internet connection can't be established, AlertMessageBox.AlertMessageBoxIcon.Info); return; } if (StringUtil.isNullOrWhitespace(ConstantValues.TWITTER_CONSUMER_KEY) || StringUtil.isNullOrWhitespace(ConstantValues.TWITTER_CONSUMER_SECRET)) { AlertMessageBox.Show(MainActivity.this, Twitter oAuth infos, Please set your twitter consumer key and consumer secret, AlertMessageBox.AlertMessageBoxIcon.Info); return; } initializeComponent();}還要給許可權:
如果前面的檢查一切ok,你就可以看到“login with Twitter”的按鈕,點擊這個按鈕時,程式會檢查使用者是否已經登入授權,如果是,就直接跳轉到TwitterActivity,你就可以發tweet了;如果不是,對不起,請授權先。授權時會啟動瀏覽器(或者一個具有瀏覽器功能的頁面),使用者在該頁面中登入授權,成功之後則會轉回TwitterActivity,後面的事兒你都知道了。
Login with Twitter的click listener長得就像這個樣子:
private View.OnClickListener buttonLoginOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); if (!sharedPreferences.getBoolean(ConstantValues.PREFERENCE_TWITTER_IS_LOGGED_IN,false)) { new TwitterAuthenticateTask().execute(); } else { Intent intent = new Intent(MainActivity.this, TwitterActivity.class); startActivity(intent); } }};上面的代碼其實先檢查程式的內部設定(也就是Sharedpreferences),如果PREFERENCE_TWITTER_IS_LOGGED_IN已經有值,說明程式已經授權成功了。如果沒有設定,使用者就需要先授權,這個過程需要執行TwitterAuthenticateTask()。
class TwitterAuthenticateTask extends AsyncTask { @Override protected void onPostExecute(RequestToken requestToken) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(requestToken.getAuthenticationURL())); startActivity(intent); } @Override protected RequestToken doInBackground(String... params) { return TwitterUtil.getInstance().getRequestToken(); }}TwitterAuthenticateTask會建立request token,並從中獲得授權頁面的地址。請注意開啟Twitter授權連結的intent的構造,它需要一個Action叫做Intent.ACTION_VIEW。
(關於ACTION_VIEW的詳細內容請參見Android api)
That is an activity action to display the data to the user. This is the most common action performed on data — it is the generic action you can use on a piece of data to get the most reasonable thing to occur. For example, when used on a contacts entry it will view the entry; when used on a mailto: URI it will bring up a compose window filled with the information supplied by the URI; when used with a tel: URI it will invoke the dialer (From Google).
在我們的程式當中,瀏覽器將會處理這個請求。(譯者:其實我們可以自己實現一個webview,然後把url傳給這個webview來完成這個工作。)
點擊授權應用(Authorize app),你將需要輸入使用者名稱和密碼。登入,如果成功,Twitter將會跳回你的app;如果不成功,對不起,成人了(哈哈,原文不是這麼說的)。
看起來非常簡單。不過request code是如何產生的,以及Twitter又是怎麼知道要跳轉到哪個Activity的呢?接著看代碼。在TwitterUtil.class當中,你就會看到我用單例模式完成了所有的工作,比如setOAuthConsumerKey,setOAuthConsumerSecret以及getRequestToken。。。
public final class TwitterUtil { private RequestToken requestToken = null; private TwitterFactory twitterFactory = null; private Twitter twitter; public TwitterUtil() { ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); configurationBuilder.setOAuthConsumerKey(ConstantValues.TWITTER_CONSUMER_KEY); configurationBuilder.setOAuthConsumerSecret(ConstantValues.TWITTER_CONSUMER_SECRET); Configuration configuration = configurationBuilder.build(); twitterFactory = new TwitterFactory(configuration); twitter = twitterFactory.getInstance(); } public TwitterFactory getTwitterFactory() { return twitterFactory; } public void setTwitterFactory(AccessToken accessToken) { twitter = twitterFactory.getInstance(accessToken); } public Twitter getTwitter() { return twitter; } public RequestToken getRequestToken() { if (requestToken == null) { try { requestToken = twitterFactory.getInstance().getOAuthRequestToken(ConstantValues.TWITTER_CALLBACK_URL); } catch (TwitterException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } return requestToken; } static TwitterUtil instance = new TwitterUtil(); public static TwitterUtil getInstance() { return instance; } public void reset() { instance = new TwitterUtil(); }}這個類是唯一需要你設定Consumer Key和Consumer Secret的地方。callback URL也是必須的,因為Twitter正是通過它在認證成功之後跳轉指定的Activity的。在我的demo當中,我希望能夠跳到TwitterActivity當中,所以TWITTER_CALLBACK_URL的值就像這個樣子:
public static String TWITTER_CALLBACK_URL = oauth://com.hintdesk.Twitter_oAuth;
咦,這看起來也跟TwitterActivity沒得撒子關係嘛。對的,活還沒有幹完呢。在AndroidManifest.xml當中:
我們聲稱TwitterActivity可以被瀏覽器以“oauth://com.hintdesk.Twitter_oAuth”這樣的資料格式喚起。所以認證成功結束之後,後面的事兒你們又都知道了。當TwitterActivity被喚起之後,你一定迫不及待的要發tweet了。呃,別著急,接著幹活----不過只需要再堅持一下,當TwitterActivity啟動之後,從intent當中拿到access token之後你就可以發tweet了。
private void initControl() { Uri uri = getIntent().getData(); if (uri != null && uri.toString().startsWith(ConstantValues.TWITTER_CALLBACK_URL)) { String verifier = uri.getQueryParameter(ConstantValues.URL_PARAMETER_TWITTER_OAUTH_VERIFIER); new TwitterGetAccessTokenTask().execute(verifier); } else new TwitterGetAccessTokenTask().execute();}如果有了access token,果斷開始發tweet:
if (!StringUtil.isNullOrWhitespace(accessTokenString) && !StringUtil.isNullOrWhitespace(accessTokenSecret)) { AccessToken accessToken = new AccessToken(accessTokenString, accessTokenSecret); twitter4j.Status status = TwitterUtil.getInstance().getTwitterFactory().getInstance(accessToken).updateStatus(params[0]); return true;}這個access token只有在Twitter授權成功之後,並跳轉到我們的app之後才可以使用。不過一旦你拿到這個access token,你就可以把它存起來,並一直使用而不再需要任何授權了。
try { AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, params[0]); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(ConstantValues.PREFERENCE_TWITTER_OAUTH_TOKEN, accessToken.getToken()); editor.putString(ConstantValues.PREFERENCE_TWITTER_OAUTH_TOKEN_SECRET, accessToken.getTokenSecret()); editor.putBoolean(ConstantValues.PREFERENCE_TWITTER_IS_LOGGED_IN, true); editor.commit(); return twitter.showUser(accessToken.getUserId()).getName();} catch (TwitterException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.}params[0]就是“oauth_verifier”的值。你可以在之前給出的initControl函數當中看到。
好的,非常完美。
希望這個demo能夠協助你的應用接入Twitter並使你拓展出更多更豐富的功能。
源碼代碼:“Connect to Twitter in Android Phone“
------------------------------------------------------------------------------------------------------------------------------------
哇,翻譯結束。話說自從去年做完科技新聞的翻譯之後就再也沒幹過這種事兒了,我並不享受翻譯這個過程,不過我覺得好的文章有必要分享給大家。
另外,由於原文所用的Twitter4j3.0.3似乎已經過時,所以我附上我用的4.0.1的:http://pan.baidu.com/s/1o6jVXGm
或到Twitter4j的官網瞅瞅:http://twitter4j.org/en/index.html (需要科學上網哦~)