Flutter platform channels实现dart和原生交互
目的
在flutter中调用原生代码,比如调用Android原生的api获取设备的电量
实现
1.首先在MainActivity中增加一个通过原生Api获取设备电量的方法getBatteryLevel()
private fun getBatteryLevel(): Int {
val batteryLevel: Int
if (Build.VERSION.SDK_INT >= Build.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
}
2.然后在MainActivity的onCreate方法中增加如下代码,用于处理从flutter端发送过来的请求消息,若方法名为getBatteryLevel,则调用getBatteryLevel()方法获取电量,通过result对象设置获取的结果
MethodChannel的第二个参数channel name必须唯一
MethodChannel(flutterView, "samples.flutter.dev/battery").setMethodCallHandler { 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()
}
}
3.在Flutter端的main.dart的State中创建一个MethodChannel对象,参数须与步骤2中的channel name一致
static const platform = const MethodChannel('samples.flutter.dev/battery');
4.在State中新增一个_getBatteryLevel()方法,通过MethodChannel对象调用原生的方法获取设备电量,然后通过setState更新UI显示获取的电量值
String _batteryLevel = '电量';
Future<void> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = '电量 $result%';
} on PlatformException catch (e) {
batteryLevel = "获取电量失败: '${e.message}'.";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
完整代码
原生端代码
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
MethodChannel(flutterView, "samples.flutter.dev/battery").setMethodCallHandler { 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 (Build.VERSION.SDK_INT >= Build.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端代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const platform = const MethodChannel('samples.flutter.dev/battery');
String _batteryLevel = '电量';
Future<void> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = '电量 $result%';
} on PlatformException catch (e) {
batteryLevel = "获取电量失败: '${e.message}'.";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Text(
_batteryLevel,
),
),
floatingActionButton: FloatingActionButton(
onPressed: _getBatteryLevel,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Java实现
java实现与kotlin类似,至于iOS的object-c或者swift实现,可以参考官方文档
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), "samples.flutter.dev/battery").setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.equals("getBatteryLevel")) {
int batteryLevel = getBatteryLevel();
if (batteryLevel != -1) {
result.success(batteryLevel);
} else {
result.error("UNAVAILABLE", "Battery level not available.", null);
}
} else {
result.notImplemented();
}
}
});
}
private int getBatteryLevel() {
int batteryLevel = -1;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
} else {
Intent intent = new ContextWrapper(getApplicationContext()).
registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
}
return batteryLevel;
}
}