前言
因為鴻蒙系統剛出不久,官方的第三方登錄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