flutter與原生通信主要有三種方式:MethodChannel、EventChannel、BasicMessageChannel,這三種方式均各有適用的場(chǎng)景:MethodChannel用于native與flutter的方法調(diào)用,EventChannel用于native單向的向flutter發(fā)送廣播消息,BasicMessageChannel用于native與flutter之間的消息互發(fā)。
創(chuàng)新互聯(lián)公司主營(yíng)赤壁網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,成都App定制開(kāi)發(fā),赤壁h5成都微信小程序搭建,赤壁網(wǎng)站營(yíng)銷(xiāo)推廣歡迎赤壁等地區(qū)企業(yè)咨詢(xún)
MethodChannel用于雙方之間的方法互調(diào),使用步驟是:
1.創(chuàng)建一個(gè)MethodChannel對(duì)象,傳入MethodChannel名稱(chēng)。
2.使用setMethodHandle對(duì)對(duì)方調(diào)用自己的方法進(jìn)行監(jiān)聽(tīng),通過(guò)回調(diào)中的MethodCall對(duì)象方法名判斷、獲取方法參數(shù),并且返回調(diào)用結(jié)果。
3.使用invokeMethod來(lái)調(diào)用對(duì)方的方法,可傳入方法名,方法參數(shù),以及監(jiān)聽(tīng)對(duì)方的回調(diào)結(jié)果。
以下是示例:
需要注意的是,MethodChannel的名稱(chēng)需要雙方保持一致,否則就不是同一個(gè)MethodChannel了。另外這里的方法調(diào)用并不是像Java里面反射那樣去先找到class示例對(duì)象再解析到相應(yīng)的方法,而是將雙方互發(fā)的消息包裝成了MethodCall對(duì)象,拿到這個(gè)對(duì)象后通過(guò)MethodCall里面的方法名去判斷要做什么操作,并不是直接就調(diào)用了自身(native或flutter)相對(duì)應(yīng)的方法。具體要做什么操作、調(diào)用什么方法還是得自己去調(diào)用和實(shí)現(xiàn)。
EventChannel適用于native向flutter發(fā)送廣播消息,只是單向的消息發(fā)送,native發(fā),flutter收,返過(guò)來(lái)flutter并不能向native發(fā)送消息。例如native可將定位數(shù)據(jù)不斷的報(bào)給flutter,或者錄像數(shù)據(jù)等等,所有基于原生能力產(chǎn)生的數(shù)據(jù)都可以通過(guò)EventChannel進(jìn)行發(fā)送。
步驟:
1.創(chuàng)建一個(gè)EventChannel對(duì)象,傳入EventChannel名稱(chēng)。
2.flutter端調(diào)用receiveBroadcastStream進(jìn)行廣播消息注冊(cè),傳入arguments參數(shù)即為廣播名稱(chēng),此參數(shù)是告訴native端你要接受的廣播類(lèi)型,判別是什么廣播發(fā)送的數(shù)據(jù)。
2.native調(diào)用setStreamHandler方法進(jìn)行廣播消息監(jiān)聽(tīng),onListen回調(diào)里會(huì)有一個(gè)arguments參數(shù),這里及為flutter注冊(cè)的廣播類(lèi)型,若flutter端沒(méi)有注冊(cè),則native端不會(huì)收到這個(gè)回調(diào),也就無(wú)法進(jìn)行消息發(fā)送。收到flutter端的廣播注冊(cè)后,根據(jù)arguments可判斷廣播類(lèi)型,然后根據(jù)EventChannel.EventSink來(lái)進(jìn)行消息發(fā)送,EventSink.success()即可將消息發(fā)送給flutter端。
3.flutter進(jìn)行廣播注冊(cè)會(huì)返回一個(gè)streamSubscription類(lèi)型的對(duì)象,該對(duì)象可以進(jìn)行消息的停止,native可在onCancel回調(diào)里面收到。
示例如下:
BasicMessageChannel就是比較常用的消息互發(fā),使用步驟如下:
1.創(chuàng)建BasicMessageChannel對(duì)象,傳入BasicMessageChannel名稱(chēng)。還需傳入編解碼方式(可以自己實(shí)現(xiàn)),系統(tǒng)提供了一些列的編解碼方式,后續(xù)會(huì)介紹到。
2.使用setMessageHandler方法進(jìn)行消息監(jiān)聽(tīng),也可進(jìn)行回復(fù)。
3.使用send方法進(jìn)行消息發(fā)送。
無(wú)論哪種方式的消息傳遞,最終都是將自定義數(shù)據(jù)轉(zhuǎn)化為二進(jìn)制數(shù)據(jù)進(jìn)行傳遞,flutter提供的編解碼方式分為MethodCodec和MessageCodec兩種,EventChannel和MethodChannel使用的就是MethodCodec,BasicMessageChannel使用的是MessageCodec。MethodCodec其實(shí)就是在MessageCodec的基礎(chǔ)上將數(shù)據(jù)包裝了一下,使其轉(zhuǎn)化為MethodCall對(duì)象方便使用。
MethodCodec源碼:
MethodCodec提供了兩種方式:JSONMethodCodec和StandardMethodCodec,前一種就是JSON和MethodCall對(duì)象之間的互轉(zhuǎn),后一種則是根據(jù)傳入的數(shù)據(jù)基本類(lèi)型(String,Integer等)來(lái)進(jìn)行互轉(zhuǎn)。
MessageCodec則提供了四種方式,如下圖,具體就不詳細(xì)講述了,看看名字就知道是怎么回事,可以直接去看源碼。最常用和默認(rèn)的就是StandardMessageCodec方式。
從上面的使用方式可以看出,每一種Channel在創(chuàng)建的時(shí)候都需要傳遞一個(gè)BinaryMessenger,這個(gè)接口可以在FlutterEngine里面拿到,因此需要在FlutterActivity里面實(shí)現(xiàn)configFlutterEngine方法里面重寫(xiě)這個(gè)方法。FlutterActivity在attach FlutterEngine之后就會(huì)調(diào)用這個(gè)configFlutterEngine方法,通過(guò)flutterEngine.getPlugins().add(FlutterPlugin)方法可以FlutterPlugin的回調(diào)方法里進(jìn)行數(shù)據(jù)的初始化和銷(xiāo)毀工作。如下圖
這個(gè)回調(diào)方法里的FlutterPluginBinding提供了一些我們可能會(huì)用到的對(duì)象,如下:
一、 MethodChannel
主要是flutter端調(diào)用android方法。flutter調(diào)取android方法,也可以android主動(dòng)跟flutter通信,但是這個(gè)只能是傳遞數(shù)據(jù),不是調(diào)方法。MethodChannel的flutter調(diào)取android方法,我之前寫(xiě)過(guò),可以查看如下鏈接,
Android主動(dòng)跟flutter通信,如下
二、 BasicMessageChannel
它是可以雙端通信的,flutter端可以給Android發(fā)送消息,Android也可以給Flutter發(fā)送消息。
三、EventChannel
只能是原生發(fā)送消息給Flutter端,例如監(jiān)聽(tīng)手機(jī)電量變化,網(wǎng)絡(luò)變化,傳感器等。
打印結(jié)果如下:
總結(jié)一下:
MethodChannel 用于傳遞方法調(diào)用(method invocation),是flutter調(diào)取原生方法的,也可以原生主動(dòng)傳遞數(shù)據(jù)給Flutter。
BasicMessageChannel 用于傳遞字符串和半結(jié)構(gòu)化的信息。是兩個(gè)端相互發(fā)送數(shù)據(jù),接收數(shù)據(jù)的。
EventChannel 用于數(shù)據(jù)流(event streams)的通信。通長(zhǎng)用于Nativie向flutter的通信,如:手機(jī)電量變化,網(wǎng)絡(luò)連接變化,陀螺儀,傳感器等;
tip:多種類(lèi)型的通道混用可能會(huì)出現(xiàn)報(bào)錯(cuò)問(wèn)題。
ps:使用flutter開(kāi)發(fā)app 與 設(shè)備硬件交互 要求使用udp通信?
flutter UPD通信 ?基于這大神的文章下進(jìn)行修改的。
數(shù)據(jù)結(jié)構(gòu)
flutter 數(shù)據(jù)結(jié)構(gòu)中
Uint8List是一個(gè)固定長(zhǎng)度的8位無(wú)符號(hào)整數(shù)列表。(感覺(jué)跟byte類(lèi)型差不多 都是占用1字節(jié) 0-255)
1. Listint ?或 Uint8List轉(zhuǎn) int ? 要注意list的高低位
int byteToNum(Listint list) {
Uint8List resultList = Uint8List.fromList(list);
ByteData byteData = ByteData.view(resultList.buffer);
print(byteData);
return byteData.getInt16(0);
}
2.將字符串轉(zhuǎn)成listint 并指定長(zhǎng)度(字符串占用的字節(jié))
3. ?10進(jìn)制int 轉(zhuǎn) 16 進(jìn)制listint。
其實(shí)這里應(yīng)該是uint8list的。1字節(jié)。length 字節(jié)長(zhǎng)度
設(shè)備正常使用 ? 有問(wèn)題的方面。歡迎大家指出?