flutter调用android原生插件功能的示例

做过很多的混合开发项目,有一些要调用系统API的功能还是需要原生开发人员提供相关的SDK插件来实现,还有特定一些需求,比如开发个水印相机等,Android开发的插件SDK一般都是以.aar提供,那么flutter怎么和原生交互呢?下面我们就通过一个简单的Toast案例了解一下


核心API MethodChannel就是负责flutter和Android交互


  • 首先flutter端准备工作
    1、定义通道 static const platform = const MethodChannel('com.itplus.io/toast');
    2、调用方法 platform.invokeMethod("showToast");showToast 就是Android端用来过滤调用的方法

具体代码如下:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ToastPlugin extends StatefulWidget {
  @override
  _ToastPluginState createState() => _ToastPluginState();
}

class _ToastPluginState extends State<ToastPlugin> {
  static const platform = const MethodChannel('com.itplus.io/toast');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("flutter调用Android原生功能"),
        ),
        body: Center(
          child: RaisedButton(
            child: Text("弹个Toast"),
            onPressed: () {
              _showAndroidNativeToast();
            },
          ),
        ));
  }

  _showAndroidNativeToast() async{
    platform.invokeMethod("showToast");
  }
}

  • Android端具体实现
    1、找到Android 的MainActivity
    2、在onCreate方法中创建MethodChannel,并设置MethodCallHandler
    3、定义和flutter中相同的通道值private val CHANNEL = "com.itplus.io/toast"必须保持一致

具体代码如下:
【kotlin版本】

class MainActivity: FlutterActivity() {
  private val CHANNEL = "com.itplus.io/toast"
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    GeneratedPluginRegistrant.registerWith(this)
    MethodChannel(flutterView, CHANNEL).setMethodCallHandler { call, result ->
      if (call.method == "showToast") {
        Toast.makeText(this,"flutter 调用 Android 原生",0).show();
        result.success("ok")
      } else {
        result.notImplemented()
      }
    }
  }
}

【java版本】

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "com.itplus.io/toast";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
          new MethodCallHandler() {
             @Override
             public void onMethodCall(MethodCall call, Result result) {
                  if ( "showToast".equal(call.method) {
                     Toast.makeText(this,"flutter 调用 Android 原生",0).show();
                      result.success("ok")
                   } else {
                    result.notImplemented()
                   }
             }
          });
    }
}

在这里插入图片描述


上面的例子很简单,就是弹出个Toast,要是传递过来参数弹出提示怎么搞呢?
  • Future<T> invokeMethod<T>(String method, [ dynamic arguments ])invokeMethod有个可选参数arguments,我们可以通过这个参数给Android端传递参数
 _showAndroidNativeToast() async{
    //platform.invokeMethod("showToast"); 修改如下
    platform.invokeMethod("showToast","我是来自flutter的参数");
  }
  • Android端MethodCall有个参数 public final Object arguments;用来接收flutter端传过来的参数
 MethodChannel(flutterView, CHANNEL).setMethodCallHandler { call, result ->
      if (call.method == "showToast") {
//        Toast.makeText(this,"flutter 调用 Android 原生",0).show();
          Toast.makeText(this,call.arguments.toString(),0).show();
          result.success("ok")
      } else {
          result.notImplemented()
      }
    }

在这里插入图片描述

如果flutter需要获取一个返回值怎么搞呢?
  • MethodChannel类有个内部接口Result,可以通过这个接口返回想要的值
    在这里插入图片描述
    比如,我们可以在flutter中获取一个结果返回结果 ,android 中用
result.Success(Object)

在这里插入图片描述

如下操作

  _showAndroidNativeToast() async {
//    platform.invokeMethod("showToast");
    var result = await platform.invokeMethod("showToast", "我是来自flutter的参数");
    print("获取android返回结果:");
    print(result);
  }

返回结果如图:
在这里插入图片描述


最后附上MethodCall源码:

public final class MethodCall {
    public final String method;
    public final Object arguments;

    public MethodCall(String method, Object arguments) {
        if (method == null) {
            throw new AssertionError("Parameter method must not be null.");
        } else {
            this.method = method;
            this.arguments = arguments;
        }
    }

    public <T> T arguments() {
        return this.arguments;
    }
    /***
    *  可以看到json和Map都已经帮我处理了
    */
    @Nullable
    public <T> T argument(String key) {
        if (this.arguments == null) {
            return null;
        } else if (this.arguments instanceof Map) {
            return ((Map)this.arguments).get(key);
        } else if (this.arguments instanceof JSONObject) {
            return ((JSONObject)this.arguments).opt(key);
        } else {
            throw new ClassCastException();
        }
    }

    public boolean hasArgument(String key) {
        if (this.arguments == null) {
            return false;
        } else if (this.arguments instanceof Map) {
            return ((Map)this.arguments).containsKey(key);
        } else if (this.arguments instanceof JSONObject) {
            return ((JSONObject)this.arguments).has(key);
        } else {
            throw new ClassCastException();
        }
    }
}


总结

   我们要调用具体插件的方法都是有call.method 决定的,直接switch去不同的方法,跟Cordova中的action类似
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值