Android开源中国客户端学习 微博分享模块 <8>

今天学习的是OSC客户端的微博分享模块,界面如下

Android开源中国客户端学习 微博分享模块 <8>_第1张图片

这个功能是我们在很多app上都需要实现的功能,这里涵盖了OAuthV2 OAuthV3 以及调用Webview进行分享三种方式 希望通过这个功能的学习可以举一反三.

首先是新浪微博.

osc使用的是新浪微博V2的分享模块,并对V2的sdk做了裁剪和改造,限于篇幅,这里不sdk的说明,请自行参考com.weibo.net包

新浪微博,授权过程的时序图如下

Android开源中国客户端学习 微博分享模块 <8>_第2张图片

1- 2 在分享的activity:  ScreenShotShare,点击按钮后将调用shareToSinaWeibo函数开始发送微博.这是执行getAccessInfo函数会获取在本地存储的有新浪微博认证的token  如果本地没有存储将返回null

代码如下

/**
	 * 分享到新浪微博
	 */
	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()函数初始化微博对象

	weibo = Weibo.getInstance();
    	weibo.setupConsumerConfig(CONSUMER_KEY, CONSUMER_SECRET);
		weibo.setRedirectUrl(REDIRECT_URL);
这段代码对于做个微博开发的同学应该并不陌生

4.在第二步 .如果没有存储token 那么拿到的access为空,那么就开始调用SinaWeiboHelper的authorize函数进行授权的过程了.这时候就会弹出那个新新浪授权的webview了.

SinaWeiboHelper的authorize函数代码如下

/**
	 * 微博授权 并 分享(文本、图片)
	 */
	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()函数中执行

7. sdk中weibview的处理我们不做介绍了,下面看授权之后的回调,如果成功,就会执行inComplete函数:使用AppConfig保存token供下次使用 AppConfig可能会在以后的学习中介绍到.

	@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进行了改造和裁剪,时序图如下:

Android开源中国客户端学习 微博分享模块 <8>_第3张图片


1-2在ShareScreenActivity中执行的代码很简单就是调用QQWeiboHelper2 的send函数

/**
	 * 分享到QQ微博
	 */
	@SuppressLint("NewApi")
	private void shareToQQWeibo(String content, String imagePath) {
		helper = new QQWeiboHelper2(this, content, imagePath);
		helper.send();
	}
3.send函数如下,我们看到,对于QQ微博的保存使用的是AppContext读取 序列化 到本地的Oauth对象,读取过程请参考介绍序列化缓存的文章.
/**
	 * 发送
	 * @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进行授权了:
	/**
	 * 认证
	 * 
	 * @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 ,并发送消息

msg.obj = OAuthV1Client.requestToken(oAuth);

mHandler.sendMessage(msg);

12 如果成功拿到了request token机会 跳转到一个含有WebView的Activity进行授权:

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
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回调,代码如下
/**
	 * 认证页回调
	 */
	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

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保存到本地

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微博

这个最简单,其实就是拼接新闻标题和地址,然后调用浏览器,代码如下 这个也有它的优点,开发成本低,稳定性高

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));	
	}
}
Android开源中国客户端学习 微博分享模块 <8>_第4张图片




你可能感兴趣的:(Android开源中国客户端学习 微博分享模块 <8>)