文章目录
0. 准备
我的flutter
版本是 1.12.13
, 请确保版本差距不大! google更新的实在太快了!
1. Flutter调用Native方法(Android)
Flutter 与 原生代码进行通信, 就好比两个人在打电话, 都要先准备好电话(MethodChannel), 再根据同一条线的链接(Channel)来进行通信
- Flutter 请求数据的过程
flutter调用底层方法关键使用MethodChannel
类中的invodeMothed
方法, 有以下几个要点
MethodChannel(键名)
:即构建一个电话,通信两端都需要, 构造函数参数为一个键名, 用来标识Channel
, 与Native 代码中的Channel
名字保持一致invokeMethod(函数名)
: 即拨打电话, 需要指定一条线路,目的是接收原生通信端提供的服务,参数为函数名, 用来标识调用的函数, 与Native 代码中的函数名保持一致setMethodCallHandler
: 即接收一个电话, 为同一条线路上拨打来的电话提供服务
1.1 Flutter 端
在flutter端有以下要点:
- 搭建座机: 即建立
MethodChannel
对象 - 发送请求: 即调用
MethodChannel
对象的invokeMethod
方法
1.2 Android 端
- 搭建座机: 也需要构建
MethodChannel
对象 - 接受请求: 使用
MethodChannel
对象中的setMethodCallHandler
方法
2. 代码实例
2.1 项目介绍
项目调用原生代码来获取手机电量, 并且显示, 如下图
2.2 编写flutter 端代码
import 'package:flutter/material.dart';
import 'dart:async';
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> {
//1. 搭建桥梁Channel: 名字为samples.flutter.dev/battery, 是一个键, 与native端通信用
static const batteryChannel = const MethodChannel("samples.flutter.dev/battery");
String _batteryPercentage;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("TestNativeFlutter"),),
body: Container(
alignment: Alignment.center,
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialButton(
onPressed:_getBatteryInformation,
color: Colors.blueAccent,
child: Padding(
padding: EdgeInsets.all(16.0),
child: Text(
"click me",
style: TextStyle(
color: Colors.white,
fontSize: 35.0
),
),
),
),
Text(_batteryPercentage,style: TextStyle(fontSize: 20.0),)
],),
),
);
}
Future<void> _getBatteryInformation() async{
String batteryPercentage;
try{
//2. 发送信息, 请求数据
final int result = await batteryChannel.invokeMethod('getBatteryLevel');
batteryPercentage = 'Battery level at $result %';
}on PlatformException catch(e){
batteryPercentage = "Failed to get battery level: '${e.message}' ";
}
setState(() {
_batteryPercentage = batteryPercentage;
});
}
}
2.3 编写 Android端原生代码
package com.example.test_flutter_native
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
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat.getSystemService
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
//1. 建立座机, 为通信做准备, CHANNEL名字为samples.flutter.dev/battery, 与注意要与flutter端相同
val methodChannel=MethodChannel(flutterEngine.dartExecutor, CHANNEL)
//2. 接收消息, 且根据接收的消息来做出反应
methodChannel.setMethodCallHandler{
call, result ->
if(call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNABAILABLE", "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
}
}