美文网首页FlutterFlutterFlutter
Flutter与Native数据交互,MethodChannel

Flutter与Native数据交互,MethodChannel

作者: iwakevin | 来源:发表于2018-12-25 19:04 被阅读256次

    平台通道

    Flutter APP同iOS&Android native之间的数据通信如下图所示:


    消息和响应是异步传递,以确保用户界面保持响应。
    在客户端,MethodChannel(API)允许发送对应于方法调用的消息。在平台端,Android上的MethodChannel(API)和iOS上的FlutterMethodChannel(API)支持接收方法调用并返回结果。

    平台信道数据类型支持和编解码器

    Dart Android iOS
    null null nil (NSNull when nested)
    bool java.lang.Boolean NSNumber numberWithBool:
    int java.lang.Integer NSNumber numberWithInt:
    int, if 32 bits not enough java.lang.Long NSNumber numberWithLong:
    double java.lang.Double NSNumber numberWithDouble:
    String java.lang.String NSString
    Uint8List byte[] FlutterStandardTypedData typedDataWithBytes:
    Int32List int[] FlutterStandardTypedData typedDataWithInt32:
    Int64List long[] FlutterStandardTypedData typedDataWithInt64:
    Float64List double[] FlutterStandardTypedData typedDataWithFloat64:
    List java.util.ArrayList NSArray
    Map java.util.HashMap NSDictionary

    示例:使用平台通道调用平台特定的iOS和Android代码

    1.创建Flutter 平台

    首先,我们构建通道。我们使用平台的MethodChannel方法返回电池电量。

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    ...
    class _MyHomePageState extends State<MyHomePage> {
      static const platform = const MethodChannel('samples.flutter.io/battery');
    
      // Get battery level.
    }
    

    接下来,使用invokeMethod方法通过字符串的形式调用getBatteryLevel,使用invokeMethod方法时注意try-catch.

    // Get battery level.
      String _batteryLevel = 'Unknown battery level.';
    
      Future<void> _getBatteryLevel() async {
        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;
        });
      }
    

    最后,用下面的代码替换build方法

    @override
    Widget build(BuildContext context) {
      return Material(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              RaisedButton(
                child: Text('Get Battery Level'),
                onPressed: _getBatteryLevel,
              ),
              Text(_batteryLevel),
            ],
          ),
        ),
      );
    }
    
    

    2.Android平台使用java实现

    首先,在onCreate方法中创建MethodChannel并且设置MethodCallHandler回调,确保channel名称与Flutter侧的一致.

    import io.flutter.app.FlutterActivity;
    import io.flutter.plugin.common.MethodCall;
    import io.flutter.plugin.common.MethodChannel;
    import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
    import io.flutter.plugin.common.MethodChannel.Result;
    
    public class MainActivity extends FlutterActivity {
        private static final String CHANNEL = "samples.flutter.io/battery";
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
            GeneratedPluginRegistrant.registerWith(this);
    
            new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
                    new MethodCallHandler() {
                        @Override
                        public void onMethodCall(MethodCall call, Result result) {
                            // TODO
                        }
                    });
        }
    }
    

    接下来,我们使用Android的电量API获取电量创建Android端java代码。
    onCreate方法下面创建一个新方法,如下:

    private int getBatteryLevel() {
      int batteryLevel = -1;
      if (VERSION.SDK_INT >= 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;
    }
    

    最后完成onMethodCall的回调

    @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();
        }
    }
    

    3.iOS平台使用Object-C实现

    首先,在application didFinishLaunchingWithOptions:方法中创建FlutterMethodChannel并且设置回调,确保channel名称与Flutter侧的一致.

    #import <Flutter/Flutter.h>
    #import "GeneratedPluginRegistrant.h"
    
    @implementation AppDelegate
    - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
      FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
    
      FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
                                              methodChannelWithName:@"samples.flutter.io/battery"
                                              binaryMessenger:controller];
    
      [batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
        // TODO
      }];
    
      [GeneratedPluginRegistrant registerWithRegistry:self];
      return [super application:application didFinishLaunchingWithOptions:launchOptions];
    }
    

    接下来实现获取电量方法

    - (int)getBatteryLevel {
      UIDevice* device = UIDevice.currentDevice;
      device.batteryMonitoringEnabled = YES;
      if (device.batteryState == UIDeviceBatteryStateUnknown) {
        return -1;
      } else {
        return (int)(device.batteryLevel * 100);
      }
    }
    
    __weak typeof(self) weakSelf = self
    [batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
      if ([@"getBatteryLevel" isEqualToString:call.method]) {
        int batteryLevel = [weakSelf getBatteryLevel];
    
        if (batteryLevel == -1) {
          result([FlutterError errorWithCode:@"UNAVAILABLE"
                                     message:@"Battery info unavailable"
                                     details:nil]);
        } else {
          result(@(batteryLevel));
        }
      } else {
        result(FlutterMethodNotImplemented);
      }
    }];
    

    相关文章

      网友评论

        本文标题:Flutter与Native数据交互,MethodChannel

        本文链接:https://www.haomeiwen.com/subject/eqaflqtx.html