Développement de plugins Flutter pour HarmonyOS avec ArkTs

Développer un plugin Flutter pour la plateforme HarmonyOS, implémenter une intégration mixte Flutter-HarmonyOS et gérer la communication inter-processus.

Côté Flutter : Configuration du MethodChannel


const MethodChannel _channel = MethodChannel('com.example.app/service');

/// Récupérer le jeton d'authentification
static Future<dynamic> fetchAuthToken() {
  return _channel.invokeMethod("retrieveSetting", 'auth_token');
}

/// Enregistrer le jeton d'authentification
static Future<dynamic> storeAuthToken(String jeton) {
  return _channel
      .invokeMethod("saveSetting", {'cle': 'auth_token', 'valeur': jeton});
}

Ce code définit un canal de méthode et expose des fonctions pour stocker et récupérer des données via des appels de méthode.

Côté ArkTs : Implémentation native

Fichier EntryAbility.ets


import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { PluginManager } from '../plugins/PluginManager';
import CustomBridgePlugin from './CustomBridgePlugin';
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';
import { preferences } from '@kit.ArkData';

let localStore: preferences.Preferences | null = null;

export default class AppAbility extends FlutterAbility {

  onWindowStageCreate(windowStage: window.WindowStage): void {
    super.onWindowStageCreate(windowStage);
    preferences.getPreferences(this.context, 'appDataStore', (err: BusinessError, prefs: preferences.Preferences) => {
      if (err) {
        console.error("Échec de l'initialisation des préférences. code=" + err.code);
        return;
      }
      localStore = prefs;
      console.info("Préférences chargées avec succès.");
    })
  }

  setupFlutterEngine(flutterEngine: FlutterEngine) {
    super.setupFlutterEngine(flutterEngine)
    PluginManager.registerPlugins(flutterEngine)
    this.registerPlugin(new CustomBridgePlugin());
  }
}

export {localStore};

Ce fichier initialise le moteur Flutter, configure les plugins et charge le stockage local au démarrage de l'application.

Fichier CustomBridgePlugin.ets


import { MethodChannel, MethodCall, MethodResult, FlutterPlugin, FlutterPluginBinding } from '@ohos/flutter_ohos';
import { localStore } from './AppAbility';

const LOG_TAG = "[HarmonyPlugin]";

export default class CustomBridgePlugin implements FlutterPlugin {
  private methodChannel?: MethodChannel;
  private storageService = new StorageOperations();

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.methodChannel = new MethodChannel(binding.getBinaryMessenger(), "com.example.app/service");
    this.methodChannel.setMethodCallHandler({
      onMethodCall : (call: MethodCall, result: MethodResult) => {
        console.log(`${LOG_TAG} Méthode appelée: ${call.method}`);
        switch (call.method) {
          case "retrieveSetting":
            this.storageService.readValue(String(call.args), result);
            break;
          case "saveSetting":
            const key = String(call.argument("cle"));
            const value = String(call.argument("valeur"));
            this.storageService.writeValue(key, value);
            break;
          default:
            result.notImplemented();
        }
      }
    })
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    this.methodChannel?.setMethodCallHandler(null);
  }
}

Classe StorageOperations


class StorageOperations {
  readValue(key: string, callback: MethodResult) {
    localStore?.get(key, '', (err: BusinessError, storedValue: preferences.ValueType) => {
      if (err) {
        console.error(`${LOG_TAG} Erreur de lecture pour la clé ${key}`);
        callback.success('');
      }
      callback.success(storedValue);
    })
  }

  writeValue(key: string, value: string) {
    localStore?.put(key, value, (err: BusinessError) => {
      if (!err) {
        console.info(`${LOG_TAG} Valeur écrite pour la clé ${key}`);
      }
    })
  }

  removeValue(key: string) {
    localStore?.delete(key, (err: BusinessError) => {
      if (!err) {
        console.info(`${LOG_TAG} Clé ${key} supprimée`);
      }
    })
  }
}

Points d'attention

  • Les noms des canaux de méthode doivent correspondre exactement entre les parties Flutter et native (ex: 'com.example.app/service').
  • Les réponses natives sont asynchrones ; côté Dart, utilisez await ou des callbacks pour traiter les données.
  • Seuls les types de données simples sont supportés nativement ; les objets complexes nécessitent une sérialisation.
  • Les données reçues en Dart sont de type dynamic et nécessitent une conversion exlpicite.

Étiquettes: Flutter HarmonyOS ArkTS MethodChannel plugins

Publié le 4 août à 09h20