0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙应用如何唤起 QQ 安卓客户端进行授权

OpenHarmony技术社区 来源:HarmonyOS技术社区 作者:HarmonyOS技术社区 2022-01-04 15:01 次阅读

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

前期准备

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

https://connect.qq.com/index.html
注意:要选择网站应用,移动应用和小程序不适用该方案。

编写代码

①判断是否已登录

获取登录状态:在入口 AbilitySliceMainAbilitySlice 中进行判断。

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

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

进行相应跳转:已登录跳转至个人界面 MyAbility,未登录跳转至登录界面 LoginAbility。

if(token!=null){
//已登录,跳转至MyAbility
IntentmyIntent=newIntent();
myIntent.setParam("token",token);
OperationmyOperation=newIntent.OperationBuilder()
.withBundleName("cn.dsttl3.test")
.withAbilityName("cn.dsttl3.qqlogin.MyAbility")
.build();
myIntent.setOperation(myOperation);
startAbility(myIntent);
terminateAbility();
}else{
//未登录,跳转至LoginAbility
IntentloginIntent=newIntent();
OperationloginOperation=newIntent.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 组件。







登录界面的 AbilitySlice LoginAbilitySlice.java,需要用到的几个常量如下:

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

WebView 的配置:

WebViewmyWebView=(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客户端
IntentqqIntent=newIntent();
OperationqqOperation=newIntent.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存入数据库
Preferencespreferences=newDatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
preferences.putString("token",token);
preferences.flush();

token 存储完成后跳转至 MyAbility,自定义 WebAgent 完整代码:

myWebView.setWebAgent(newWebAgent(){
//当WebView即将打开一个链接时调用该方法
@Override
publicbooleanisNeedLoadUrl(WebViewwebView,ResourceRequestrequest){
//request.getRequestUrl().toString()WebView即将打开的链接地址
if(request.getRequestUrl().toString().startsWith("wtloginmqq")){
//打开QQ客户端
IntentqqIntent=newIntent();
OperationqqOperation=newIntent.OperationBuilder()
.withAction("android.intent.action.VIEW")
.withUri(Uri.parse(request.getRequestUrl().toString()))
.build();
qqIntent.setOperation(qqOperation);
startAbility(qqIntent);
//向自己的服务器请求token
newThread(newRunnable(){
@Override
publicvoidrun(){
while(true){
StringgetTokenURL="https://api.dsttl3.cn/Redis/Get?key="+state;
try{
OkHttpClientclient=newOkHttpClient();
Requestrequest=newRequest.Builder().url(getTokenURL).build();
Stringtoken=client.newCall(request).execute().body().string();
if(token.length()==32){
getUITaskDispatcher().asyncDispatch(newRunnable(){
@Override
publicvoidrun(){
//将token存入数据库
Preferencespreferences=newDatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
preferences.putString("token",token);
preferences.flush();
//跳转至用户界面
IntentmyIntent=newIntent();
OperationmyOperation=newIntent.OperationBuilder()
.withBundleName("cn.dsttl3.test")
.withAbilityName("cn.dsttl3.qqlogin.MyAbility")
.build();
myIntent.setOperation(myOperation);
startAbility(myIntent);
terminateAbility();
}
});
break;
}
Time.sleep(1500);
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}).start();
returnfalse;
}
returntrue;
}
});

加载网页:

myWebView.load(authorize_url);

LoginAbilitySlice.java 完整代码:

importcn.dsttl3.qqlogin.ResourceTable;
importohos.aafwk.ability.AbilitySlice;
importohos.aafwk.content.Intent;
importohos.aafwk.content.Operation;
importohos.agp.components.webengine.ResourceRequest;
importohos.agp.components.webengine.WebAgent;
importohos.agp.components.webengine.WebView;
importohos.data.DatabaseHelper;
importohos.data.preferences.Preferences;
importohos.miscservices.timeutility.Time;
importohos.utils.net.Uri;
importokhttp3.OkHttpClient;
importokhttp3.Request;
importjava.io.IOException;
importjava.util.UUID;

publicclassLoginAbilitySliceextendsAbilitySlice{

//QQ开放平台登录授权文档https://wiki.connect.qq.com/%e5%87%86%e5%a4%87%e5%b7%a5%e4%bd%9c_oauth2-0
Stringstate=UUID.randomUUID().toString();//唯一标识,成功授权后回调时会原样带回。
Stringclient_id="101547151";//QQ开放平台应用APPID
Stringredirect_uri="https%3A%2F%2Fapi.dsttl3.cn%2FRedis%2FQQLogin";//应用网站回调域需进行url编码,授权成功后会跳转至该链接
Stringauthorize_url="https://graph.qq.com/oauth2.0/authorize?response_type=code"+
"&client_id="+client_id+
"&redirect_uri="+redirect_uri+
"&state="+state;
@Override
publicvoidonStart(Intentintent){
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_login);
WebViewmyWebView=(WebView)findComponentById(ResourceTable.Id_WebView_qqlogin);
myWebView.getWebConfig().setJavaScriptPermit(true);
myWebView.getWebConfig().setUserAgent("android");
myWebView.setWebAgent(newWebAgent(){
//当WebView即将打开一个链接时调用该方法
@Override
publicbooleanisNeedLoadUrl(WebViewwebView,ResourceRequestrequest){
//request.getRequestUrl().toString()WebView即将打开的链接地址
if(request.getRequestUrl().toString().startsWith("wtloginmqq")){
//打开QQ客户端
IntentqqIntent=newIntent();
OperationqqOperation=newIntent.OperationBuilder()
.withAction("android.intent.action.VIEW")
.withUri(Uri.parse(request.getRequestUrl().toString()))
.build();
qqIntent.setOperation(qqOperation);
startAbility(qqIntent);
//向自己的服务器请求token
newThread(newRunnable(){
@Override
publicvoidrun(){
while(true){
StringgetTokenURL="https://api.dsttl3.cn/Redis/Get?key="+state;
try{
OkHttpClientclient=newOkHttpClient();
Requestrequest=newRequest.Builder().url(getTokenURL).build();
Stringtoken=client.newCall(request).execute().body().string();
if(token.length()==32){
getUITaskDispatcher().asyncDispatch(newRunnable(){
@Override
publicvoidrun(){
//将token存入数据库
Preferencespreferences=newDatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
preferences.putString("token",token);
preferences.flush();
//跳转至用户界面
IntentmyIntent=newIntent();
OperationmyOperation=newIntent.OperationBuilder()
.withBundleName("cn.dsttl3.test")
.withAbilityName("cn.dsttl3.qqlogin.MyAbility")
.build();
myIntent.setOperation(myOperation);
startAbility(myIntent);
terminateAbility();
}
});
break;
}
Time.sleep(1500);
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}).start();
returnfalse;
}
returntrue;
}
});
myWebView.load(authorize_url);
}
}

个人界面,获取 token 信息

Preferencespreferences=newDatabaseHelper(getApplicationContext()).getPreferences("DATA_NAME");
Stringtoken=preferences.getString("token",null);

更新 Text 数据:

Texttext=findComponentById(ResourceTable.Id_text_helloworld);
text.setText(token);

后续操作

获取用户信息请参考 QQ 开放平台文档:

https://wiki.connect.qq.com/get_user_info

附件下载

https://harmonyos.51cto.com/posts/9448

原文标题:在鸿蒙上实现QQ第三方登录!

文章出处:【微信公众号:HarmonyOS技术社区】欢迎添加关注!文章转载请注明出处。

审核编辑:彭菁

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    3561

    浏览量

    63292
  • SDK
    SDK
    +关注

    关注

    3

    文章

    960

    浏览量

    44536
  • 鸿蒙
    +关注

    关注

    54

    文章

    1459

    浏览量

    42034

原文标题:在鸿蒙上实现QQ第三方登录!

文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    2012微信电脑客户端免费下载

    的彩信不用再在意彩信费用,因为它完全免费,即时拍照即时分享。  同所有同类的聊天软件一样,微信也能设置自己的个人信息和头像,更方便你的好友快速的找到你。  微信目前就是简单的手机客户端,没有电脑
    发表于 09-13 18:59

    一个服务器,多个客户端,怎么向指定的客户端发数据

    我用labview做服务器,单片机做客户端客户端几百个,怎么区分客户端,给指定的客户发发数据
    发表于 06-01 09:26

    请问smartconfig开发手机客户端的应用程序提供源代码了吗?在哪里下载?

    本帖最后由 一只耳朵怪 于 2018-6-7 14:46 编辑 你好,请问基于smartconfig开发手机客户端的应用程序,你们提供源代码了吗?在哪里下载?ios和的都要,谢谢
    发表于 06-07 05:03

    的蓝牙全面开发教程

    就基本完成了,在两块都开启了蓝牙的设备上分别建议服务器跟客户端,并进行连接,连接成功后双方就可以通过蓝牙进行通信了。
    发表于 12-05 10:51

    基于的视频遥控小车——电脑开发

    虚拟机中运行的,和平台无关,只要平台上有相应的Java虚拟机。本设计中手机是客户端,电脑是服务器。采用ServerSocket类与多线程技术相互配合共同完成服务器
    发表于 07-06 16:10

    如履薄冰?华为将以鸿蒙替代

    `华为消费者CEO余承东表示HMS生态仅次于和iOS,生态中集成的AppGallery(应用市场)是谷歌Play、苹果iOS之后全球第三大应用商店,这意味着鸿蒙系统所依赖的系统生态基本打造完成
    发表于 09-04 09:44

    如何看待鸿蒙系统兼容系统?

    网络看到很多人讨论鸿蒙,有人说鸿蒙就是换皮版的,有人说
    发表于 10-10 11:06

    鸿蒙 vs 六大维度对比

    生态系统至今已经发展了十几年了,软件生态可以说是相当完善。鸿蒙初出茅庐。所以现阶段生态上完胜鸿蒙
    发表于 12-07 14:13

    鸿蒙 vs 六大维度对比

    生态系统至今已经发展了十几年了,软件生态可以说是相当完善。鸿蒙初出茅庐。所以现阶段生态上完胜鸿蒙
    发表于 12-07 16:43

    如何使用Socket实现UDP客户端

    本教程介绍了如何利用socket 编程来实现一个 UDP 客户端,与服务器进行通信。与开发 TCP 客户端一样,我们先将 socket 编程的流程列出来,然后给出具体的实例。
    发表于 03-30 07:39

    Labview客户端状态获取

    求助,目前只有5积分,哪位大佬给点帮助:采用TCP传输数据,一个服务器多个客户端,通过一个按钮控制,点动按钮将服务器中的一个文件发给4个客户端,目前已实现发送文件和读取连接客户端数量,不过客户
    发表于 11-15 15:02

    鸿蒙取代?这下鸿蒙开发者要坐不住了!

    授权。仅这一点,华为做的事情,就应当受到国人的支持。换句话说,华为现如今不开发鸿蒙OS系统,谷歌全面断供国产手机的情况一旦出现。手机直接变成“板砖”,届时对于国内的手机市场造成的
    发表于 12-08 09:33

    当WiFi信号变低时,服务器和客户端之间的TCP通信丢失,如何使客户端重新连接?

    大家好, 当 WiFi 信号变低时,服务器和客户端之间的 TCP 通信丢失,比如超过 -80dBm。一旦客户端断开连接,它就无法重新连接并正常进行通信。如何让客户端在这里重新连接。
    发表于 05-15 07:31

    AT32基于FreeRTOS的AWS MQTT客户端

    AT32基于FreeRTOS的AWS MQTT客户端建立一个MQTT客户端与 AWS IoT Core进行通讯,用户可以基于这个范例去开发属于自己的应用。
    发表于 10-26 06:03

    Android 仿QQ客户端及服务端源码

    Android 仿QQ客户端及服务端源码
    发表于 03-19 11:23 3次下载