Flutter插件詳解及其發布插件

前言?

?
? ? ? ? ? ? ? ?
Flutter提供了和原生做交互的方式,有了和原生交互這個功能,我們就可以達到Flutter調用原生平臺的相關功能的目的。換句話說,Flutter做不到的事(比如:設備有關的、第三方SDK、長連接等),我們都可以通過Flutter與原生交互來做到,其中插件的編寫是必不可少的一個過程,所以我們一定要掌握插件的編寫。?

有人會說:“網上不是有很多插件庫嗎?” 沒錯!但是如果別人寫的插件功能沒有你想要的功能怎么辦?如果插件與你本地不兼容怎么辦?如果你的項目急用一個功能,網上找不到插件庫怎么辦?那么這個時候學會自己編寫插件庫就非常有必要了!? ? ? ? ? ? ? ? ? ? ? ?


? ?
本文的源碼發布在GitHub上,如果有什么問題,歡迎留言。
? ? ? ?

https://github.com/AweiLoveAndroid/flutter_device_information

下面詳細的講解一下Flutter如何創建一個插件,讓大家快速學會自己寫一個插件。同時在這里也教大家上傳到Pub庫,讓大家也體驗一把自己的庫被別人使用的自豪感和成就感。

1 Flutter調用原生平臺交互過程

這里以調用原生平臺設備信息為例做講解。手把手教大家寫一個Flutter插件。Flutter中通過MethodChannel和原生平臺做交互。如圖所示:

2 創建Flutter Plugin插件項目

如果是使用Android Studio/Intellij IDEA創建項目,截圖如下:

如果使用命令行的方式,可以使用?flutter create?命令行創建,項目名稱放在最后,具體命令如下所示:

flutter?create?--org?com.awei?--template=plugin?-a?java?--description?"A?Flutter?plugin?for?using?devices?informations?in?Android"?flutter_device_information
▲ 左右滑動查看更多

常用的命令參數如下:

  • --org:定義項目的組織結構? ? ? ? ? ? ?
  • ?-a:用什么語言編寫Android代碼? ? ? ? ? ?
  • ?--description:插件的描述?
  • ?-i:用什么語言編寫iOS代碼? ?? ? ? ? ??

上面那個命令的意思是:創建一個插件,包名為“com.awei”,指定Android代碼使用Java語言編寫,插件項目名稱為“flutter_device_information”,項目描述為:“A Flutter plugin for using devices informations in Android”。

3 完整的目錄結構

下面看一下完整的目錄結構,如下圖所示:

其中:

?“android”目錄:是插件API在Android平臺的實現。? ? ? ? ? ?

?“ios”目錄:是插件API在iOS平臺的實現。? ? ?

?“example”目錄:是使用插件的一個示例項目。

?“lib”目錄里面的文件:主要是創建“MethodChannel”,然后接收并處理來自原生平臺發來的消息。 ? ? ?

4 插件編寫步驟

1.創建MethodChannel對象

打開?flutter_device_information.dart?文件,開始創建?MethodChannel?對象,參數是自己協定的,后面的原生平臺需要用到的這個參數,每一個?MethodChannel?對象的這個參數是唯一的標識符,必須記住。如下所示:

import?'package:flutter/services.dart';
class?FlutterDeviceInformation?{
? ?static?const?MethodChannel?_channel?=
? ?const?MethodChannel('com.awei.devices/flutter_device_information');
}

2.Android端接收消息并做出相應的處理? ?

打開文件?FlutterDeviceInformationPlugin.java,然后接收MethodChannel?傳過來的消息。如下所示:

 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;
 import?io.flutter.plugin.common.PluginRegistry.Registrar;



 7public?class?FlutterDeviceInformationPlugin?implements?MethodCallHandler?{

??/**

??*?Plugin?registration.?插件注冊

??*/

??public?static?void?registerWith(Registrar?registrar)?{

????final?MethodChannel?channel?=?new?MethodChannel(

????registrar.messenger(),?"?com.awei.devices/flutter_device_information?");

????//?設置setMethodCallHandler回調??處理Flutter端的調用

????channel.setMethodCallHandler(new?FlutterDeviceInformationPlugin());

??}



[email protected]

??public?void?onMethodCall(MethodCall?call,?Result?result)?{

????if?(call.method.equals("getPlatformVersion"))?{

??????result.success("Android?"?+?android.os.Build.VERSION.RELEASE);

????}??else?{

??????result.notImplemented();

????}

??}

}

