Flutter Plugin 開(kāi)發(fā)過(guò)程,詳細(xì)記錄

Demo地址

準(zhǔn)備

1、nav端(ios、android)調(diào)試原生實(shí)現(xiàn)。
2、flutter_app(一個(gè)), 調(diào)試插件。
3、flutter_plugin(一個(gè)), 寫(xiě)插件。

三種Channel

BasicMessageChannel:用于傳遞字符串和半結(jié)構(gòu)化的信息
MethodChannel:用于傳遞方法調(diào)用(method invocation)
EventChannel:用于數(shù)據(jù)流(event streams)的通信


BinaryMessage.png

Flutter端對(duì)三種Channel的書(shū)寫(xiě)

1、定義

//字符串需和原生保持一致
  MethodChannel _methodChannel = MethodChannel("flutter/live/methodChannel");
  EventChannel _eventChannel = EventChannel("flutter/live/eventChannel");
  BasicMessageChannel _messageChannel = BasicMessageChannel("flutter/live/messageChannel", StandardMessageCodec());

2、原生調(diào)用Flutter

_methodChannel.setMethodCallHandler((call) async {
      print('_methodChannel 收到:' + call.toString());
    });
_eventChannel.receiveBroadcastStream().listen((event) {
      print('_eventChannel 收到:' + event);
    });
_messageChannel.setMessageHandler((message) async {
      print('_messageChannel 收到:' + message);
    });

3、Flutter調(diào)用原生

_methodChannel.invokeMethod("startLive",{"url" : "rtmp://192.168.101.164"});

Map msg = {"startLive":"rtmp://192.168.101.164"};
                _messageChannel.send(msg);

原生端實(shí)現(xiàn)書(shū)寫(xiě)

兩種方案
1、創(chuàng)建flutter plugin項(xiàng)目。

dio: ^3.0.6
  • 1.2 本地引用
flutter_ijkplayer:
    path:
      plugins/flutter_ijkplayer

2、直接在Flutter項(xiàng)目文件夾下的iOS文件夾和Android文件夾中寫(xiě)實(shí)現(xiàn)邏輯,所以這種方案只能在本項(xiàng)目使用。

iOS端對(duì)三種Channel的書(shū)寫(xiě)

1、創(chuàng)建
- (void)createMethodChannel:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterMethodChannel* methodChannel = [FlutterMethodChannel
    methodChannelWithName:@"flutter/live/methodChannel"
          binaryMessenger:[registrar messenger]];
    [registrar addMethodCallDelegate:self channel:methodChannel];
}
- (void)createEventChannel:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:@"flutter/live/eventChannel" binaryMessenger:[registrar messenger]];
    [eventChannel setStreamHandler:self];
}
- (void)createMessageChannel:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterBasicMessageChannel *messageChannel = [FlutterBasicMessageChannel messageChannelWithName:@"flutter/live/messageChannel" binaryMessenger:[registrar messenger]];
    [messageChannel setMessageHandler:^(id  _Nullable message, FlutterReply  _Nonnull callback) {
        NSLog(@"MessageChannel 收到:%@",message);
//        NSString *method=message[@"method"];
//        if ([method isEqualToString:@"startLive"]) {
//            NSLog(@"Flutter MessageChannel 收到:startLive");
//        }
    }];
}
2、監(jiān)聽(tīng)回調(diào)

1、MethodChannel

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {

  if ([call.method isEqualToString:@"startLive"]) {
      NSLog(@"Flutter MethodChannel 收到:startLive");
  }
  else {
    result(FlutterMethodNotImplemented);
  }
}

2、EventChannel,通過(guò)綁定FlutterEventSink,讓eventSink來(lái)發(fā)送消息

@property (nonatomic) FlutterEventSink eventSink;
- (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments {
    _eventSink = nil;
    return nil;
}

- (FlutterError * _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(nonnull FlutterEventSink)events {
    _eventSink = events;
    return nil;
}

3、BasicMessageChannel 創(chuàng)建的時(shí)候綁定

注意事項(xiàng):

如果直接在Flutter項(xiàng)目中直接寫(xiě)plugin,每次運(yùn)行都會(huì)更新GeneratedPluginRegistrant這個(gè)類,是按podfile的描述重新生成,所以不要在GeneratedPluginRegistrant里邊寫(xiě)。

1、可以直接在AppDelegate里寫(xiě)

2、可以封裝FlutterChannelPlugin工具類,在AppDelegate入口函數(shù)調(diào)用

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  
  [GeneratedPluginRegistrant registerWithRegistry:self];
  
  [FlutterChannelPlugin registerWithRegistrar:[self registrarForPlugin:@"FlutterChannelPlugin"]];
  
}
  • 2.1、FlutterChannelPlugin需遵循代理(FlutterPlugin,FlutterStreamHandler)

  • 2.2、FlutterChannelPlugin需實(shí)現(xiàn)FlutterPlugin代理的類方法,作為入口

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterChannelPlugin *plugin = [[FlutterChannelPlugin alloc] init];
    [plugin createMethodChannel:registrar];
    [plugin createEventChannel:registrar];
    [plugin createMessageChannel:registrar];
}

3、如果需要跳轉(zhuǎn)原生頁(yè)面則需拿到當(dāng)前控制器
可通過(guò)下面方法實(shí)現(xiàn)

@property(strong, nonatomic) UIViewController *viewController;

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FlutterMethodChannel* channel = [FlutterMethodChannel
      methodChannelWithName:@"flutter_rtmp_plugin"
            binaryMessenger:[registrar messenger]];

  UIViewController *viewController =
    [UIApplication sharedApplication].delegate.window.rootViewController;

  FlutterRtmpPlugin* instance = [[FlutterRtmpPlugin alloc] initWithViewController:viewController];
  [registrar addMethodCallDelegate:instance channel:channel];
}

- (instancetype)initWithViewController:(UIViewController *)viewController {
  self = [super init];
  if (self) {
    self.viewController = viewController;
  }
  return self;
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  if ([call.method isEqualToString:@"startLive"]) {
      NSDictionary * dict = call.arguments;
      NSLog(@"流地址是 %@",dict[@"url"]);

      LFViewController *liveVC = [[LFViewController alloc] init];
      liveVC.liveUrl = dict[@"url"];
      liveVC.modalPresentationStyle = UIModalPresentationFullScreen;
      [self.viewController presentViewController:liveVC animated:YES completion:nil];
  }
  else {
    result(FlutterMethodNotImplemented);
  }
}

Android端的書(shū)寫(xiě)

MethodChannel, 另外兩種Channel參照iOS,兩者類似

1、入口函數(shù)中創(chuàng)建MethodChannel

 public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "flutterplugintemp");
    channel.setMethodCallHandler(this);
  }

2、遵循兩個(gè)協(xié)議

implements FlutterPlugin, MethodCallHandler 

3、實(shí)現(xiàn)協(xié)議方法,在方法中寫(xiě)代碼實(shí)現(xiàn)。

public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if(call.method.equals("startLive")){
      Intent intent = new Intent(context,LivingActivity.class);
      String url = call.argument("url");
      intent.putExtra("url",url);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
      context.startActivity(intent);

    } else {
      result.notImplemented();
    }
注意事項(xiàng)

flutter 1.12版本之前的入口函數(shù)是

public static void registerWith(Registrar registrar) {

flutter 1.12版本以后是

public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {

若果寫(xiě)錯(cuò)會(huì)收不到Flutter的方法回調(diào)

2、若果要跳轉(zhuǎn)原生頁(yè)面則需要拿到app的當(dāng)前context或activity
可通過(guò)這種寫(xiě)法獲取

//
private Context context;

public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    FlutterRtmpPlugin plugin = new FlutterRtmpPlugin();
    plugin.context = flutterPluginBinding.getApplicationContext();
    final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "flutter_rtmp_plugin");
    channel.setMethodCallHandler(plugin);
  }
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if(call.method.equals("startLive")){
      Intent intent = new Intent(context,LivingActivity.class);
      String url = call.argument("url");
      intent.putExtra("url",url);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
      context.startActivity(intent);

    } else {
      result.notImplemented();
    }
  }

總結(jié):

以上是plugin的基本使用,要想應(yīng)付各種復(fù)雜的場(chǎng)景還需多參考google官方插件源碼,來(lái)汲取養(yǎng)分。
比如 camera

最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Flutter Plugin 資料 [TOC] 前言 在Flutter中,如果我們需要打印日志,如果不進(jìn)行自定義,...
    zcwfeng閱讀 5,572評(píng)論 3 3
  • 一、簡(jiǎn)述 對(duì)于構(gòu)建Flutter類型應(yīng)用,因其開(kāi)發(fā)語(yǔ)言Dart、虛擬機(jī)、構(gòu)建工具與平時(shí)我們開(kāi)發(fā)Native應(yīng)用不同...
    微店App技術(shù)團(tuán)隊(duì)閱讀 1,394評(píng)論 0 3
  • 概述 調(diào)用原生功能 嵌入原有項(xiàng)目 Flutter模塊調(diào)試 一、調(diào)用原生功能 1.1、Camera某些應(yīng)用程序可能需...
    IIronMan閱讀 1,202評(píng)論 1 7
  • Flutter使用了一個(gè)靈活的系統(tǒng),允許您調(diào)用特定平臺(tái)的API,F(xiàn)lutter平臺(tái)特定的API支持不依賴于代碼生成...
    我是酷閱讀 1,123評(píng)論 0 1
  • 推薦指數(shù): 6.0 書(shū)籍主旨關(guān)鍵詞:特權(quán)、焦點(diǎn)、注意力、語(yǔ)言聯(lián)想、情景聯(lián)想 觀點(diǎn): 1.統(tǒng)計(jì)學(xué)現(xiàn)在叫數(shù)據(jù)分析,社會(huì)...
    Jenaral閱讀 6,038評(píng)論 0 5

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