前言
因为鸿蒙系统刚出不久,官方的第三方登录SDK还没出来,下面就介绍下在鸿蒙应用中实现QQ登录的方法(支持唤起QQ安卓客户端进行授权)
前期准备
登录QQ开放平台 > 应用管理 > 创建应用 ,创建一个网站应用。
注意:要选择网站应用,移动应用和小程序不适用该方案。
编写代码
判断是否已登录
获取登录状态
在入口AbilitySliceMainAbilitySlice中进行判断。
从数据库获取token的值判断是否已经登录账号 (已登录返回token,未登录返回null)
- // 创建数据库(这里使用官方提供的“轻量级数据存储”,相关文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/database-preference-guidelines-0000000000030083)
- Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
- // 从数据库获取token的值判断是否已经登录账号 (已登录返回token,未登录返回null)
- String token = preferences.getString("token",null);
进行相应跳转
已登录跳转至个人界面MyAbility,未登录跳转至登录界面LoginAbility.
- if(token != null){
- // 已登录,跳转至MyAbility
- Intent myIntent = new Intent();
- myIntent.setParam("token", token);
- Operation myOperation = new Intent.OperationBuilder()
- .withBundleName("cn.dsttl3.test")
- .withAbilityName("cn.dsttl3.qqlogin.MyAbility")
- .build();
- myIntent.setOperation(myOperation);
- startAbility(myIntent);
- terminateAbility();
- }else {
- // 未登录,跳转至LoginAbility
- Intent loginIntent = new Intent();
- Operation loginOperation = new Intent.OperationBuilder()
- .withBundleName("cn.dsttl3.test")
- .withAbilityName("cn.dsttl3.qqlogin.LoginAbility")
- .build();
- loginIntent.setOperation(loginOperation);
- startAbility(loginIntent);
- terminateAbility();
- }
登录界面的操作
申请网络访问权限
在config.json添加
- "reqPermissions": [
- {
- "name": "ohos.permission.INTERNET"
- }
- ]
登录界面布局文件ability_login.xml
在布局文件中添加以后webview组件
- "1.0" encoding="utf-8"?>
-
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:alignment="center"
- ohos:orientation="vertical">
-
- ohos:id="$+id:WebView_qqlogin"
- ohos:height="match_parent"
- ohos:width="match_parent"/>
登录界面的AbilitySlice LoginAbilitySlice.java
需要用到的几个常量
- String state = UUID.randomUUID().toString();// 唯一标识,成功授权后回调时会原样带回。
- String client_id = "101***151";//QQ开放平台 应用 APP ID
- String redirect_uri = "https%3A%2F%2Fapi.dsttl3.cn%2FRedis%2FQQLogin"; //应用 网站回调域 需进行url编码,授权成功后会跳转至该链接
- String authorize_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code" +
- "&client_id=" + client_id +
- "&redirect_uri=" + redirect_uri +
- "&state="+ state;
WebView的配置
- WebView myWebView = (WebView) findComponentById(ResourceTable.Id_WebView_qqlogin);
- myWebView.getWebConfig().setJavaScriptPermit(true);//支持JavaScript
- myWebView.getWebConfig().setUserAgent("android");//将UserAgent设置为安卓,授权页才显示QQ客户端一键登录按钮
自定义WebAgent
当WebView即将打开一个链接时调用isNeedLoadUrl方法,当在网页上点击“一键登录”时,打开QQ客户端
wtloginmqq是QQ安卓客户端URL Scheme
- if (request.getRequestUrl().toString().startsWith("wtloginmqq")){
- // 打开QQ客户端
- Intent qqIntent = new Intent();
- Operation qqOperation = new Intent.OperationBuilder()
- .withAction("android.intent.action.VIEW")
- .withUri(Uri.parse(request.getRequestUrl().toString()))
- .build();
- qqIntent.setOperation(qqOperation);
- startAbility(qqIntent);
因为目前还找不到网页端唤起鸿蒙应用的方法,所以QQ客户端回调的code放在自己服务器处理。
授权成功后,会打开之前在QQ开放平台设置的回调域redirect_uri
示例:https://api.dsttl3.cn/Redis/QQLogin?code=********&state=*****
code:QQ授权返回的code,用于申请token
state:在webview请求QQ授权页面时传入的唯一标识,用于判断用户身份,方便后续从服务器请求token
出于安全考虑 ,请求token操作放在服务器上执行。获取到token后将token存入数据库,客户端通过请求https://api.dsttl3.cn/Redis/Get?key= + state来获取到token
客户端请求到token后,将token存储到数据库
- // 将token存入数据库
- Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
- preferences.putString("token",token);
- preferences.flush();
token存储完成后跳转至MyAbility
自定义WebAgent完整代码
- myWebView.setWebAgent(new WebAgent(){
- // 当WebView即将打开一个链接时调用该方法
- @Override
- public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) {
- // request.getRequestUrl().toString() WebView即将打开的链接地址
- if (request.getRequestUrl().toString().startsWith("wtloginmqq")){
- // 打开QQ客户端
- Intent qqIntent = new Intent();
- Operation qqOperation = new Intent.OperationBuilder()
- .withAction("android.intent.action.VIEW")
- .withUri(Uri.parse(request.getRequestUrl().toString()))
- .build();
- qqIntent.setOperation(qqOperation);
- startAbility(qqIntent);
- // 向自己的服务器请求token
- new Thread(new Runnable() {
- @Override
- public void run() {
- while (true){
- String getTokenURL = "https://api.dsttl3.cn/Redis/Get?key=" + state;
- try {
- OkHttpClient client = new OkHttpClient();
- Request request = new Request.Builder().url(getTokenURL).build();
- String token = client.newCall(request).execute().body().string();
- if (token.length() == 32){
- getUITaskDispatcher().asyncDispatch(new Runnable() {
- @Override
- public void run() {
- // 将token存入数据库
- Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
- preferences.putString("token",token);
- preferences.flush();
- // 跳转至用户界面
- Intent myIntent = new Intent();
- Operation myOperation = new Intent.OperationBuilder()
- .withBundleName("cn.dsttl3.test")
- .withAbilityName("cn.dsttl3.qqlogin.MyAbility")
- .build();
- myIntent.setOperation(myOperation);
- startAbility(myIntent);
- terminateAbility();
- }
- });
- break;
- }
- Time.sleep(1500);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- return false;
- }
- return true;
- }
- });
加载网页
- myWebView.load(authorize_url);
LoginAbilitySlice.java完整代码
- import cn.dsttl3.qqlogin.ResourceTable;
- import ohos.aafwk.ability.AbilitySlice;
- import ohos.aafwk.content.Intent;
- import ohos.aafwk.content.Operation;
- import ohos.agp.components.webengine.ResourceRequest;
- import ohos.agp.components.webengine.WebAgent;
- import ohos.agp.components.webengine.WebView;
- import ohos.data.DatabaseHelper;
- import ohos.data.preferences.Preferences;
- import ohos.miscservices.timeutility.Time;
- import ohos.utils.net.Uri;
- import okhttp3.OkHttpClient;
- import okhttp3.Request;
- import java.io.IOException;
- import java.util.UUID;
- public class LoginAbilitySlice extends AbilitySlice {
- //QQ开放平台登录授权文档 https://wiki.connect.qq.com/%e5%87%86%e5%a4%87%e5%b7%a5%e4%bd%9c_oauth2-0
- String state = UUID.randomUUID().toString();// 唯一标识,成功授权后回调时会原样带回。
- String client_id = "101547151";//QQ开放平台 应用 APP ID
- String redirect_uri = "https%3A%2F%2Fapi.dsttl3.cn%2FRedis%2FQQLogin"; //应用 网站回调域 需进行url编码,授权成功后会跳转至该链接
- String authorize_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code" +
- "&client_id=" + client_id +
- "&redirect_uri=" + redirect_uri +
- "&state="+ state;
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_login);
- WebView myWebView = (WebView) findComponentById(ResourceTable.Id_WebView_qqlogin);
- myWebView.getWebConfig().setJavaScriptPermit(true);
- myWebView.getWebConfig().setUserAgent("android");
- myWebView.setWebAgent(new WebAgent(){
- // 当WebView即将打开一个链接时调用该方法
- @Override
- public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) {
- // request.getRequestUrl().toString() WebView即将打开的链接地址
- if (request.getRequestUrl().toString().startsWith("wtloginmqq")){
- // 打开QQ客户端
- Intent qqIntent = new Intent();
- Operation qqOperation = new Intent.OperationBuilder()
- .withAction("android.intent.action.VIEW")
- .withUri(Uri.parse(request.getRequestUrl().toString()))
- .build();
- qqIntent.setOperation(qqOperation);
- startAbility(qqIntent);
- // 向自己的服务器请求token
- new Thread(new Runnable() {
- @Override
- public void run() {
- while (true){
- String getTokenURL = "https://api.dsttl3.cn/Redis/Get?key=" + state;
- try {
- OkHttpClient client = new OkHttpClient();
- Request request = new Request.Builder().url(getTokenURL).build();
- String token = client.newCall(request).execute().body().string();
- if (token.length() == 32){
- getUITaskDispatcher().asyncDispatch(new Runnable() {
- @Override
- public void run() {
- // 将token存入数据库
- Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
- preferences.putString("token",token);
- preferences.flush();
- // 跳转至用户界面
- Intent myIntent = new Intent();
- Operation myOperation = new Intent.OperationBuilder()
- .withBundleName("cn.dsttl3.test")
- .withAbilityName("cn.dsttl3.qqlogin.MyAbility")
- .build();
- myIntent.setOperation(myOperation);
- startAbility(myIntent);
- terminateAbility();
- }
- });
- break;
- }
- Time.sleep(1500);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- return false;
- }
- return true;
- }
- });
- myWebView.load(authorize_url);
- }
- }
个人界面
获取token信息
- Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
- String token = preferences.getString("token",null);
更新Text数据
- Text text = findComponentById(ResourceTable.Id_text_helloworld);
- text.setText(token);
后续操作
获取用户信息请参考QQ开放平台文档 https://wiki.connect.qq.com/get_user_info
文章相关附件可以点击下面的原文链接前往下载
https://harmonyos.51cto.com/resource/1554
原文链接:https://harmonyos.51cto.com