From 42d6b46004e663dfc840e3576906a9f78ea5af05 Mon Sep 17 00:00:00 2001 From: yeliulee Date: Tue, 5 Nov 2024 22:53:56 +0800 Subject: [PATCH] add support for HarmonyOS Signed-off-by: yeliulee --- .metadata | 3 + README.md | 45 ++++- example/ohos/.gitignore | 19 +++ example/ohos/AppScope/app.json5 | 10 ++ .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes example/ohos/build-profile.json5 | 52 ++++++ example/ohos/entry/.gitignore | 7 + example/ohos/entry/build-profile.json5 | 29 ++++ example/ohos/entry/hvigorfile.ts | 17 ++ example/ohos/entry/oh-package.json5 | 27 +++ .../main/ets/entryability/EntryAbility.ets | 24 +++ .../ohos/entry/src/main/ets/pages/Index.ets | 38 +++++ example/ohos/entry/src/main/module.json5 | 53 ++++++ .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 ++ .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/buildinfo.json5 | 8 + .../resources/base/profile/main_pages.json | 5 + .../main/resources/en_US/element/string.json | 16 ++ .../main/resources/zh_CN/element/string.json | 16 ++ .../src/ohosTest/ets/test/Ability.test.ets | 50 ++++++ .../entry/src/ohosTest/ets/test/List.test.ets | 20 +++ .../ohosTest/ets/testability/TestAbility.ets | 63 +++++++ .../ohosTest/ets/testability/pages/Index.ets | 49 ++++++ .../ets/testrunner/OpenHarmonyTestRunner.ts | 64 +++++++ example/ohos/entry/src/ohosTest/module.json5 | 51 ++++++ .../resources/base/element/color.json | 8 + .../resources/base/element/string.json | 16 ++ .../ohosTest/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/test_pages.json | 5 + example/ohos/hvigor/hvigor-config.json5 | 20 +++ example/ohos/hvigorfile.ts | 21 +++ example/ohos/oh-package.json5 | 34 ++++ ohos/.gitignore | 12 ++ ohos/build-profile.json5 | 10 ++ ohos/hvigorfile.ts | 2 + ohos/index.ets | 17 ++ ohos/oh-package.json5 | 12 ++ ohos/src/libs/QQOpenSdk.har | Bin 0 -> 29330 bytes .../components/plugin/TencentKitPlugin.ets | 159 ++++++++++++++++++ ohos/src/main/module.json5 | 10 ++ pubspec.yaml | 2 + 43 files changed, 1023 insertions(+), 3 deletions(-) create mode 100644 example/ohos/.gitignore create mode 100644 example/ohos/AppScope/app.json5 create mode 100644 example/ohos/AppScope/resources/base/element/string.json create mode 100644 example/ohos/AppScope/resources/base/media/app_icon.png create mode 100644 example/ohos/build-profile.json5 create mode 100644 example/ohos/entry/.gitignore create mode 100644 example/ohos/entry/build-profile.json5 create mode 100644 example/ohos/entry/hvigorfile.ts create mode 100644 example/ohos/entry/oh-package.json5 create mode 100644 example/ohos/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 example/ohos/entry/src/main/ets/pages/Index.ets create mode 100644 example/ohos/entry/src/main/module.json5 create mode 100644 example/ohos/entry/src/main/resources/base/element/color.json create mode 100644 example/ohos/entry/src/main/resources/base/element/string.json create mode 100644 example/ohos/entry/src/main/resources/base/media/icon.png create mode 100644 example/ohos/entry/src/main/resources/base/profile/buildinfo.json5 create mode 100644 example/ohos/entry/src/main/resources/base/profile/main_pages.json create mode 100644 example/ohos/entry/src/main/resources/en_US/element/string.json create mode 100644 example/ohos/entry/src/main/resources/zh_CN/element/string.json create mode 100644 example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets create mode 100644 example/ohos/entry/src/ohosTest/ets/test/List.test.ets create mode 100644 example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets create mode 100644 example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets create mode 100644 example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts create mode 100644 example/ohos/entry/src/ohosTest/module.json5 create mode 100644 example/ohos/entry/src/ohosTest/resources/base/element/color.json create mode 100644 example/ohos/entry/src/ohosTest/resources/base/element/string.json create mode 100644 example/ohos/entry/src/ohosTest/resources/base/media/icon.png create mode 100644 example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json create mode 100644 example/ohos/hvigor/hvigor-config.json5 create mode 100644 example/ohos/hvigorfile.ts create mode 100644 example/ohos/oh-package.json5 create mode 100644 ohos/.gitignore create mode 100644 ohos/build-profile.json5 create mode 100644 ohos/hvigorfile.ts create mode 100644 ohos/index.ets create mode 100644 ohos/oh-package.json5 create mode 100644 ohos/src/libs/QQOpenSdk.har create mode 100644 ohos/src/main/ets/components/plugin/TencentKitPlugin.ets create mode 100644 ohos/src/main/module.json5 diff --git a/.metadata b/.metadata index 268ebaf..18804df 100644 --- a/.metadata +++ b/.metadata @@ -21,6 +21,9 @@ migration: - platform: ios create_revision: 9cd3d0d9ff05768afa249e036acc66e8abe93bff base_revision: 9cd3d0d9ff05768afa249e036acc66e8abe93bff + - platform: ohos + create_revision: 9cd3d0d9ff05768afa249e036acc66e8abe93bff + base_revision: 9cd3d0d9ff05768afa249e036acc66e8abe93bff # User provided section diff --git a/README.md b/README.md index 46b33c1..97c78df 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Flutter 版腾讯(QQ)SDK ### Android -``` +```txt # 不需要做任何额外接入工作 # 配置已集成到脚本里 # 混淆已打入 Library,随 Library 引用,自动添加到 apk 打包混淆 @@ -39,7 +39,7 @@ Flutter 版腾讯(QQ)SDK > 暂不支持 SceneDelegate,详见文档 [iOS_SDK环境搭建](https://wiki.connect.qq.com/ios_sdk%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba) -``` +```txt # 不需要做任何额外接入工作 # 配置已集成到脚本里 ``` @@ -70,6 +70,44 @@ https://${your applinks domain}/universal_link/${example_app}/qq_conn/${appId} > ⚠️ 很多 SDK 都会用到 universal_link,可为不同 SDK 分配不同的 path 以作区分 +### HarmonyOS + +> 当前在 `HarmonyOS` 平台, 仅支持 `setIsPermissionGranted/registerApp/isQQInstalled/loginServerSide` +> +> 由于 SDK 限制,当前仅支持 Server-Side 模式登录,auth code 在 accessToken 字段,获取后可自行在后端使用 + +项目中 module.json5 的 "module" 节点下配置 querySchemes + +```json5 +"querySchemes": [ + "https", + "qqopenapi" +] +``` + +在 Ability 的 skills 节点中配置 scheme + +```json5 +"skills": [ + { + "entities": [ + "entity.system.browsable" + ], + "actions": [ + "ohos.want.action.viewData" + ], + "uris": [ + { + "scheme": "qqopenapi", // 接收 QQ 回调数据 + "host": "102061317", // 业务申请的互联 appId + "path": "auth", + "linkFeature": "Login", + } + ] + } +] +``` + ### Flutter |分享类型|说说(图/文/视频)|文本|图片|音乐|视频|网页| @@ -84,7 +122,8 @@ https://${your applinks domain}/universal_link/${example_app}/qq_conn/${appId} * 兼容 flutter 2.5 兼容问题 [issues/54](https://github.com/RxReader/tencent_kit/issues/54) -``` + +```ruby post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) diff --git a/example/ohos/.gitignore b/example/ohos/.gitignore new file mode 100644 index 0000000..6ca13b3 --- /dev/null +++ b/example/ohos/.gitignore @@ -0,0 +1,19 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +*.har +**/BuildProfile.ets +**/oh-package-lock.json5 + +**/src/main/resources/rawfile/flutter_assets/ +**/libs/arm64-v8a/libapp.so +**/libs/arm64-v8a/libflutter.so +**/libs/arm64-v8a/libvmservice_snapshot.so diff --git a/example/ohos/AppScope/app.json5 b/example/ohos/AppScope/app.json5 new file mode 100644 index 0000000..cee1881 --- /dev/null +++ b/example/ohos/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "io.github.v7lin.tencent_kit_example", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/example/ohos/AppScope/resources/base/element/string.json b/example/ohos/AppScope/resources/base/element/string.json new file mode 100644 index 0000000..af73376 --- /dev/null +++ b/example/ohos/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "tencent_kit_example" + } + ] +} diff --git a/example/ohos/AppScope/resources/base/media/app_icon.png b/example/ohos/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets b/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000..cef0447 --- /dev/null +++ b/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000..1def08f --- /dev/null +++ b/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + var debug = abilityDelegatorArguments.parameters['-D'] + if (debug == 'true') + { + cmd += ' -D' + } + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/example/ohos/entry/src/ohosTest/module.json5 b/example/ohos/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000..fab77ce --- /dev/null +++ b/example/ohos/entry/src/ohosTest/module.json5 @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/example/ohos/entry/src/ohosTest/resources/base/element/color.json b/example/ohos/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000..3c71296 --- /dev/null +++ b/example/ohos/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/example/ohos/entry/src/ohosTest/resources/base/element/string.json b/example/ohos/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000..65d8fa5 --- /dev/null +++ b/example/ohos/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/example/ohos/entry/src/ohosTest/resources/base/media/icon.png b/example/ohos/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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�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

