Android端Flutter插件开发

一、简介

此文章主要记录本人的flutter插件开发过程以及遇到的问题等,如有错误请指正.

二、开发准备(Windows)

1.Android Studio 4.0以上
2.Flutter SDK

三、环境配置

1.安装flutter sdk

下载好之后,解压,找到根目录下的flutter文件下找到flutter_console.bat,双击运行并启动flutter命令行。

2.更新环境变量

要在终端运行 flutter 命令, 你需要添加以下环境变量到系统PATH:

转到 “控制面板>用户帐户>用户帐户>更改我的环境变量”
在“用户变量”下检查是否有名为“Path”的条目:
如果该条目存在, 追加 flutter\bin的全路径,使用 ; 作为分隔符.
如果条目不存在, 创建一个新用户变量 Path ,然后将 flutter\bin的全路径作为它的值.
在“用户变量”下检查是否有名为”PUB_HOSTED_URL”和”FLUTTER_STORAGE_BASE_URL”的条目,如果没有,也添加它们。
重启Windows以应用此更改

3.测试flutter环境

打开命令行输入:flutter doctor

flutter_plugin.png

如图可以看到有两个报错为插件工具没有导入可查看这里解决问题:
https://www.jianshu.com/p/3dc7dbd0712c

四、插件开发

1.使用Android Studio创建flutter插件

参照: https://www.jianshu.com/p/3dc7dbd0712c

2.编译插件桥接类

找到插件桥接类


微信截图_20210125172304.png

打开后可以看到很多红色报错,如下图可以点开新的AS界面进行编译:


微信截图_20201224104312.png
3.方法简介
onAttachedToEngine方法

初始化方法,"flutter_vin_plugin"为定义好的插件桥接类名,后面调用需要一一对应。

@Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
        channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "flutter_vin_plugin");
        channel.setMethodCallHandler(this);
    }
onMethodCall方法

接受从js层获取参数的方法"isCropImage"等都是传递的参数标识通过MethodCall 对象获取传递过来的数据
startScanVin等为自定义的原生方法,里面可以自定义一些操作

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
        resultPlugin = result;
        String isCrop = call.argument("isCropImage");
        ConstantConfig.isImportCrop = !TextUtils.isEmpty(isCrop) && isCrop.equals("1");
        ConstantConfig.isCheckMotorbike = Boolean.getBoolean(call.argument("containMoto") + "");
        initOcrFile();
        if (call.method.equals("scanVin")) { 
            startScanVin();
        } else if (call.method.equals("imageVin")) {  
            startImport();
        } else {
            unInitOcrApi();
            result.notImplemented();
        }
    }
onAttachedToActivity方法

此方法的包含一些原生的activity中的一些监听方法,添加监听后可实现对应的原生方法。
①addRequestPermissionsResultListener: 对应原生中的权限监听方法
②addActivityResultListener:对应原生中activity回调方法等一些有关activity生命周期的方法

@Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
        this.activity = binding.getActivity();
        binding.addRequestPermissionsResultListener(new PluginRegistry.RequestPermissionsResultListener() {
            @Override
            public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
                switch (requestCode) {
                    case SCAN_PERMISSION_CODE:
                        if (permissions.length != 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {//失败
                            Toast.makeText(activity, "请允许权限在识别", Toast.LENGTH_SHORT).show();
                        } else {//成功
                            //启动启动VIN码扫描识别页面
                            Intent intent = new Intent(activity, ScanVinActivity.class);
                            activity.startActivityForResult(intent, VIN_RECOG_CODE);
                        }
                        break;
                    case IMPORT_PERMISSION_CODE:
                        if (permissions.length != 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {//失败
                            Toast.makeText(activity, "请允许权限在识别", Toast.LENGTH_SHORT).show();
                        } else {//成功
                            //启动启动VIN码导入识别页面
                            Intent intent = new Intent(activity, VinRecogActivity.class);
                            activity.startActivityForResult(intent, VIN_RECOG_CODE);
                        }
                        break;
                }
                return false;
            }
        });
        binding.addActivityResultListener(new PluginRegistry.ActivityResultListener() {
            @Override
            public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
                if (data != null && requestCode == VIN_RECOG_CODE) {
                    //接收所有识别结果,图片
                    String vinResult = data.getStringExtra("vinResult");
                    //接收识别结果的状态码,0表示成功,其他值表示识别失败
                    int recogCode = data.getIntExtra("recogCode", -1);
                    String vinThumbPath = data.getStringExtra("vinThumbPath");
                    String vinAreaPath = data.getStringExtra("vinAreaPath");
                    Map map = new HashMap<>();
                    map.put("ocrResult", vinResult);
                    map.put("ocrThumbPath", vinThumbPath);
                    map.put("ocrAreaPath", vinAreaPath);
                    resultPlugin.success(map);
                }
                return false;
            }
        });
    }

到此插件部分已经开发的差不多了

五、引用插件

1.在插件中的demo调用测试

找到插件目录下的lib文件夹下的文件打开如下;


微信截图_20210128104358.png

此文件为插件原生与js端沟通的桥梁所有的方法交互都需要通过此方法
如下图,一共定义几个方法,比如licName等参数是js传递过来的参数,将这些参数放入param中,通过我们上面定义的flutter_vin_plugin的对象_channel执行invokeMethod方法调用原生并声明原生中的方法名scanVin以及传递js端数据集合param,,通过map接受原生中返回的数据即可.


微信截图_20210128105151.png

找到js端主页
微信截图_20210128110329.png

打开后可以定义我们在桥接中定义好的方法名称


微信截图_20210128110637.png

下面在main.dart中定义对应调用的方法:
result为从原生获取的数据_resultOcr为定义好的变量.
    Future scanVin() async {
      Map result;
    // 参数说明 ("授权文件名称","是否屏蔽部分校验规则") 0为false 1为true
      result = await FlutterVinPlugin.scanVin("7332DBAFD2FD18301EF6", "0"); // TODO 扫描识别
      setState(() {
        _resultMap = result;
        _resultOcr = _resultMap['ocrResult'];
        _resultThumbPath = _resultMap['ocrThumbPath'];
        _resultAreaPath = _resultMap['ocrAreaPath'];
      });
    }

然后即可在view中点击监听调用:


微信截图_20210128110842.png

main.dart中这里不多做描述了,具体可以查看官方文档学习如何开发。

2.在实际项目中调用测试
①将插件复制进Flutter项目目录中
②Flutter项目中的pubspec.yaml文件,进行如下图配置,path根据自己的插件的相对路径配置
图片1.png
③在你的项目中打开pubspec.yam文件执行插件引用如图:
图片2.png
④在你的项目中打开example下GeneratedPluginRegistrant.Java代码,可以看到这里已经成功引用了FlutterVinPlugin插件如图
图片3.png

六、调试运行

微信截图_20210128113627.png

运行成功


微信截图_20210128113700.png

你可能感兴趣的:(Android端Flutter插件开发)