在 Flutter App 中編寫自定義平臺特定程式碼[Method Channel]
在 Flutter App 中編寫自定義平臺特定程式碼[Method Channel]
前言
學習如何編寫自定義平臺程式碼,並將其連線到 flutter 應用程式中
Flutter 使用了一個靈活的系統,允許您使用直接與這些 API 協作的語言呼叫特定於平臺的 API:
- 在 Android 上使用 Kotlin 或 Java
- IOS 上的 Swift 或 Objective-C
- Windows 下的 C + +
- 在 macOS 上的 Objective-C
- Linux 上的 C 語言
正文
下面的解釋來自 Flutter 官方文件,解釋 Method Channel 是如何工作的
我也將 應用 application 在官方檔案的解釋得到當前的裝置電池電量給予更多的背景下,它是如何工作的
首先使用你喜歡的 IDE 建立一個 Flutter 應用程式
清除 Flutter Starter 應用程式並建立一個新的 dart 檔案 home_screen. dart
在 home_screen. dart 內部建立一個新的狀態完整的 widget ,返回一個現在的指令碼框
```dart import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State
}
class _HomeScreenState extends State
@override
Widget build(BuildContext context) {
return Scaffold();
}
} ```
然後匯入那些庫
dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
請注意,與 Platfrom 的通訊是非同步的,所以我們將在這個應用程式的未來工作
建立一個字串
dart
String _batteryLevel = 'Unknown battery level.';
您的程式碼現在應該如下所示
```dart import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State
}
class _HomeScreenState extends State
String _batteryLevel = 'Unknown battery level.';
@override
Widget build(BuildContext context) {
return Scaffold();
}
} ```
然後在您的狀態內建立一個未來的非同步函式 getBatteryLevel
```dart
Future
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}
setState(() {
_batteryLevel = batteryLevel;
});
} ```
現在您將注意到平臺中的一個錯誤,這是因為我們還沒有定義它
在我們宣告它之前,我們需要知道 Method Channel 必須有一個唯一的域,以便兩端進行通訊,因此它將是不可變的
返回您的狀態並釋放一個 methodChannel 物件
dart
static const platform = MethodChannel('mediumExplain/battery');
然後,我們需要新增一些簡單的使用者介面互動,以獲得電池電平
用此程式碼替換生成方法
```dart @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Text('Your battery level is ${_batteryLevel}'),
ElevatedButton(
onPressed: _getBatteryLevel,
child: const Text('Get Battery Level'),
),
],
),
);
} ```
現在是機器人的本機部分,
Android 配置 Kotlin
開啟 android 應用程式目錄
-
app -> src ->main->kotlin->MainActivity.kt
- 加上那些進口
```java import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import androidx.annotation.NonNull
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES ```
這些都是本地庫從機器人聯絡電池電平 hteapi
然後新增這個變數,就像我們在 flutter 應用程式中建立的那樣
java
class MainActivity: FlutterActivity() {
private val CHANNEL = "mediumExplain/battery"
然後重寫該函式並保持不變
```dart override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
// This method is invoked on the main thread.
// TODO
}
} ```
然後在它新增這個方法,將得到電池百分比和重新發送到我們的通道
```dart private fun getBatteryLevel(): Int {
val batteryLevel: Int
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} else {
val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
batteryLevel = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
}
return batteryLevel
} ```
注意: 這些和 flutter 沒有任何關係這是一個 android 原生 kotlin 程式碼,你一定不知道,你也可以從 android 或 ios 呼叫任何 api 即使你不知道原生程式碼,你可以在 stackoverflow 上搜索,找到任何你需要的相關內容。你只需要在這些程式碼之間建立一個通道
現在你的整個程式碼應該看起來像
```java package com.example.bateery_level
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import androidx.annotation.NonNull
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
class MainActivity: FlutterActivity() {
private val CHANNEL ="mediumExplain/battery"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// This method is invoked on the main thread.
call, result ->
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
} else {
result.notImplemented()
}
}
}
private fun getBatteryLevel(): Int {
val batteryLevel: Int
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} else {
val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
batteryLevel = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
}
return batteryLevel
}
} ```
現在回到你的 flutter 應用程式並執行它
下一步是 ios 配置,如果在 Windows 裝置上執行,則跳過
IOS Configuration 配置
在 Xcode 中開啟 IOS 資料夾
然後開啟執行器目錄中的 AppGenerate.swift
在 did FinishLaunchingWithOptions 方法中新增這兩行
swift
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "mediumExplain/battery",
binaryMessenger: controller.binaryMessenger)
再加上這個
```swift batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
guard call.method == "getBatteryLevel" else {
result(FlutterMethodNotImplemented)
return
}
self.receiveBatteryLevel(result: result)
})
```
然後在檔案的底部新增這個函式
```swift private func receiveBatteryLevel(result: FlutterResult) {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
if device.batteryState == UIDevice.BatteryState.unknown {
result(FlutterError(code: "UNAVAILABLE",
message: "Battery level not available.",
details: nil))
} else {
result(Int(device.batteryLevel * 100))
}
} ```
現在你的整個檔案應該看看
```swift import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "mediumExplain/battery",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
guard call.method == "getBatteryLevel" else {
result(FlutterMethodNotImplemented)
return
}
self.receiveBatteryLevel(result: result)
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func receiveBatteryLevel(result: FlutterResult) {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
if device.batteryState == UIDevice.BatteryState.unknown {
result(FlutterError(code: "UNAVAILABLE",
message: "Battery level not available.",
details: nil))
} else {
result(Int(device.batteryLevel * 100))
}
}
} ```
then run the app from a rea ios device not on a simualtor
GitHub 倉庫
Https://github.com/mohaberabi/flutter_method_channel
結束語
如果本文對你有幫助,請轉發讓更多的朋友閱讀。
也許這個操作只要你 3 秒鐘,對我來說是一個激勵,感謝。
祝你有一個美好的一天~
© 貓哥
-
微信 ducafecat
-
https://wiki.ducafecat.tech
-
https://video.ducafecat.tech
- Flutter 中使用 OpenAI GPT-3 進行語義化處理
- Flutter 構建設計系統
- Flutter ー Authentication 認證
- Flutter 離線資料方案 Flutter_Data 包
- 基於 Hive 的 Flutter 文件型別儲存
- Flutter AlarmManager = ⏰
- Flutter 8 個優秀動畫 Packages
- Flutter 建立自己的對話方塊,不使用任何包!
- 在 Flutter App 中編寫自定義平臺特定程式碼[Method Channel]
- Flutter 最有用的 5 個優秀的依賴包
- Neumorphism 元件 ーー Dart extension 擴充套件
- 用抽象工廠方法構建 Flutter 主題
- Dart 語言的7個很酷的特點
- 17 個提高效能的 Flutter 最佳實踐
- Flutter 應用程式建立一個擴充套件面板列表
- 在 Flutter 使用 GetX 對話方塊
- flutter 互動式使用者指導,以及如何在佈局中創造一個洞
- Flutter開源專案 - appFlowy 真的是 Notion 的替代品? 一週暴漲 star 9k 多!
- 桌面 Flutter 應用程式
- Flutter 2020 開源專案推薦 第一彈