flutter插件化开发与原生的多次通信(BasicMessageChannel)

flutter与原生的通信有三种方式

  • BasicMessageChannel:用于传递字符串和半结构化的信息,双向通信,原生可以多次向flutter发送消息
  • MethodChannel:用于传递方法调用(method invocation),双向通行,
  • EventChannel: 用于数据流(event streams)的通信,flutter调用原生一次,原生也只能返回flutter一次消息,然后通信结束

本文介绍使用BasicMessageChannel插件化开发flutter与原生的多次通信

flutter_plugin端代码

class AdhubPlugin {
  // adhub_plugin通信名称
  static const _channel = const BasicMessageChannel(
      'adhub_plugin', StandardMessageCodec());

 /// 注意:返回_channel 用于接受多次返回的消息
  static Future<BasicMessageChannel> adHubSplash(String applicationID,String spaceID) async {
      Map map = {"method":"getAdHubSplash","arguments":{}};
       _channel.send(map);
       return _channel;
  }
}

iOS端代码

#import "AdhubPlugin.h"

@implementation AdhubPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    AdhubPlugin* instance = [[AdhubPlugin alloc] init];
    [instance setMessageChannel:registrar];

}

-(void)setMessageChannel:(NSObject<FlutterPluginRegistrar>*)registrar{
    messageChannel = [FlutterBasicMessageChannel messageChannelWithName:@"adhub_plugin" binaryMessenger:[registrar messenger]];
    // 接收消息监听 callback用于单次通讯,无法多次返回消息
    __block AdhubPlugin *blockSelf = self;
    [messageChannel setMessageHandler:^(id message, FlutterReply callback) {
        NSString *method = message[@"method"];
        if ([@"getAdHubSplash" isEqualToString:method]) {
            NSDictionary* dic = message[@"arguments"];
            [blockSelf createSplash:dic];
        } else {
            callback(@"");
        }
    }];
}

/// 第三方开屏 
- (void)createSplash:(NSDictionary *)dic{
    [AdHubSDKManager configureWithApplicationID:[dic objectForKey:@"applicationID"]];
    [AdHubSDKManager openTheAdHubLog];
    self.splash = [[AdHubSplash alloc]initWithSpaceID:[dic objectForKey:@"spaceID"] spaceParam:@"" lifeTime:5000];
    self.splash.delegate = self;
    self.splash.showLaunchImage = NO;
    [self.splash ADH_loadAndDisplaySplashAd];// 使用此方法加载开屏
}

#pragma mark adHub广告
/**
 开屏展现
 [messageChannel sendMessage:@""]用来与flutter端多次通信 类型可以是任意类型 这里是字符串
 */
- (void)ADH_splashDidPresentScreen:(AdHubSplash *)adHubSplash {
    [messageChannel sendMessage:@"开屏展现"];
}

/**
 开屏点击
 */
- (void)ADH_splashDidClick:(AdHubSplash *)adHubSplash {
    [messageChannel sendMessage:@"开屏点击"];
}

/**
 开屏即将消失
 */
- (void)ADH_splashWillDismissScreen:(AdHubSplash *)adHubSplash {
    
}

/**
 开屏消失
 */
- (void)ADH_splashDidDismissScreen:(AdHubSplash *)adHubSplash {
    [messageChannel sendMessage:@"开屏消失"];
}

/**
 开屏请求失败
 */
- (void)ADH_splash:(AdHubSplash *)adHubSplash didFailToLoadAdWithError:(AdHubRequestError *)error {
    [messageChannel sendMessage:@"开屏请求失败"];

}


@end

如果通信是多页面的话,可以用通知来实现,在本页面注册通知,在其他页面实现通知

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    //注册通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationFuncion:) name:@"ios.to.flutter" object:nil];

    AdhubPlugin* instance = [[AdhubPlugin alloc] init];
    [instance setMessageChannel:registrar];

}

- (void)notificationFuncion: (NSNotification *) notification {
    // iOS 中其他页面向Flutter 中发送消息通过这里
    // 本页中 可以直接使用   [messageChannel sendMessage:dic];
    //处理消息
    NSLog(@"notificationFuncion ");
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    if (messageChannel!=nil) {
        [dic setObject:@" [messageChannel sendMessage:dic]; 向Flutter 发送消息 " forKey:@"message"];
        [dic setObject: [NSNumber numberWithInt:401] forKey:@"code"];
        //主动向Flutter 中发送消息
        [messageChannel sendMessage:dic];
    }
    
}

- (void)dealloc {
    //单条移除观察者
    //[[NSNotificationCenter defaultCenter] removeObserver:self name:@"ios.to.flutter" object:nil];
    //移除所有观察者
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Android端代码(非plugin插件化实例)

在MainActivity中,创建了 BasicMessageChannel 的实例 mMessageChannel,可以在MainActivity 中直接使用 mMessageChannel 实例来向 Flutter 中发送消息

	
	private void channelSendMessage() {
		
		Toast.makeText(mContext, "flutter 调用到了 android test", Toast.LENGTH_SHORT).show();
		//构建参数 
		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("message", "reply.reply 返回给flutter的数据");
		resultMap.put("code", 200);
		//向 Flutter 中发送消息
		//参数 二可以再次接收到 Flutter 中的回调
		//也可以直接使用 mMessageChannel.send(resultMap)
		mMessageChannel.send(resultMap, new BasicMessageChannel.Reply<Object>() {
			@Override
			public void reply(Object o) {
				
				Log.d("mMessageChannel", "mMessageChannel send 回调 " + o);
			}
		});
	}
	

在其他的 Activity 页面中,我们就使用不到这个实例的,我这里的一个实现 Android 中新建的Activity 页面向 Flutter 中发送消息的方法 是广播机制

在 MainActivity 中注册广播,在广播接收者中通过 BasicMessageChannel 的实例 mMessageChannel 来发送消息。

在 Android 中其他的页面中 发送广播到 MainActivity 中的广播接收者中,这样就实现了Android 中新建的Activity 页面向 Flutter 中发送消息

public class MainActivity extends FlutterActivity {
	
	
	... ...
	
	Handler mHandler = new Handler(Looper.myLooper());
	private MainReceiver mMainReceiver;
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		//注销广播
		unregisterReceiver(mMainReceiver);
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		... ...
		//注册广播
		mMainReceiver = new MainReceiver();
		IntentFilter lIntentFilter = new IntentFilter("android.to.flutter");
		registerReceiver(mMainReceiver, lIntentFilter);
		
		
	}
	
	
	public class MainReceiver extends BroadcastReceiver {
		public MainReceiver() {
		}
		
		@Override
		public void onReceive(Context context, Intent intent) {
			Toast.makeText(context, "接收到自定义的广播", Toast.LENGTH_SHORT).show();
			mHandler.post(new Runnable() {
				@Override
				public void run() {
					Map<String, Object> resultMap2 = new HashMap<>();
					resultMap2.put("message", "android 主动调用 flutter test 方法");
					resultMap2.put("code", 200);
					
					if (mMessageChannel != null) {
						// 向Flutter 发送消息
						mMessageChannel.send(resultMap2, new BasicMessageChannel.Reply<Object>() {
							@Override
							public void reply(Object o) {
								System.out.println("android onReply: " + o);
							}
						});
					}
					
				}
			});
		}
	}
}

flutter项目调用

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(

        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: InkWell(
            child: Text('进入开屏页面'),
            onTap: () async {
              BasicMessageChannel channel = await AdhubPlugin.adHubSplash('20017','102904');
              channel.setMessageHandler((result) async {
                //解析 原生发给 Flutter 的参数
                print(result);
              });
            }
          )
        ),
      ),
    );
  }
}

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