最近接觸的項目要實現Twitter,Facebook,Email的分享功能。當然Android可以簡單的用Intent調用第三方App實現這些功能。但是如果需求變態需要你自己寫一個分享功能呢?
先介紹一下Twitter的分享:
Twiter這裏我使用了twitter4j-core-android-2.2.6.jar這個是給android用的twitter4j的精簡包,體積小。
授權(Oauth)流程如下:
1) 註冊申請Twitter的開發者,創建App,獲得開發者的Key和Secret,即consumer_key & consumer_secret
2) 用Http通過Twitter提供的Api url + 參數consumer_key & consumer_secret到Twitter的服務器獲取request_token
3) 用Http通過Twitter提供的Api url + 參數request_token到Twitter服務器請求授權
4) 授權確認後頁面跳轉到由你之前註冊時填寫的callback_url爲地址前綴的的一個新網址(頁面),並獲取到oauth_verifer
5) 最後,再發送request_token & oauth_verifer到Twitter服務器換取access_token & access_token_secret, 有了這兩個值就可以通過它們進行各種Twitter操作。
以上是授權的一個通用過程,但是在實現中需要考慮一些問題,因此有以下流程:
1\ 從手機的文件存儲中讀取access_token & access_token_secret,,如果沒有繼續2\,有就直接設置它們到twitter對象中,然後到5\
2\ 進行授權,前提是要已經設置consumer_key & consumer_secret到了twitter對象中,向服務器獲取request_token(代碼實現中是要求傳遞call_back_url作爲參數)
3\ 獲取到request_token後將request_token作爲參數傳遞並開啓一個有WebView的Activity,然後自己用瀏覽器處理獲取oauth_verifer,並將其作爲參數傳回給之前的那個Activity
這裏說一下用一個帶WebView 的Activity處理的好處,一個是在有多個第三方瀏覽器的時候直接用Intent會沒辦法關閉第三方瀏覽器,不過其實最關鍵的是我在使用系統自帶的瀏覽器的獲取oauth_verifierr時,雖然XML有寫回調數據的處理(<data android:scheme="http" android:host="app.com"),但是沒有效果,於是我就在webview 的 onPageFinished()回調方法中自己獲取它callback_url後面帶的oauth_verifer參數值
4\ 在之前的Activity裏用接收到的oauth_verifer繼續處理,向服務器獲取access_token & access_token_secret,並且設置到twitter對象中,並且把它存入文件
5\ 用twitter對象進行一些twitter操作
注意:在5\ 中操作時會遇到如果用戶撤銷了授權的一些情況,這個時候就會拋出異常,此時就需要從2\開始再一次進行授權。
關鍵的代碼:
在onCreate()裏初始化以及設置組件:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_twitter);
mPrefs = App.getInstance().getAppPrefs(); //獲得操作文件系統的對象
InitializeTwitter(); //初始化Twitter對象
Intent intent = getIntent();
if (intent != null) {
preview_url = intent.getStringExtra("preview_url"); //Intent傳過來的一個字符串,把它作爲推文
}
String accessToken = mPrefs.getTwitterAccessToken();
String accessTokenSecret = mPrefs.getTwitterAccessTokenSecret();
if (accessToken == null || accessTokenSecret == null) { //從文件系統裏讀取的access_token 和 access_token_secret的判斷
reOauth(); //驗證以及出問題的重複驗證都會用這個函數
} else {
twitter.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
}
close = (Button)findViewById(R.id.btn_close);
send = (Button)findViewById(R.id.btn_send);
content = (EditText)findViewById(R.id.edit_content); //在這個Activity上用於顯示推文內容
close.setOnClickListener(closeListener); //關閉,調用finish()
send.setOnClickListener(sendListner); //發佈推文
}
private void InitializeTwitter() {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(AppConstants.TWITTER_CONSUMER_KEY); //consumer_key
builder.setOAuthConsumerSecret(AppConstants.TWITTER_CONSUMER_SECRET); //consumer_secret
Configuration conf = builder.build();
twitter = new TwitterFactory(conf).getInstance();
twitter.setOAuthAccessToken(null);
}
private void reOauth() {
try {
twitter.setOAuthAccessToken(null);
requestToken = twitter.getOAuthRequestToken(AppConstants.TWITTER_CALLBACK_URL); //獲取requestToken
} catch (TwitterException e) {
Log.d("TEST", e.getMessage());
}
if (requestToken != null) {
Intent i = new Intent(this, WebsiteActivity.class);
i.putExtra(AppConstants.EXTRA_URL, requestToken.getAuthenticationURL());
startActivityForResult(i, TITTER_OAUTH); //開啓一個帶webview的Activity處理,名字爲WebsiteActivity
}
}
private class MyWebViewClient extends WebViewClient { //要求是可以點擊其他超練級繼續瀏覽網頁的,因此繼承WebViewClient實現
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) { //在網頁加載結束後,對callback_url帶回的參數進行獲取。並關閉這個activity
super.onPageFinished(view, url);
progressbar.setVisibility(View.GONE);
if (url != null && url.startsWith(AppConstants.TWITTER_CALLBACK_URL)) {
String oauthVerifer = Uri.parse(url).
getQueryParameter(AppConstants.TWITTER_OAUTH_VERIFIER);
Intent i = new Intent();
i.putExtra(AppConstants.TWITTER_OAUTH_VERIFIER, oauthVerifer);
setResult(RESULT_OK, i); //把獲取的oauth_verifer
finish();
}
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
progressbar.setVisibility(View.VISIBLE);
}
}
對返回的oauth_verifer進行處理,並與request_token一起去獲取access_token & access_token_secret:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("TEST", "Twitter onActivityResult()");
if (requestCode == TITTER_OAUTH) {
if (resultCode == Activity.RESULT_OK) {
oauthVerifier = data.getStringExtra(AppConstants.TWITTER_OAUTH_VERIFIER);
try {
AccessToken at = twitter.getOAuthAccessToken(requestToken, oauthVerifier);
String accessToken = at.getToken();
String accessTokenSecret = at.getTokenSecret();
twitter.setOAuthAccessToken(at); //這裏要設置access_token
mPrefs.setTwitterAccessToken(accessToken); //記得存入文件系統
mPrefs.setTwitterAccessTokenSecret(accessTokenSecret);
} catch (TwitterException e) {
Log.d("TEST", e.getMessage());
}
}
}
}
最後就可以用twitter發佈推文了,Send按鈕事件:
private View.OnClickListener sendListner = new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
twitter.updateStatus(content.getText().toString() + preview_url);
} catch (TwitterException e) {
reOauth(); //在用戶撤銷授權或者刪除app的時候,會拋出異常,這裏就可以再次重新授權
Log.d("TEST", e.getMessage());
}
}
};