When using Flutter to develop apps, you will encounter the interaction with the Android native system API.
You can usually use Flutter to write pages and reuse existing Android logic (such as your own or third-party SDK) to speed up development schedule.
You can use plug-ins to solve, the official website about the development of plug-ins:
writing dual-end platform code (plug-in writing implementation)
A complete demo is listed in the article:
Note: The complete runnable code for this example can be obtained in / examples / platform_channel / for Android using Java and iOS using Objective-C For iOS code implemented in Swift, see / examples / platform_channel_swift / .
Channel
Flutter defines three different types of Channel, they are
- BasicMessageChannel: Used to pass string and semi-structured information, and can request data in both directions.
- MethodChannel: Used to pass method invocation (method invocation, that is, the Flutter side can call the method on the Platform side and call back the result data through the Result interface.
- EventChannel: Used for communication of event streams, that is, the Flutter side monitors real-time messages on the Platform side, and once the Platform side generates data, it immediately calls back to the Flutter side.
⚠️ Note: On Android and iOS platforms, Platform Task Runner runs on the main thread. Therefore, time-consuming operations should not be handled in the Handler on the Platform side.
First look at the main.dart
file of MethodChannel and EventChannel as follows:
class PlatformChannel extends StatefulWidget {
@override
_PlatformChannelState createState() => _PlatformChannelState();
}
class _PlatformChannelState extends State<PlatformChannel> {
static const MethodChannel methodChannel =
MethodChannel('samples.flutter.io/battery');
static const EventChannel eventChannel =
EventChannel('samples.flutter.io/charging');
String _batteryLevel = 'Battery level: unknown.';
String _chargingStatus = 'Battery status: unknown.';
Future<void> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await methodChannel.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level: $result%.';
} on PlatformException {
batteryLevel = 'Failed to get battery level.';
}
setState(() {
_batteryLevel = batteryLevel;
});
}
@override
void initState() {
super.initState();
eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
}
void _onEvent(Object event) {
setState(() {
_chargingStatus =
"Battery status: ${event == 'charging' ? '' : 'dis'}charging.";
});
}
void _onError(Object error) {
setState(() {
_chargingStatus = 'Battery status: unknown.';
});
}
@override
Widget build(BuildContext context) {
return Material(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_batteryLevel, key: const Key('Battery level label')),
Padding(
padding: const EdgeInsets.all(16.0),
child: RaisedButton(
child: const Text('Refresh'),
onPressed: _getBatteryLevel,
),
),
],
),
Text(_chargingStatus),
],
),
);
}
}
void main() {
runApp(MaterialApp(home: PlatformChannel()));
}
1. Use MethodChannel steps
- It defines an
MethodChannel
object, andmethodChannel
theinvokeMethod('getBatteryLevel')
method used can be called to the Android native method, - Define the MethodChannel object in Android and call its setMethodCallHandler method, implement the onMethodCall method in the callback interface MethodCallHandler, and return the value to the Flutter end through the Result object.
private static final String BATTERY_CHANNEL = "samples.flutter.io/battery";
new MethodChannel(getFlutterView(), BATTERY_CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, 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();
}
}
}
);
In this MethodCallHandler
callback, the method call request sent by the Flutter part is processed, and the result.success(batteryLevel)
data is passed back.
This is the case where the value returned directly from the Android side can be obtained directly, but usually the Android side operates asynchronously and returns the value in the interface callback, then how to pass the value to the Flutter side at this time? Then it can be used EventChannel
.
2. Use EventChannel steps
- Define the EventChannel object on the Android side and call the setStreamHandler () method, implement the onListen and onCancel methods in the anonymous inner class StreamHandler, and pass the data back to the Flutter side through the EventSink object
- Flutter by side
eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
to define_onEvent
the function and the_onError
function processing return value.
new EventChannel(getFlutterView(), CHARGING_CHANNEL).setStreamHandler(
new StreamHandler() {
private BroadcastReceiver chargingStateChangeReceiver;
@Override
public void onListen(Object arguments, EventSink events) {
chargingStateChangeReceiver = createChargingStateChangeReceiver(events);
registerReceiver(
chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
@Override
public void onCancel(Object arguments) {
unregisterReceiver(chargingStateChangeReceiver);
chargingStateChangeReceiver = null;
}
}
);
3. Steps to use BasicMessageChannel
Android side:
dart side:
Reference:
Flutter Platform channel
in-depth understanding of Flutter Platform Channel