2023年3月15日 星期三

Flutter 開發筆記 - 撰寫平台相依性功能,以取得 Android Device 資料為例


研究了一下 Flutter 如何寫平台相依性的程式碼,看一眼也是常見的 Channel or Message 等溝通機制,也滿直觀的。以 Android 平台和 Kotlin 為例,先找到 MainActivity.kt ,接著,在 Code -> Override Methods 可以找到 configureFlutterEngine 可以添加

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
    }
}

接著就可以在透過 MethodChannel 建立綁定溝通管道:

import android.os.Build
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
    private val myCHANNEL = "samples.flutter.dev/helper"
    
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, myCHANNEL).setMethodCallHandler {
                call, result ->
            // This method is invoked on the main thread.
            // TODO

            if (call.method == "getBatteryLevel") {
                val batteryLevel = 0; // getBatteryLevel()
                if (batteryLevel != -1) {
                    result.success(batteryLevel)
                } else {
                    result.error("UNAVAILABLE", "Battery level not available.", null)
                }
            } else if (call.method == "getDeviceInfo") {
                result.success(getDeviceInfo())
            } else {
                result.notImplemented()
            }
        }
    }

    private fun getDeviceInfo(): HashMap<String, String> {
        val deviceInfo:HashMap<String, String> = HashMap<String, String>()
        deviceInfo.run {
            put("MODEL", Build.MODEL)
            put("MANUFACTURER", Build.MANUFACTURER)
        }
        return deviceInfo
    }
}

如此在 Flutter Dart 端,就可以呼叫:

class _MyHomePageState extends State<MyHomePage> {
  static const platform = MethodChannel('samples.flutter.dev/helper');

  String _deviceInfo = "system info unknown";
  Future<void> _getDeviceInfo() async {
    Map<String, String> deviceInfo = {};
    try {
      final Map<Object?, Object?> result = await platform.invokeMethod('getDeviceInfo');
      deviceInfo.clear();
      result.forEach((key, value) {
        if (key.runtimeType == String && value.runtimeType == String) {
          deviceInfo[key.toString()] = value.toString();
        }
      });
    } on PlatformException catch (e) {
      deviceInfo.clear();
    } on Exception catch (e) {
      //print("Exception catch: $e ");
    }

    setState(() {
      _deviceInfo = json.encode(deviceInfo);
    });
  }
...

後續就只是完善細節,強烈建議直接觀看官方文件,有完整的細流程資訊和各平台的範例: docs.flutter.dev/development/platform-integration/platform-channels 

沒有留言:

張貼留言