使用 ArkTs 開發(fā) Flutter 鴻蒙平臺插件
本文講述如何開發(fā)一個 Flutter 鴻蒙插件枫笛,如何實現(xiàn) Flutter 與鴻蒙的混合開發(fā),以及雙端消息通信多律。
Flutter側(cè)痴突,編寫 MethodChannel
const MethodChannel _methodChannel = MethodChannel('xxx.com/app');
/// 獲取token
static Future<dynamic> getToken() {
return _methodChannel.invokeMethod("getPrefs", 'token');
}
/// 設(shè)置token
static Future<dynamic> setToken(String token) {
return _methodChannel
.invokeMethod("setPrefs", {'key': 'token', 'value': token});
}
代碼生命了一個 methodChannel, 并實現(xiàn)了 token 存錯的調(diào)用方法。
ArkTs側(cè)狼荞,實現(xiàn)調(diào)用
編寫 src/main/ets/entryability/EntryAbility.ets
import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
import ForestPlugin from './ForestPlugin';
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';
import { preferences } from '@kit.ArkData';
let dataPreferences: preferences.Preferences | null = null;
export default class EntryAbility extends FlutterAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
super.onWindowStageCreate(windowStage);
preferences.getPreferences(this.context, 'forestStore', (err: BusinessError, val: preferences.Preferences) => {
if (err) {
console.error("Failed to get preferences. code =" + err.code + ", message =" + err.message);
return;
}
dataPreferences = val;
console.info("Succeeded in getting preferences1.");
})
}
configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
this.addPlugin(new ForestPlugin());
}
}
export {dataPreferences};
該文件使的原生頁面在加載時辽装,配置 Flutter 引擎,注冊插件相味。 Flutter初始化時拾积,同時初始化了 首選項dataPreferences,以備后用攻走。
編寫 src/main/ets/entryability/ForestPlugin.ets
import { Any, BasicMessageChannel, EventChannel, FlutterManager, FlutterPlugin, Log, MethodCall, MethodChannel, StandardMessageCodec} from '@ohos/flutter_ohos';
import { FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin';
import { batteryInfo } from '@kit.BasicServicesKit';
import { MethodCallHandler, MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel';
import { preferences } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
import {dataPreferences} from './EntryAbility';
import router from '@ohos.router'
import { webviewRouterParams } from '../pages/Webview';
const TAG = "[flutter][plugin][forest]";
export default class ForestPlugin implements FlutterPlugin {
private channel?: MethodChannel;
private basicChannel?: BasicMessageChannel<Any>;
private api = new ForestApi();
private dataPreferences: preferences.Preferences | null = null;
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(), "xxx.com/app");
this.channel.setMethodCallHandler({
onMethodCall : (call: MethodCall, result: MethodResult) => {
console.log(`${TAG}-->[${call.method}]: ${JSON.stringify(call.args)}`);
switch (call.method) {
case "getPrefs":
this.api.getPrefs(String(call.args), result);
break;
case "setPrefs":
let key = String(call.argument("key"));
let value = String(call.argument("value"));
this.api.setPrefs(key, value);
default:
result.notImplemented();
break;
}
}
})
}
//···
onDetachedFromEngine(binding: FlutterPluginBinding): void {
Log.i(TAG, "onDetachedFromEngine");
this.channel?.setMethodCallHandler(null);
}
getUniqueClassName(): string {
return "ForestPlugin";
}
以上代碼實現(xiàn)了一個插件類,其核心實現(xiàn)了FlutterPlugin中的 onAttachedToEngine方法此再,該方法在 Flutter 引擎加載成功后調(diào)用昔搂。
onMethodCall
中接收來自 Flutter 的消息調(diào)用,分別實現(xiàn)了 'getPrefs' 和 'setPrefs' 兩個回掉输拇,其中 getPrefs
有返回值摘符,通過 result.success(val);
(見下)異步返回,
setPrefs
沒有返回值策吠。
以下為 ForestApi
的具體實現(xiàn)逛裤,使用了 HarmonyOS 中的首選項 API 設(shè)置和讀取數(shù)據(jù)。
class ForestApi {
getPrefs(key: string, result: MethodResult) {
dataPreferences?.get(key, '', (err: BusinessError, val: preferences.ValueType) => {
if (err) {
console.error(`${TAG} Failed to get value of ${key}. code =` + err.code + ", message =" + err.message);
result.success('');
}
console.info(`${TAG} Succeeded in getting value of ${key}:${val}.`);
result.success(val);
})
}
setPrefs(key: string, value: string) {
dataPreferences?.put(key, value, (err: BusinessError) => {
if (err) {
console.error(`${TAG} Failed to put value of ${key}. code =` + err.code + ", message =" + err.message);
return;
}
console.info(`${TAG} Succeeded in putting value of ${key}.`);
})
}
clearPrefs(key: string) {
dataPreferences?.delete(key, (err: BusinessError) => {
if (err) {
console.error("Failed to delete the key 'startup'. code =" + err.code + ", message =" + err.message);
return;
}
console.info(`Succeeded in deleting the key ${key}.`);
})
}
}
注意事項
1.雙端初始化methodChannel中的名稱必須保持一致猴抹,如 xxx.com/app
.
2.arkTS側(cè)通過 result.success(val) 返回數(shù)據(jù)带族,該過程是異步的,故在 Dart 側(cè)需要使用 await 或者回調(diào)函數(shù)取值蟀给。
3.通信中默認只支持基礎(chǔ)的數(shù)據(jù)類型蝙砌,復(fù)雜類型的需要進行序列化或編解碼。
4.在Dart 側(cè)接收的數(shù)據(jù)為 dymanic 類型跋理,需要進行數(shù)據(jù)類型轉(zhuǎn)換择克。