HarmonyOS 第三方登录之QQ登录

开发 OpenHarmony
因为鸿蒙系统刚出不久,官方的第三方登录SDK还没出来,下面就介绍下在鸿蒙应用中实现QQ登录的方法(支持唤起QQ安卓客户端进行授权)

[[438480]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

前言

因为鸿蒙系统刚出不久,官方的第三方登录SDK还没出来,下面就介绍下在鸿蒙应用中实现QQ登录的方法(支持唤起QQ安卓客户端进行授权)

前期准备

登录QQ开放平台 > 应用管理 > 创建应用 ,创建一个网站应用。

注意:要选择网站应用,移动应用和小程序不适用该方案。

编写代码

判断是否已登录

获取登录状态

在入口AbilitySliceMainAbilitySlice中进行判断。

从数据库获取token的值判断是否已经登录账号 (已登录返回token,未登录返回null)

  1. // 创建数据库(这里使用官方提供的“轻量级数据存储”,相关文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/database-preference-guidelines-0000000000030083) 
  2. Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME"); 
  3. //  从数据库获取token的值判断是否已经登录账号 (已登录返回token,未登录返回null
  4. String token = preferences.getString("token",null); 

进行相应跳转

已登录跳转至个人界面MyAbility,未登录跳转至登录界面LoginAbility.

  1. if(token != null){ 
  2.             // 已登录,跳转至MyAbility 
  3.             Intent myIntent = new Intent(); 
  4.             myIntent.setParam("token", token); 
  5.             Operation myOperation = new Intent.OperationBuilder() 
  6.                     .withBundleName("cn.dsttl3.test"
  7.                     .withAbilityName("cn.dsttl3.qqlogin.MyAbility"
  8.                     .build(); 
  9.             myIntent.setOperation(myOperation); 
  10.             startAbility(myIntent); 
  11.             terminateAbility(); 
  12. }else { 
  13.             // 未登录,跳转至LoginAbility 
  14.             Intent loginIntent = new Intent(); 
  15.             Operation loginOperation = new Intent.OperationBuilder() 
  16.                     .withBundleName("cn.dsttl3.test"
  17.                     .withAbilityName("cn.dsttl3.qqlogin.LoginAbility"
  18.                     .build(); 
  19.             loginIntent.setOperation(loginOperation); 
  20.             startAbility(loginIntent); 
  21.             terminateAbility(); 

登录界面的操作

申请网络访问权限

在config.json添加

  1. "reqPermissions": [ 
  2.       { 
  3.         "name""ohos.permission.INTERNET" 
  4.       } 
  5.     ] 

登录界面布局文件ability_login.xml

在布局文件中添加以后webview组件

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <DirectionalLayout 
  3.     xmlns:ohos="http://schemas.huawei.com/res/ohos" 
  4.     ohos:height="match_parent" 
  5.     ohos:width="match_parent" 
  6.     ohos:alignment="center" 
  7.     ohos:orientation="vertical"
  8.  
  9.     <ohos.agp.components.webengine.WebView 
  10.         ohos:id="$+id:WebView_qqlogin" 
  11.         ohos:height="match_parent" 
  12.         ohos:width="match_parent"/> 
  13.  
  14. </DirectionalLayout> 

登录界面的AbilitySlice LoginAbilitySlice.java

需要用到的几个常量

  1. String state = UUID.randomUUID().toString();// 唯一标识,成功授权后回调时会原样带回。 
  2. String client_id = "101***151";//QQ开放平台 应用 APP ID 
  3. String redirect_uri = "https%3A%2F%2Fapi.dsttl3.cn%2FRedis%2FQQLogin"; //应用 网站回调域 需进行url编码,授权成功后会跳转至该链接 
  4. String authorize_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code" + 
  5.             "&client_id=" + client_id + 
  6.             "&redirect_uri=" + redirect_uri + 
  7.             "&state="+ state; 

 WebView的配置

  1. WebView myWebView = (WebView) findComponentById(ResourceTable.Id_WebView_qqlogin); 
  2.         myWebView.getWebConfig().setJavaScriptPermit(true);//支持JavaScript 
  3.         myWebView.getWebConfig().setUserAgent("android");//将UserAgent设置为安卓,授权页才显示QQ客户端一键登录按钮 

自定义WebAgent

当WebView即将打开一个链接时调用isNeedLoadUrl方法,当在网页上点击“一键登录”时,打开QQ客户端

wtloginmqq是QQ安卓客户端URL Scheme

  1. if (request.getRequestUrl().toString().startsWith("wtloginmqq")){ 
  2.                    // 打开QQ客户端 
  3.                    Intent qqIntent = new Intent(); 
  4.                    Operation qqOperation = new Intent.OperationBuilder() 
  5.                            .withAction("android.intent.action.VIEW"
  6.                            .withUri(Uri.parse(request.getRequestUrl().toString())) 
  7.                            .build(); 
  8.                    qqIntent.setOperation(qqOperation); 
  9.                    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存储到数据库

  1.  // 将token存入数据库 
  2. Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME"); 
  3. preferences.putString("token",token); 
  4. preferences.flush(); 

token存储完成后跳转至MyAbility

自定义WebAgent完整代码

  1. myWebView.setWebAgent(new WebAgent(){ 
  2.             // 当WebView即将打开一个链接时调用该方法 
  3.             @Override 
  4.             public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) { 
  5.                 // request.getRequestUrl().toString() WebView即将打开的链接地址 
  6.                 if (request.getRequestUrl().toString().startsWith("wtloginmqq")){ 
  7.                     // 打开QQ客户端 
  8.                     Intent qqIntent = new Intent(); 
  9.                     Operation qqOperation = new Intent.OperationBuilder() 
  10.                             .withAction("android.intent.action.VIEW"
  11.                             .withUri(Uri.parse(request.getRequestUrl().toString())) 
  12.                             .build(); 
  13.                     qqIntent.setOperation(qqOperation); 
  14.                     startAbility(qqIntent); 
  15.                     // 向自己的服务器请求token 
  16.                     new Thread(new Runnable() { 
  17.                         @Override 
  18.                         public void run() { 
  19.                             while (true){ 
  20.                                 String getTokenURL = "https://api.dsttl3.cn/Redis/Get?key=" + state; 
  21.                                 try { 
  22.                                     OkHttpClient client = new OkHttpClient(); 
  23.                                     Request request = new Request.Builder().url(getTokenURL).build(); 
  24.                                     String token = client.newCall(request).execute().body().string(); 
  25.                                     if (token.length() == 32){ 
  26.                                         getUITaskDispatcher().asyncDispatch(new Runnable() { 
  27.                                             @Override 
  28.                                             public void run() { 
  29.                                                 // 将token存入数据库 
  30.                                                 Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME"); 
  31.                                                 preferences.putString("token",token); 
  32.                                                 preferences.flush(); 
  33.                                                 // 跳转至用户界面 
  34.                                                 Intent myIntent = new Intent(); 
  35.                                                 Operation myOperation = new Intent.OperationBuilder() 
  36.                                                         .withBundleName("cn.dsttl3.test"
  37.                                                         .withAbilityName("cn.dsttl3.qqlogin.MyAbility"
  38.                                                         .build(); 
  39.                                                 myIntent.setOperation(myOperation); 
  40.                                                 startAbility(myIntent); 
  41.                                                 terminateAbility(); 
  42.                                             } 
  43.                                         }); 
  44.                                         break; 
  45.                                     } 
  46.                                     Time.sleep(1500); 
  47.                                 } catch (IOException e) { 
  48.                                     e.printStackTrace(); 
  49.                                 } 
  50.                             } 
  51.                         } 
  52.                     }).start(); 
  53.                     return false
  54.                 } 
  55.                 return true
  56.             } 
  57.         }); 

加载网页

  1. myWebView.load(authorize_url); 

LoginAbilitySlice.java完整代码

  1. import cn.dsttl3.qqlogin.ResourceTable; 
  2. import ohos.aafwk.ability.AbilitySlice; 
  3. import ohos.aafwk.content.Intent; 
  4. import ohos.aafwk.content.Operation; 
  5. import ohos.agp.components.webengine.ResourceRequest; 
  6. import ohos.agp.components.webengine.WebAgent; 
  7. import ohos.agp.components.webengine.WebView; 
  8. import ohos.data.DatabaseHelper; 
  9. import ohos.data.preferences.Preferences; 
  10. import ohos.miscservices.timeutility.Time
  11. import ohos.utils.net.Uri; 
  12. import okhttp3.OkHttpClient; 
  13. import okhttp3.Request; 
  14. import java.io.IOException; 
  15. import java.util.UUID; 
  16.  
  17. public class LoginAbilitySlice extends AbilitySlice { 
  18.  
  19.     //QQ开放平台登录授权文档 https://wiki.connect.qq.com/%e5%87%86%e5%a4%87%e5%b7%a5%e4%bd%9c_oauth2-0 
  20.     String state = UUID.randomUUID().toString();// 唯一标识,成功授权后回调时会原样带回。 
  21.     String client_id = "101547151";//QQ开放平台 应用 APP ID 
  22.     String redirect_uri = "https%3A%2F%2Fapi.dsttl3.cn%2FRedis%2FQQLogin"; //应用 网站回调域 需进行url编码,授权成功后会跳转至该链接 
  23.     String authorize_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code" + 
  24.             "&client_id=" + client_id + 
  25.             "&redirect_uri=" + redirect_uri + 
  26.             "&state="+ state; 
  27.     @Override 
  28.     public void onStart(Intent intent) { 
  29.         super.onStart(intent); 
  30.         super.setUIContent(ResourceTable.Layout_ability_login); 
  31.         WebView myWebView = (WebView) findComponentById(ResourceTable.Id_WebView_qqlogin); 
  32.         myWebView.getWebConfig().setJavaScriptPermit(true); 
  33.         myWebView.getWebConfig().setUserAgent("android"); 
  34.         myWebView.setWebAgent(new WebAgent(){ 
  35.             // 当WebView即将打开一个链接时调用该方法 
  36.             @Override 
  37.             public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) { 
  38.                 // request.getRequestUrl().toString() WebView即将打开的链接地址 
  39.                 if (request.getRequestUrl().toString().startsWith("wtloginmqq")){ 
  40.                     // 打开QQ客户端 
  41.                     Intent qqIntent = new Intent(); 
  42.                     Operation qqOperation = new Intent.OperationBuilder() 
  43.                             .withAction("android.intent.action.VIEW"
  44.                             .withUri(Uri.parse(request.getRequestUrl().toString())) 
  45.                             .build(); 
  46.                     qqIntent.setOperation(qqOperation); 
  47.                     startAbility(qqIntent); 
  48.                     // 向自己的服务器请求token 
  49.                     new Thread(new Runnable() { 
  50.                         @Override 
  51.                         public void run() { 
  52.                             while (true){ 
  53.                                 String getTokenURL = "https://api.dsttl3.cn/Redis/Get?key=" + state; 
  54.                                 try { 
  55.                                     OkHttpClient client = new OkHttpClient(); 
  56.                                     Request request = new Request.Builder().url(getTokenURL).build(); 
  57.                                     String token = client.newCall(request).execute().body().string(); 
  58.                                     if (token.length() == 32){ 
  59.                                         getUITaskDispatcher().asyncDispatch(new Runnable() { 
  60.                                             @Override 
  61.                                             public void run() { 
  62.                                                 // 将token存入数据库 
  63.                                                 Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME"); 
  64.                                                 preferences.putString("token",token); 
  65.                                                 preferences.flush(); 
  66.                                                 // 跳转至用户界面 
  67.                                                 Intent myIntent = new Intent(); 
  68.                                                 Operation myOperation = new Intent.OperationBuilder() 
  69.                                                         .withBundleName("cn.dsttl3.test"
  70.                                                         .withAbilityName("cn.dsttl3.qqlogin.MyAbility"
  71.                                                         .build(); 
  72.                                                 myIntent.setOperation(myOperation); 
  73.                                                 startAbility(myIntent); 
  74.                                                 terminateAbility(); 
  75.                                             } 
  76.                                         }); 
  77.                                         break; 
  78.                                     } 
  79.                                     Time.sleep(1500); 
  80.                                 } catch (IOException e) { 
  81.                                     e.printStackTrace(); 
  82.                                 } 
  83.                             } 
  84.                         } 
  85.                     }).start(); 
  86.                     return false
  87.                 } 
  88.                 return true
  89.             } 
  90.         }); 
  91.         myWebView.load(authorize_url); 
  92.     } 

个人界面

获取token信息

  1. Preferences preferences = new DatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME"); 
  2. String token = preferences.getString("token",null); 

 更新Text数据

  1. Text text = findComponentById(ResourceTable.Id_text_helloworld); 
  2. text.setText(token); 

后续操作

获取用户信息请参考QQ开放平台文档 https://wiki.connect.qq.com/get_user_info

文章相关附件可以点击下面的原文链接前往下载

https://harmonyos.51cto.com/resource/1554

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2015-11-05 16:44:37

第三方登陆android源码

2015-01-20 17:01:30

Android源码QQdemo

2014-07-23 08:55:42

iOSFMDB

2024-03-04 10:36:39

2011-12-20 14:23:15

MozillaBrower ID

2021-08-26 16:07:46

鸿蒙HarmonyOS应用

2019-07-30 11:35:54

AndroidRetrofit

2018-09-30 15:18:29

2019-09-03 18:31:19

第三方支付电商支付行业

2017-12-11 15:53:56

2009-12-31 14:38:34

Silverlight

2016-10-21 14:09:10

2022-01-14 09:57:14

鸿蒙HarmonyOS应用

2013-08-12 16:04:19

第三方移动应用

2014-07-22 10:56:45

Android Stu第三方类库

2017-05-16 13:24:02

LinuxCentOS第三方仓库

2009-01-14 12:45:05

MSNIM苹果

2010-05-25 11:09:31

SVN工具

2024-04-03 12:57:29

2021-09-26 10:43:08

注册Istio集成
点赞
收藏

51CTO技术栈公众号