Android webview一键登录手机QQ(2018.11)

前言

不知道什么时候开始, QQ oauth登陆, 不再让你在网页输入账号密码了. 页面提示正在拉起QQ手机版. 然后程序就在这里没有然后了.

可能有人会问, 为什么不使用QQ sdk做登陆. 这里提2点:

  • Android, iOS, Web 3端需要打通, 才能确保一个QQ用户唯一.
  • 平台sdk, 封装了QQ登陆, 对外多个应用提供. 比如常见的游戏sdk.

搜索了下这个sdk就无法QQ登陆了, 应该是QQ web页面不让输入账号密码之后出现的.
QQ只有一键登录,无法输入账号密码

解决问题

首先在webviewshouldOverrideUrlLoading(WebView view, String url)方法里打印下url. 会发现输出

wtloginmqq://ptlogin/qlogin?p=xxxxxxxxxxxxxxxxxxxxxxxxxxxx

这是个非http开头的地址, 内嵌的webview无法识别. 可以联想到QQ应该是走了定制的uri协议来跳转手机QQ. 我们可以通过intent来让系统帮我们跳转到QQ.

if (url.startsWith("wtloginmqq://ptlogin/qlogin")) {
  Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
  startActivity(intent);
}

加了上述代码, 就能启动QQ并登陆了. 登陆完了, 还会提示跳转到浏览器. 但是这样有个问题, 我们应用拿不到oauth要用到的code了.

既然QQ会登陆完毕会跳转浏览器, 那就让我们应用也能接收url跳转.

<activity
    android:name=".ui.activity.QQActivity"
    android:label="@string/app_name"
    android:screenOrientation="portrait"
    android:theme="@style/TransparentTheme">
    <intent-filter>
        <category android:name="android.intent.category.DEFAULT"/>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="https" android:host="ssl.ptlogin2.qq.com" android:path="/jump"/>
    </intent-filter>
</activity>

开始测试时只加了scheme限定, 得到地址规则后, 再加的hostpath限定符.

然后QQ登陆完毕后, 就是提示应用选择框


这里在做登陆前, 加个引导让用户点自己应用, 否则没有后续了.

选择我们的应用, 在对应的上述我们定义的QQActivity的onCreate或onNewIntent(如果该activity在栈里出现过)里就能响应了. 通过intent取出url, 找了url特征字符没有发现tokencode. 才发现在系统浏览器里最终会跳转到我们指定的REDIRECT_URI. 我们让之前那个内嵌webview的执行

mWebView.loadUrl(intent.getData().toString());

shouldOverrideUrlLoading里就能拦截到REDIRECT_URI, 以前不能跳转的代码就又续上了...

当然我们也可以自己发起http请求, 获取跳转地址. 代码如下

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        if (Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() != null) { 
                        String url = intent.getData().toString();
            StringRequest request = new StringRequest();
            request.setMethod("GET");
            request.setUrl(url);
            request.setListener(new Listener<String>() {
                @Override
                public void onResponse(int code, String response, Map<String, String> headers) {
                    if (code == 302 && headers.containsKey("Location")) {
                        String url = headers.get("Location");
                        //url结果为http://你填的REDIRECT_URI?code=aaaaaaaaaaa&state=bbbb
                    }
                }

                @Override
                public void onError(Response.ResponseError error) {
                    int w = 0;
                }
            });
            AsyncHttp.get().executeAsync(request);
        }
    }

备注: 测试手机小米mix2, 未测过其它手机

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容