其中:registerWith?函數是Plugin registration. 插件注冊,它里面設置setMethodCallHandler回調 處理Flutter端的調用。 FlutterDeviceInformationPlugin?類實現?MethodCallHandler?接口,重寫方法?onMethodCall,MethodCall?和?Result?主要是用來執行相關的邏輯判斷。

3.Dart代碼獲取原生平臺的消息? ? ? ?

打開?flutter_device_information.dart?文件,其中的platformVersion函數獲取的是原生平臺的系統版本號:

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

 import?'dart:async';



 class?FlutterDeviceInformation?{

 ??//?獲取的是原生平臺的系統版本號

 ??static?Future<String>?get?platformVersion?async?{

 ????final?String?version?=?await?_channel.invokeMethod('getPlatformVersion');

 ????return?version;

 ??}

}

4.Dart代碼調用插件里面的Dart代碼? ? ? ?

打開?main.dart?文件:

 import?'dart:async';



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

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

 import?'package:flutter_device_information/flutter_device_information.dart';



 void?main()?=>?runApp(MyApp());



 class?MyApp?extends?StatefulWidget?{

 [email protected]

??_MyAppState?createState()?=>?return?_MyAppState();

}



class?_MyAppState?extends?State<MyApp>?{

??String?_platformVersion?=?'Unknown';



[email protected]

??void?initState()?{

????super.initState();

????initPlatformState();

??}



??//?Platform?messages?are?asynchronous,?so?we?initialize?in?an?async?method.

??Future<void>?initPlatformState()?async?{

????String?platformVersion;



????//?Platform?messages?may?fail,?so?we?use?a?try/catch?PlatformException.

????try?{

??????platformVersion?=?await?FlutterDeviceInformation.platformVersion;

????}?on?PlatformException?{

??????platformVersion?=?'Failed?to?get?platform?version.';

????}



????//?If?the?widget?was?removed?from?the?tree?while?the?asynchronous?platform

????//?message?was?in?flight,?we?want?to?discard?the?reply?rather?than?calling

????//?setState?to?update?our?non-existent?appearance.

????if?(!mounted)?return;



????setState(()?{

??????_platformVersion?=?platformVersion;

????});

??}



[email protected]

??Widget?build(BuildContext?context)?{

????return?MaterialApp(

??????home:?Scaffold(

????????appBar:?AppBar(

??????????title:?const?Text('Plugin?example?app'),

????????),

????????body:?Center(

??????????child:?Text('Running?on:?$_platformVersion'),

????????),

??????),

????);

??}

}

上面代碼定義了一個變量“_platformVersion”,用于存儲版本號信息。“initPlatformState ()”函數是異步的,用于接收來自平臺的消息,里面有一個局部變量“platformVersion”。“try...catch”語句是捕獲異常。“setState((){...})”函數把我們獲取到的“platformVersion”賦值給“_platformVersion”,來更新“_platformVersion”的值。

5.新增和完善插件代碼? ? ? ?

上述代碼中,只是默認創建的示例代碼,下面來看看在?flutter_device_information.dart?中新增函數,獲取Android的其它設備信息。新增的代碼如下:

 static?Future<String>?get?sdkInt?async?{

 ??final?String?version?=?await?_channel.invokeMethod('getSDKINT');

 ??return?version;

 }



 static?Future<String>?get?board?async?{

 ??final?String?version?=?await?_channel.invokeMethod('getBoard');

 ??return?version;

 }



