QQ原生SDK第三方登录

在新进的项目中,原先使用SharedSDK做第三方登录。在近期的数据统计分析中,发现会存在获取openid成功,而获取QQ用户信息不成功的情形。除却在获取信息失败情形下添加条件拦截外,使用QQ SDK直接实现第三方登录是另一个选择。


一、资源查看与下载

度娘还是很好用的啦,信息渠道的扩展,极大地缩小了信息搜索的难度,增加了信息获取的公平性。

这里是QQ官方文档,用于引导开发者使用并达到功能实现。

这篇博客描述也是相当详细


二、功能实现

1,官方渠道注册

保存并获取APPID。

在新建项目中,导入下载的QQ 登录注册等相关jar包。

ps:QQ sdk 在3.2.1版本中添加基础包,有最基本的功能。【正在完善APP中只需要登录功能,遂换成基础包】


2,项目代码实现  -- 清单文件添加权限

   <!-- QQ登录授权所需权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

3,项目代码实现  -- 声明Activity

<!-- 注册SDKActivity -->
        <activity
            android:name="com.tencent.tauth.AuthActivity"
            android:launchMode="singleTask"
            android:noHistory="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="tencentAppID" /> <!-- 开放平台获取的APPID -->
            </intent-filter>
        </activity>
        <activity android:name="com.tencent.connect.common.AssistActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:screenOrientation="portrait"/>
ps:有些博客中没有声明AssistActivity,会导致创建Tencent对象为空的情形。

AppID为之前官方渠道注册所得,前面tencent字符串不可省不可改。

4,项目代码实现 ---  IUiListener接口实现

/**
 * qq登录监听器
 */

public class BaseUiListener implements IUiListener {

    protected void doComplete(Object values) {

    }

    @Override
    public void onComplete(Object response) {
        doComplete(response);
    }

    @Override

    public void onError(UiError e) {


    }

    @Override

    public void onCancel() {


    }

}
doComplete()方法在不同版本中传参可能不一样,并不影响使用。另一种传参为JsonObject。在实际的数据解析中,都会转换成为JSonObject从而获取需要的值。

5,项目代码实现 ---  创建Tencent实例

mTencent = Tencent.createInstance("AppID", this.getApplicationContext());


AppID为QQ官方注册所得,此处不添加其他任何字符串。
当清单文件没有AssistActivity声明,会导致获取对象为空。


6,项目代码实现 ---  登录事件触发

在页面实现的QQ点击进行第三方登陆的onClick()事件下添加:

                if (!mTencent.isSessionValid()) {
                       mTencent.login(this, "all", new BaseUiListener());
                }

7,项目代码实现 ---  回调监听

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (mTencent != null) {
            mTencent.handleLoginData(data, new BaseUiListener() {
                @Override
                protected void doComplete(Object values) {
                    String expires_in = "";
                    try {
                        qq_id = new JSONObject(values.toString()).getString("openid");
                        qq_token = new JSONObject(values.toString()).getString("access_token");
                        expires_in = new JSONObject(values.toString()).getString("expires_in");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

		    //依据回调回来的值修改原有默认值
                    mTencent.setOpenId(qq_id);
                    mTencent.setAccessToken(qq_token, expires_in);


                    QQToken qqToken = mTencent.getQQToken();
                    UserInfo info = new UserInfo(LoginMainActivity.this, qqToken);

		    //获取用户基本信息
                    info.getUserInfo(new BaseUiListener() {
                        @Override
                        protected void doComplete(Object values) {
                            try {
                                JSONObject jsonObject = new JSONObject(values.toString());

                                qq_name = jsonObject.getString("nickname");
                                qq_icon = jsonObject.getString("figureurl_qq_2");

                                /**
                                 * 增加QQ信息获取不完整拦截
                                 */
                                if (qq_name == null || qq_name.length() <= 0
                                        || qq_icon == null || qq_icon.length() <= 0
                                        || qq_id == null || qq_id.length() <= 0) {
                                    CustomProgressDialog.getInstance().dismiss();
                                    ToastView.showToast(LoginMainActivity.this, R.string.network_bad, ToastView.LENGTH_SHORT);//工具类,展示信息获取不完整
                                    return;
                                }

                    		//登录到客户端服务器

                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            });
        }
    }
注意:

(1)QQToken qqToken = mTencent.getQQToken();

                  获取前需要依据返回值设置数据,否则在之后的用户信息获取下会出现传参错误。


(2)用户信息获取的方法模式封装好

                 info.getUserInfo(new BaseUiListener() {});回调方法里面处理详细细节


        (3)获取到用户信息,openid之后,需要与客户端本身的服务器关联,实现真正的登录。


三、细节注意

1,APPID的两处使用,清单文件中携带tencent的字符串,代码中获取Tencent对象不加任何其他字符;

2,获取用户信息前,需要重新设置Tencent对象的值;

3,mTencent.isSessionValid()是否使用:

(1)使用:需要在和APP登录成功后,注销掉QQ登录,使其失效。否则会出现APP退出再进行登录无效。

【原因:QQ已经是登陆状态,还没有失效,下次不会重新获取,触发登录流程】

mTencent.logout(this);
能够注销登录。

(2)不使用

每次点击事件都相当于触发登录事件,走登录流程。

客户端会有连续快速点击,需要做快速点击防止!

4,无QQ客户端添加拦截

在客户端处理没有QQ客户端拦截,不允许登录或者提示安装QQ客户端再登录。否则会有:WebAuthorizeActivity错误:

java.lang.NoSuchMethodError: cn.sharesdk.framework.authorize.e.disableScreenCapture
	at cn.sharesdk.framework.authorize.e.onCreate(WebAuthorizeActivity.java:125)
	at com.mob.tools.MobUIShell.onCreate(MobUIShell.java:89)
	at android.app.Activity.performCreate(Activity.java:5350)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2332)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2430)
	at android.app.ActivityThread.access$800(ActivityThread.java:151)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342)
	at android.os.Handler.dispatchMessage(Handler.java:110)
	at android.os.Looper.loop(Looper.java:193)
	at android.app.ActivityThread.main(ActivityThread.java:5334)
	at java.lang.reflect.Method.invokeNative(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:515)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
	at dalvik.system.NativeStart.main(Native Method)



小小的自我提醒:

在追求任何知识和技能的过程中,最顶端的最后一小段路的边际成本是最高的,关山修阻,难以成行。但是边际理论只能带你到那里,最后一段路上请你务必忘记它。


发布了121 篇原创文章 · 获赞 32 · 访问量 16万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章