因为鸿蒙系统刚出不久,官方的第三方登录 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文章
2654浏览量
62398 -
SDK
+关注
关注
2文章
778浏览量
43802 -
鸿蒙
+关注
关注
50文章
853浏览量
39607
发布评论请先 登录
相关推荐
客户端初始化后是否可以从客户端句柄中获取客户端配置呢?
密钥服务器和客户端常见问题解答
Linux网络编程-TCP客户端如何获取要连接的服务端IP?

SSH 客户端各种特性和使用说明
分享几款Windows系统下的SSH客户端软件
使用firefly的RK3308的buildroot编译Dueros客户端进行语音交互就出错怎么解决?
监控系统客户端及服务端设计
鸿蒙取代安卓?这下鸿蒙开发者要坐不住了!
Labview客户端状态获取
NodeMCU项目(三)MQTT客户端

鸿蒙:我来了!安卓:那我走?
鸿蒙、iOS、安卓的开发者数量,APP数量大对比,差距有多大呢?
线程多客户端设置
鸿蒙基于安卓 鸿蒙系统和安卓有什么区别
安卓系统怎么转换鸿蒙系统
鸿蒙是基于安卓吗 鸿蒙与安卓区别
鸿蒙是否脱离安卓 鸿蒙跟安卓的关系
鸿蒙系统vs安卓系统哪个更好
鸿蒙还是安卓系统吗 两者的区别
安卓手机可以换鸿蒙系统吗? 安卓如何升级为鸿蒙
鸿蒙比安卓好吗 鸿蒙系统有哪些优势
鸿蒙的底层是安卓吗 鸿蒙是基于安卓吗
鸿蒙系统好还是安卓系统好
鸿蒙系统真的比安卓流畅吗
鸿蒙os底层是安卓吗
华为鸿蒙与安卓系统的区别
基于Socket开发TCP传输客户端
华为鸿蒙系统与安卓系统的区别
鸿蒙系统和安卓系统那个更好
鸿蒙系统和安卓的区别是什么
鸿蒙系统与安卓系统的区别有哪些
鸿蒙系统是基于安卓吗
鸿蒙os和安卓的区别,鸿蒙与安卓比有什么优势
鸿蒙系统比安卓系统好吗 鸿蒙是基于安卓系统吗
鸿蒙系统和安卓系统区别在哪里 鸿蒙与安卓的比较
鸿蒙系统和安卓系统哪个好
鸿蒙系统和安卓的区别到底是什么
鸿蒙系统是安卓换皮吗?鸿蒙系统本质还是安卓?
华为鸿蒙系统想全面取代安卓还面临哪些问题
华为鸿蒙系统与安卓系统有哪些区别
如何使用Socket实现UDP客户端?
鸿蒙 vs 安卓 六大维度对比
鸿蒙 vs 安卓 六大维度对比
如何看待鸿蒙系统兼容安卓系统?
有奖话题:HarmonyOS 2.0兼容安卓APP是否可以体现自身光环?
有奖话题:鸿蒙系统达到安卓70%-80%水平,你对鸿蒙有哪些期待?
安卓如履薄冰?华为将以鸿蒙替代安卓
安卓危在旦夕!华为将以鸿蒙系统替代安卓系统
TCP通信时服务端如何接收客户端的数据?
GitHub iOS和Android客户端发布稳定版
怎么获取连接客户端的MAC地址?
有奖话题:不为替代安卓,鸿蒙会成长为“下一代”安卓吗?
“鸿蒙比安卓更强大”?“鸿蒙应未来而生”
基于安卓的视频遥控小车——电脑端开发
华为鸿蒙系统和安卓系统有什么区别?
Adobe修复Windows客户端漏洞
请问smartconfig开发手机客户端的应用程序提供源代码了吗?在哪里下载?
Cmd Markdown客户端免费下载

评论