Android端Flutter插件開發(fā)

一、簡介

此文章主要記錄本人的flutter插件開發(fā)過程以及遇到的問題等,如有錯(cuò)誤請(qǐng)指正.

二、開發(fā)準(zhǔn)備(Windows)

1.Android Studio 4.0以上
2.Flutter SDK

三、環(huán)境配置

1.安裝flutter sdk

下載好之后,解壓,找到根目錄下的flutter文件下找到flutter_console.bat,雙擊運(yùn)行并啟動(dòng)flutter命令行。

2.更新環(huán)境變量

要在終端運(yùn)行 flutter 命令, 你需要添加以下環(huán)境變量到系統(tǒng)PATH:

轉(zhuǎn)到 “控制面板>用戶帳戶>用戶帳戶>更改我的環(huán)境變量”
在“用戶變量”下檢查是否有名為“Path”的條目:
如果該條目存在, 追加 flutter\bin的全路徑,使用 ; 作為分隔符.
如果條目不存在, 創(chuàng)建一個(gè)新用戶變量 Path ,然后將 flutter\bin的全路徑作為它的值.
在“用戶變量”下檢查是否有名為”PUB_HOSTED_URL”和”FLUTTER_STORAGE_BASE_URL”的條目,如果沒有,也添加它們。
重啟Windows以應(yīng)用此更改

3.測試flutter環(huán)境

打開命令行輸入:flutter doctor

flutter_plugin.png

如圖可以看到有兩個(gè)報(bào)錯(cuò)為插件工具沒有導(dǎo)入可查看這里解決問題:
http://www.itdecent.cn/p/3dc7dbd0712c

四、插件開發(fā)

1.使用Android Studio創(chuàng)建flutter插件

參照: http://www.itdecent.cn/p/3dc7dbd0712c

2.編譯插件橋接類

找到插件橋接類


微信截圖_20210125172304.png

打開后可以看到很多紅色報(bào)錯(cuò),如下圖可以點(diǎn)開新的AS界面進(jìn)行編譯:


微信截圖_20201224104312.png
3.方法簡介
onAttachedToEngine方法

初始化方法,"flutter_vin_plugin"為定義好的插件橋接類名,后面調(diào)用需要一一對(duì)應(yīng)。

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

接受從js層獲取參數(shù)的方法"isCropImage"等都是傳遞的參數(shù)標(biāo)識(shí)通過MethodCall 對(duì)象獲取傳遞過來的數(shù)據(jù)
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中的一些監(jiān)聽方法,添加監(jiān)聽后可實(shí)現(xiàn)對(duì)應(yīng)的原生方法。
①addRequestPermissionsResultListener: 對(duì)應(yīng)原生中的權(quán)限監(jiān)聽方法
②addActivityResultListener:對(duì)應(yīng)原生中activity回調(diào)方法等一些有關(guān)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, "請(qǐng)?jiān)试S權(quán)限在識(shí)別", Toast.LENGTH_SHORT).show();
                        } else {//成功
                            //啟動(dòng)啟動(dòng)VIN碼掃描識(shí)別頁面
                            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, "請(qǐng)?jiān)试S權(quán)限在識(shí)別", Toast.LENGTH_SHORT).show();
                        } else {//成功
                            //啟動(dòng)啟動(dòng)VIN碼導(dǎo)入識(shí)別頁面
                            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) {
                    //接收所有識(shí)別結(jié)果,圖片
                    String vinResult = data.getStringExtra("vinResult");
                    //接收識(shí)別結(jié)果的狀態(tài)碼,0表示成功,其他值表示識(shí)別失敗
                    int recogCode = data.getIntExtra("recogCode", -1);
                    String vinThumbPath = data.getStringExtra("vinThumbPath");
                    String vinAreaPath = data.getStringExtra("vinAreaPath");
                    Map<String, String> map = new HashMap<>();
                    map.put("ocrResult", vinResult);
                    map.put("ocrThumbPath", vinThumbPath);
                    map.put("ocrAreaPath", vinAreaPath);
                    resultPlugin.success(map);
                }
                return false;
            }
        });
    }

到此插件部分已經(jīng)開發(fā)的差不多了

五、引用插件

1.在插件中的demo調(diào)用測試

找到插件目錄下的lib文件夾下的文件打開如下;


微信截圖_20210128104358.png

此文件為插件原生與js端溝通的橋梁所有的方法交互都需要通過此方法
如下圖,一共定義幾個(gè)方法,比如licName等參數(shù)是js傳遞過來的參數(shù),將這些參數(shù)放入param中,通過我們上面定義的flutter_vin_plugin的對(duì)象_channel執(zhí)行invokeMethod方法調(diào)用原生并聲明原生中的方法名scanVin以及傳遞js端數(shù)據(jù)集合param,,通過map接受原生中返回的數(shù)據(jù)即可.


微信截圖_20210128105151.png

找到j(luò)s端主頁
微信截圖_20210128110329.png

打開后可以定義我們?cè)跇蚪又卸x好的方法名稱


微信截圖_20210128110637.png

下面在main.dart中定義對(duì)應(yīng)調(diào)用的方法:
result為從原生獲取的數(shù)據(jù)_resultOcr為定義好的變量.
    Future<void> scanVin() async {
      Map<String, String> result;
    // 參數(shù)說明 ("授權(quán)文件名稱","是否屏蔽部分校驗(yàn)規(guī)則") 0為false 1為true
      result = await FlutterVinPlugin.scanVin("7332DBAFD2FD18301EF6", "0"); // TODO 掃描識(shí)別
      setState(() {
        _resultMap = result;
        _resultOcr = _resultMap['ocrResult'];
        _resultThumbPath = _resultMap['ocrThumbPath'];
        _resultAreaPath = _resultMap['ocrAreaPath'];
      });
    }

然后即可在view中點(diǎn)擊監(jiān)聽調(diào)用:


微信截圖_20210128110842.png

main.dart中這里不多做描述了,具體可以查看官方文檔學(xué)習(xí)如何開發(fā)。

2.在實(shí)際項(xiàng)目中調(diào)用測試
①將插件復(fù)制進(jìn)Flutter項(xiàng)目目錄中
②Flutter項(xiàng)目中的pubspec.yaml文件,進(jìn)行如下圖配置,path根據(jù)自己的插件的相對(duì)路徑配置
圖片1.png
③在你的項(xiàng)目中打開pubspec.yam文件執(zhí)行插件引用如圖:
圖片2.png
④在你的項(xiàng)目中打開example下GeneratedPluginRegistrant.Java代碼,可以看到這里已經(jīng)成功引用了FlutterVinPlugin插件如圖
圖片3.png

六、調(diào)試運(yùn)行

微信截圖_20210128113627.png

運(yùn)行成功


微信截圖_20210128113700.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容