{C{Z1Ul8Bq3vq#pt4`-3x|f4 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 literal 0 HcmV?d00001 diff --git a/ohos/src/main/ets/components/plugin/TencentKitPlugin.ets b/ohos/src/main/ets/components/plugin/TencentKitPlugin.ets new file mode 100644 index 0000000..a5a316a --- /dev/null +++ b/ohos/src/main/ets/components/plugin/TencentKitPlugin.ets @@ -0,0 +1,159 @@ +import { + AbilityAware, + AbilityPluginBinding, + Any, + FlutterManager, + FlutterPlugin, + FlutterPluginBinding, + MethodCall, + MethodCallHandler, + MethodChannel, + MethodResult, + NewWantListener, +} from '@ohos/flutter_ohos'; +import { IQQOpenApi, QQOpenApiFactory, ApiCallback, AuthResponse } from '@tencent/qq-open-sdk' +import { AbilityConstant, Want } from '@kit.AbilityKit'; + +enum TencentRetCode { + RET_SUCCESS = 0, + RET_FAILED = 1, + RET_COMMON = -1, + RET_CANCEL = -2 +} + +const KEY_RET_CODE = "ret"; +const KEY_RET_MSG = "msg"; + +/** TencentKitPlugin **/ +export default class TencentKitPlugin implements FlutterPlugin, MethodCallHandler, AbilityAware, NewWantListener { + private channel: MethodChannel | null = null; + private binding: AbilityPluginBinding | null = null; + private tencent: IQQOpenApi | null = null; + private modeServerSide: boolean = false; + + getUniqueClassName(): string { + return "TencentKitPlugin" + } + + onAttachedToEngine(binding: FlutterPluginBinding): void { + this.channel = new MethodChannel(binding.getBinaryMessenger(), "v7lin.github.io/tencent_kit"); + this.channel.setMethodCallHandler(this) + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void { + if (this.channel != null) { + this.channel.setMethodCallHandler(null) + } + this.channel = null; + } + + onAttachedToAbility(binding: AbilityPluginBinding): void { + this.binding = binding; + binding.addOnNewWantListener(this); + } + + onDetachedFromAbility(): void { + this.binding = null; + } + + onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void { + this.tencent?.handleAuthResult(want) + } + + authListener: ApiCallback = { + onComplete: (response: AuthResponse): void => { + const resp: Map = new Map(); + try { + if (response.ret == TencentRetCode.RET_SUCCESS) { + // 服务端模式时, access_token 设置为为 authCode, 当前 SDK 不支持客户端模式(因此 null) + const accessToken: string | null = this.modeServerSide ? response.authCode : null; + resp.set(KEY_RET_CODE, TencentRetCode.RET_SUCCESS); + resp.set("openid", response.openId); + resp.set("access_token", accessToken); + resp.set("expires_in", response.expiresIn); + resp.set("create_at", response.authTime); + } else { + resp.set("ret", TencentRetCode.RET_COMMON); + } + } catch (e) { + resp.set(KEY_RET_CODE, TencentRetCode.RET_COMMON); + resp.set(KEY_RET_MSG, `${e}`); + } + this.channel?.invokeMethod("onLoginResp", resp); + }, + onError: (msg: string | null): void => { + const resp: Map = new Map(); + resp.set(KEY_RET_CODE, TencentRetCode.RET_FAILED); + resp.set(KEY_RET_MSG, msg); + this.channel?.invokeMethod("onLoginResp", resp); + }, + onCancel: (msg: string | null): void => { + const resp: Map = new Map(); + resp.set(KEY_RET_CODE, TencentRetCode.RET_CANCEL); + resp.set(KEY_RET_MSG, msg); + this.channel?.invokeMethod("onLoginResp", resp); + } + } + + onMethodCall(call: MethodCall, result: MethodResult): void { + switch (call.method) { + case "setIsPermissionGranted": + // 当前 SDK 不支持此方法,暂时返回 null + result.success(null); + break; + case "registerApp": + this.registerApp(call, result); + break; + case "isQQInstalled": + result.success(this.tencent != null && this.tencent.isQQInstalled()); + break; + case "isTIMInstalled": + // TIM 并未适配 harmonyOS, 暂时返回 false + result.success(false); + break; + case "login": + this.login(call, result); + break; + case "loginServerSide": + this.loginServerSide(call, result); + break; + default: + result.notImplemented(); + } + } + + private getUIContext(): UIContext { + const uiAbility = this.binding!.getAbility(); + const windowState = FlutterManager.getInstance().getWindowStage(uiAbility); + const window = windowState.getMainWindowSync(); + return window.getUIContext(); + } + + private registerApp(call: MethodCall, result: MethodResult) { + const appId: number = parseInt(call.argument("appId") as string); + this.tencent = QQOpenApiFactory.createApi(appId, { + autoHandleAuthResult: true, + forceEnableWeb: false, + }); + result.success(null); + } + + private login(call: MethodCall, result: MethodResult) { + // this.modeServerSide = false; // 客户端授权 + // 当前 SDK 仅支持 ServerSide 授权,暂时不处理 + result.success(null); + } + + private loginServerSide(call: MethodCall, result: MethodResult) { + this.modeServerSide = true; // 服务端授权 + const scope: string = call.argument("scope"); + const qrcode: boolean = call.argument("qrcode"); + this.tencent?.login(this.getUIContext(), { + scope: scope, + useQrCode: qrcode, + forceWebLogin: qrcode || !this.tencent!.isQQInstalled(), // H5 授权, 二维码登录或 QQ 未安装时强制启用 + networkTimeout: 0, // 不限制, 由 SDK 自行决定 + }, this.authListener); + result.success(null); + } +} \ No newline at end of file diff --git a/ohos/src/main/module.json5 b/ohos/src/main/module.json5 new file mode 100644 index 0000000..b1611b8 --- /dev/null +++ b/ohos/src/main/module.json5 @@ -0,0 +1,10 @@ +{ + "module": { + "name": "tencent_kit", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ] + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 2538f44..d479bda 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,6 +46,8 @@ flutter: pluginClass: TencentKitPlugin ios: pluginClass: TencentKitPlugin + ohos: + pluginClass: TencentKitPlugin # To add assets to your plugin package, add an assets section, like this: # assets: