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

今天学习的是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()函数中执行

  1. 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

原文地址: http://my.eoe.cn/sfshine/archive/5601.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值