最近接触的项目要实现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());
}
}
};