今天学习的是OSC客户端的微博分享模块,界面如下
这个功能是我们在很多app上都需要实现的功能,这里涵盖了OAuthV2 OAuthV3 以及调用Webview进行分享三种方式 希望通过这个功能的学习可以举一反三.
首先是新浪微博.
osc使用的是新浪微博V2的分享模块,并对V2的sdk做了裁剪和改造,限于篇幅,这里不sdk的说明,请自行参考com.weibo.net包
新浪微博,授权过程的时序图如下
1- 2 在分享的activity: ScreenShotShare,点击按钮后将调用shareToSinaWeibo函数开始发送微博.这是执行getAccessInfo函数会获取在本地存储的有新浪微博认证的token 如果本地没有存储将返回null
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/**
* 分享到新浪微博
*/
private void shareToSinaWeibo(String content, final String imagePath) {
AppConfig cfgHelper = AppConfig.getAppConfig(this);
final AccessInfo access = cfgHelper.getAccessInfo();
final String shareMsg = content;
// 初始化微博
if (SinaWeiboHelper.isWeiboNull()) {
SinaWeiboHelper.initWeibo();
}
// 判断之前是否登陆过
if (access != null) {
SinaWeiboHelper.progressDialog = new ProgressDialog(this);
SinaWeiboHelper.progressDialog
.setProgressStyle(ProgressDialog.STYLE_SPINNER);
SinaWeiboHelper.progressDialog.setMessage(this
.getString(R.string.sharing));
SinaWeiboHelper.progressDialog.setCancelable(true);
SinaWeiboHelper.progressDialog.show();
new Thread() {
public void run() {
SinaWeiboHelper.setAccessToken(access.getAccessToken(),
access.getAccessSecret(), access.getExpiresIn());
SinaWeiboHelper.shareMessage(ScreenShotShare.this,
shareMsg, imagePath);
}
}.start();
} else {
SinaWeiboHelper
.authorize(ScreenShotShare.this, shareMsg, imagePath);
}
}
|
3.使用 SinaWeiboHelper 的 initWeibo()函数初始化微博对象
1 2 3 |
weibo = Weibo.getInstance();
weibo.setupConsumerConfig(CONSUMER_KEY, CONSUMER_SECRET);
weibo.setRedirectUrl(REDIRECT_URL);
|
这段代码对于做个微博开发的同学应该并不陌生
4.在第二步 .如果没有存储token 那么拿到的access为空,那么就开始调用SinaWeiboHelper的authorize函数进行授权的过程了.这时候就会弹出那个新新浪授权的webview了.
SinaWeiboHelper的authorize函数代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/**
* 微博授权 并 分享(文本、图片)
*/
public static void authorize(final Activity cont,final String shareMsg,final String shareImg)
{
context = cont;
if(isWeiboNull())
{
initWeibo();
}
weibo.authorize(cont, new WeiboDialogListener() {
@Override
public void onComplete(Bundle values) {
try
{
String token = values.getString(Weibo.TOKEN);
String expires_in = values.getString(Weibo.EXPIRES);
accessToken = new AccessToken(token, CONSUMER_SECRET);
accessToken.setExpiresIn(expires_in);
//保存AccessToken
AppConfig.getAppConfig(cont).setAccessInfo(accessToken.getToken(), accessToken.getSecret(), accessToken.getExpiresIn());
//微博分享
shareMessage(cont, shareMsg, shareImg);
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void onError(DialogError e) {
Toast.makeText(context,"授权失败 : " + e.getMessage(), Toast.LENGTH_LONG).show();
}
@Override
public void onCancel() {
//Toast.makeText(context, "取消授权", Toast.LENGTH_LONG).show();
}
@Override
public void onWeiboException(WeiboException e) {
Toast.makeText(context,"授权异常 : " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
|
5 系统会再次检查一下weibo对象是否为空,如果是那么再次初始化一下weibo对象,
6. 然后就真正打开sdk中那个带有webview的activity进行授权了.这个动作在weibo.authorize()函数中执行
- sdk中weibview的处理我们不做介绍了,下面看授权之后的回调,如果成功,就会执行inComplete函数:使用AppConfig保存token供下次使用 AppConfig可能会在以后的学习中介绍到.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Override
public void onComplete(Bundle values) {
try
{
String token = values.getString(Weibo.TOKEN);
String expires_in = values.getString(Weibo.EXPIRES);
accessToken = new AccessToken(token, CONSUMER_SECRET);
accessToken.setExpiresIn(expires_in);
//保存AccessToken
AppConfig.getAppConfig(cont).setAccessInfo(accessToken.getToken(), accessToken.getSecret(), accessToken.getExpiresIn());
//微博分享
shareMessage(cont, shareMsg, shareImg);
}
catch (Exception e)
{
e.printStackTrace();
}
}
|
9.拿到了token就调用获得的token发送微博了
这样,在下次再次进行发送的时候,执行到第三个步骤的时候, 就会使用从本地获取的token进行发送微博了.
这里有一点需要注意:根据自己以前的实践和对osc的测试,发现新浪token获取后会有些延时,在获取了token荣国立即使用者token很有可能导致失败.故此我的建议是授权后回到shareactivity 让用户点击发送 完成对文字的发送
然后是QQ微博.,QQ微博使用的是V1的接口,这里作者也是做sdk进行了改造和裁剪,时序图如下:
1-2在ShareScreenActivity中执行的代码很简单就是调用QQWeiboHelper2 的send函数
1 2 3 4 5 6 7 8 |
/**
* 分享到QQ微博
*/
@SuppressLint("NewApi")
private void shareToQQWeibo(String content, String imagePath) {
helper = new QQWeiboHelper2(this, content, imagePath);
helper.send();
}
|
3.send函数如下,我们看到,对于QQ微博的保存使用的是AppContext读取 序列化 到本地的Oauth对象,读取过程请参考介绍序列化缓存的文章.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/**
* 发送
* @throws NotCallBackException
*/
public void send() {
ac = (AppContext) context.getApplication();
// 获取凭证流程优先级: 内存 ->外存 ->网络
if (OAuthV1Cache == null) {
OAuthV1 oa = (OAuthV1) ac.readObject(OAUTH_CACHE_FILE);
if (oa == null) {
authenticate();
} else {
oAuth = OAuthV1Cache = oa;
sendMessage();
}
} else {
oAuth = OAuthV1Cache;
sendMessage();
}
}
|
4.如果为空就去打开Weiview进行授权了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/**
* 认证
*
* @throws Exception
*/
private void authenticate() {
oAuth = new OAuthV1(oauthCallback);
oAuth.setOauthConsumerKey(APP_KEY);
oAuth.setOauthConsumerSecret(APP_SECRET);
OAuthV1Client.getQHttpClient().shutdownConnection();
OAuthV1Client.setQHttpClient(new QHttpClient());
new Thread() {
@Override
public void run() {
Message msg = mHandler.obtainMessage(REQUEST);
try {
msg.obj = OAuthV1Client.requestToken(oAuth);
mHandler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
|
5-11 经过一系列的初始化后, 应用想QQ服务器发送异步请求获取未授权的Request Token ,并发送消息
1 2 3 |
msg.obj = OAuthV1Client.requestToken(oAuth);
mHandler.sendMessage(msg);
|
12 如果成功拿到了request token机会 跳转到一个含有WebView的Activity进行授权:
1 2 3 4 5 6 7 8 9 10 11 12 |
case REQUEST:
oAuth = (OAuthV1) msg.obj;
if (oAuth.getStatus() == 1) {
UIHelper.ToastMessage(context, "Request Token 授权不通过");
} else {
Intent intent = new Intent(context,
OAuthV1AuthorizeWebView.class);
intent.putExtra("oauth", oAuth);
context.startActivityForResult(intent,
AUTH_VIEW_REQUEST_CODE);
}
break;
|
13 其实V1的授权处理比较简单,就是使用WebViewClient对象处理一下webview载入的url
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
WebViewClient client = new WebViewClient()
{
/**
* 回调方法,当页面开始加载时执行
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.i(TAG, "WebView onPageStarted...");
Log.i(TAG, "URL = " + url);
if (url.indexOf("checkType=verifycode") != -1) {
int start=url.indexOf("checkType=verifycode&v=")+23;
String verifyCode=url.substring(start, start+6);
oAuth.setOauthVerifier(verifyCode);
Intent intent = new Intent();
intent.putExtra("oauth", oAuth);
setResult(RESULT_CODE, intent);
view.destroyDrawingCache();
finish();
}
super.onPageStarted(view, url, favicon);
}
};
webView.setWebViewClient(client);
}
|
14.我们知道,在授权的Activity finish后会调用ScreenShareActivity的onActivityResult回调,代码如下
1 2 3 4 5 6 7 8 9 |
/**
* 认证页回调
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (helper != null) {
helper.onAuthorizeWebViewReturn(requestCode, resultCode, data);
}
}
|
原理来时又调用进入了QQAuthHelper2的onAuthorizeWebViewReturn函数进行处理,主要功能是
使用授权后的Request Token换取Access Token
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public void onAuthorizeWebViewReturn(int requestCode, int resultCode,
Intent data) {
isCallBack = true;
if (requestCode == AUTH_VIEW_REQUEST_CODE) {
if (resultCode == OAuthV1AuthorizeWebView.RESULT_CODE) {
oAuth = (OAuthV1) data.getExtras().getSerializable("oauth");
if (oAuth.getStatus() == 2) {
UIHelper.ToastMessage(context, "获取验证码失败");
} else {
new Thread() {
@Override
public void run() {
Message msg = mHandler.obtainMessage(ACCESS);
try {
msg.obj = OAuthV1Client.accessToken(oAuth);
mHandler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
}
}
}
|
成功拿到accesstoken,就会发送消息通知AppContext把获取到的oauth保存到本地
1 2 3 4 5 6 7 8 9 10 |
case ACCESS:
oAuth = (OAuthV1) msg.obj;
if (oAuth.getStatus() == 3) {
UIHelper.ToastMessage(context, "Access失败");
} else {
OAuthV1Cache = oAuth;
ac.saveObject(oAuth, OAUTH_CACHE_FILE);
QQWeiboHelper2.this.sendMessage();
}
break;
|
下一次发送QQ微博,就可以直接读取Oauth对象发送啦!
最后是使用网页形式发表QQ微博
这个最简单,其实就是拼接新闻标题和地址,然后调用浏览器,代码如下 这个也有它的优点,开发成本低,稳定性高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class QQWeiboHelper {
private static final String Share_URL = "http://share.v.t.qq.com/index.php?c=share&a=index";
private static final String Share_Source = "OSChina";
private static final String Share_Site = "OSChina.net";
private static final String Share_AppKey = "96f54f97c4de46e393c4835a266207f4";
/**
* 分享到腾讯微博
* @param activity
* @param title
* @param url
*/
public static void shareToQQ(Activity activity,String title,String url){
String URL = Share_URL;
try {
URL += "&title=" + URLEncoder.encode(title, HTTP.UTF_8) + "&url=" + URLEncoder.encode(url, HTTP.UTF_8) + "&appkey=" + Share_AppKey + "&source=" + Share_Source + "&site=" + Share_Site;
} catch (Exception e) {
e.printStackTrace();
}
Uri uri = Uri.parse(URL);
activity.startActivity(new Intent(Intent.ACTION_VIEW, uri));
}
}
|
声明:eoe文章著作权属于作者,受法律保护,转载时请务必以超链接形式附带如下信息
原文作者: sfshine