static?Future<String>?get?brand?async?{

??final?String?version?=?await?_channel.invokeMethod('getBrand');

??return?version;

}



static?Future<String>?get?model?async?{

??final?String?version?=?await?_channel.invokeMethod('getModel');

??return?version;

}



static?Future<String>?get?CPUABI?async?{

??final?String?version?=?await?_channel.invokeMethod('getCPUABI');

??return?version;

}

▲ 左右滑動查看更多

6.新增和完善原生平臺代碼 ? ? ??

修改 FlutterDeviceInformationPlugin.java 文件,如下所示:

 import?'dart:async';



 if?(call.method.equals("getPlatformVersion"))?{

 ??result.success("Android?release系統版本(字符串類型):"?+?android.os.Build.VERSION.RELEASE);

 }?else?if(call.method.equals("getSDKINT")){

 ??result.success("Android?API版本(int類型):"?+?android.os.Build.VERSION.SDK_INT);

 }?else?if(call.method.equals("getBoard")){

 ??result.success("主板型號:"?+?android.os.Build.BOARD);

 }?else?if(call.method.equals("getBrand")){

??result.success("產品品牌(or系統制造商):"?+?android.os.Build.BRAND);

}?else?if(call.method.equals("getModel")){

??result.success("手機的型號/設備名稱:"?+?android.os.Build.MODEL);

}?else?if(call.method.equals("getCPUABI")){

??result.success("設備指令集名稱(CPU的類型):"?+?android.os.Build.CPU_ABI);

}?else?{

??result.notImplemented();

}

5 發布插件到Pub庫

下面講一下如何把插件發布到Pub庫。

1.運行“flutter?packages?pub?publish?--dry?run”

首先運行“flutter?packages?pub?publish?--dry?run”命令,查看是否所有內容都通過分析。(需要翻墻)但是:如果設置了國內鏡像,這個命令經常會出錯,為了避免出錯,建議在命令后面加上服務器地址,命令如下所示:

flutter?packages?pub?publish?--server=https://pub.dartlang.org

▲ 左右滑動查看更多

2.然后按提示輸入“y/n”,輸入“y”,回車

3.然后把命令行出現的網址復制到瀏覽器打開

4.耐心等待,出現Successfully uploaded package表示上傳成功

5.我們可以在Pub上面搜索我們的庫

例如:剛發的的庫的地址為:

https://pub.dartlang.org/packages/flutter_device_information

6.庫的API文檔會自動發布到dartdocs.org

例如:我們剛才發布的庫的API文檔地址為:

https://pub.dartlang.org/documentation/flutter_device_information/latest/?


?

最多閱讀

在Flutter中添加資源和圖片 10月以前  |  1697次閱讀
發布Flutter開發的iOS程序 10月以前  |  1159次閱讀
Flutter Widget框架概述 10月以前  |  1022次閱讀
在Flutter中發起HTTP網絡請求 10月以前  |  977次閱讀
JSON和序列化 10月以前  |  920次閱讀
使用Inspector檢查用戶界面 10月以前  |  880次閱讀
Flutter框架概覽 10月以前  |  861次閱讀
使用自定義字體 10月以前  |  834次閱讀
為Flutter應用程序添加交互 10月以前  |  812次閱讀
處理文本輸入 10月以前  |  702次閱讀
發布Flutter開發的Android程序 10月以前  |  637次閱讀
使用包來開發Flutter應用 10月以前  |  623次閱讀
編寫國際化Flutter App 10月以前  |  596次閱讀
Dart 語法預覽 10月以前  |  592次閱讀
使用平臺通道編寫平臺特定的代碼 10月以前  |  582次閱讀
Flutter的手勢GestureDetector分析詳解 6月以前  |  507次閱讀
期待已久,Flutter 1.0 正式發布! 10月以前  |  502次閱讀
Flutter插件詳解及其發布插件 6月以前  |  446次閱讀
Flutter 狀態管理指南之 Provider 6月以前  |  436次閱讀

25选5玩法中奖