iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0
Mobile Development

Flutter - 從 Packages & Plugins 掌握原生系列 第 15

Day15 開發套件 - 實作MethodChannel

Flutter 端:

lib/batterylevel.dart:新增取得電池電量資訊方法,透過建立的MethodChannel傳入方法名來呼叫Native 端對應的getBatteryLevel方法

  static Future<String?> get batteryLevel async {
    final String? batteryLevel = await _channel.invokeMethod('getBatteryLevel');
    return batteryLevel;
  }

Native 端(Android):

android/.../BatterylevelPlugin.kt

這邊會取得電量會需要android 的applicationContext,所以我們新增一個applicationContext屬性,在onAttachedToEngine時透過flutterPluginBinding取得,並在onDetachedFromEngine釋放

最後新增一個方法getBatteryLevel來處理取得電量資訊的動作

最後在onMethodCall的地方實現從Flutter 端要調用的getBatteryLevel方法

class BatterylevelPlugin : FlutterPlugin, MethodCallHandler {
    private lateinit var channel: MethodChannel
    private var applicationContext: Context? = null

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        applicationContext = flutterPluginBinding.applicationContext
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "batterylevel")
        channel.setMethodCallHandler(this)
    }

    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
        if (call.method == "getPlatformVersion") {
            result.success("Android ${android.os.Build.VERSION.RELEASE}")
        } else if (call.method == "getBatteryLevel") {
            val batterLevel = getBatteryLevel()
            if (batterLevel != -1) {
                result.success("Android batterLevel = $batterLevel%")
            } else {
                result.error("UNAVAILABLE", "Battery level not available.", null);
            }
        } else {
            result.notImplemented()
        }
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        applicationContext = null;
        channel.setMethodCallHandler(null)
    }

    private fun getBatteryLevel(): Int {
        var batteryLevel = -1
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            val batteryManager =
                applicationContext?.let { getSystemService(it, BatteryManager::class.java) }
            batteryLevel = batteryManager!!.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
        } else {
            ContextWrapper(applicationContext).registerReceiver(
                null,
                IntentFilter(Intent.ACTION_BATTERY_CHANGED)
            )?.apply {
                batteryLevel = getIntExtra(
                    BatteryManager.EXTRA_LEVEL,
                    -1
                ) * 100 / getIntExtra(BatteryManager.EXTRA_SCALE, -1)
            }
        }

        return batteryLevel
    }
}

Native 端(iOS):

同樣新增一個方法getBatteryLevel來處理取得電量資訊的動作,最後在handle實現從Flutter 端要調用的getBatteryLevel方法

public class SwiftBatterylevelPlugin: NSObject, FlutterPlugin {
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "batterylevel", binaryMessenger: registrar.messenger())
        let instance = SwiftBatterylevelPlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }
    
    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch call.method {
        case "getPlatformVersion":
            result("iOS " + UIDevice.current.systemVersion)
        case "getBatteryLevel":
            let batterLevel = getBatteryLevel()
            if(batterLevel == -1) {
                result(FlutterError(code: "UNAVAILABLE", message: "Battery info unavailable", details: nil));
            } else {
                result("iOS batterLevel = \(batterLevel * 100)%")
            }
        default:
            result(FlutterMethodNotImplemented)
        }
    }
    
    private func getBatteryLevel() -> Float {
        let device = UIDevice.current
        device.isBatteryMonitoringEnabled = true
        if device.batteryState == .unknown {
            return -1;
        } else {
            return UIDevice.current.batteryLevel
        }
    }
}

這樣就完成獲得設備電池電量資訊的插件功能了,並了解對MethodChannel的實作步驟流程,接下來讓我們看看其他的Channel要如何實作吧


上一篇
Day14 開發套件 - 範例程式碼介紹03 iOS 端
下一篇
Day16 開發套件 - 實作EventChannel
系列文
Flutter - 從 Packages & Plugins 掌握原生30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言