一、概述
本文一是为了记录flutter中本地和原生以数据流方式的通信,二是完成实时获取手机物理按键音量的插件。
本人没有学习过ios,和ios互相不了解,代码全部都是现学现卖,如果有什么不对的地方或者有更好的方法也请自行修改。
二、开始编码
flutter和原生代码通信原理请参考我之前的博文:
Flutter与Android原生代码交互
首先是flutter使用:
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Volume(
onVolumeChangeListener: (num volume) {
setState(() {
currentVolume = volume;
});
},
),
Text("当前音量=${currentVolume}")
]),
),
);
}
Android端
Android端通过广播形式监听物理按键音量的变化,并通过EventChannel发送给flutter进行接收。
1.还是跟所有的通信一样,首先是需要注册通信通道:
public static void registerWith(PluginRegistry.Registrar registrar) {
channel = new EventChannel(registrar.messenger(), CHANNEL);
VolumePlugin volumePlugin = new VolumePlugin(registrar.activity());
channel.setStreamHandler(volumePlugin);
}
2.实现EventChannel.StreamHandler,并实现是方法
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
Log.e("VolumePlugin", "onListen");
this.eventSink = eventSink;
//实例化对象并设置监听器
mVolumeChangeObserver = new VolumeChangeObserver(activity);
mVolumeChangeObserver.setVolumeChangeListener(this);
int initVolume = mVolumeChangeObserver.getCurrentMusicVolume();
Log.e("VolumePlugin", "initVolume = " + initVolume);
eventSink.success(initVolume);
mVolumeChangeObserver.registerReceiver();
}
3.实现广播监听方法实时获取音量,并通过EventChannel发送给flutter:
/**
* 实现广播监听,具体方法请到最后的项目地址查看
* @author songyaru
* @date 2019-05-24
*/
@Override
public void onVolumeChanged(int volume) {
Log.e("VolumePlugin", "onVolumeChanged()--->volume = " + volume);
eventSink.success(volume);
}
iOS端
iOS端基本和Android端一样,只不过语法不同而已,此部分纯粹自己摸索,给同样不懂ios的同学马马虎虎的参考。
1.注册通道
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
VolumePlugin* instance = [[VolumePlugin alloc] init];
FlutterEventChannel* evenChannal =
[FlutterEventChannel eventChannelWithName:@"plugins.com.karen/volume"
binaryMessenger:[registrar messenger]];
[evenChannal setStreamHandler:instance];
}
2.实现FlutterStreamHandler并实现其监听:
#pragma mark - <FlutterStreamHandler>
// // 这个onListen是Flutter端开始监听这个channel时的回调,第二个参数 EventSink是用来传数据的载体。
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
eventSink:(FlutterEventSink)events {
_eventSink = events;
// 获取系统音量
MPVolumeView *volumeView = [[MPVolumeView alloc] init];
UISlider *volumeViewSlider= nil;
for (UIView *view in [volumeView subviews]){
if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
volumeViewSlider = (UISlider*)view;
break;
}
}
//float systemVolume = volumeViewSlider.value;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
float currentVol = audioSession.outputVolume;
NSLog(@"当前初始化音量%f@", currentVol);
_eventSink(@(currentVol));
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChanged:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
// arguments flutter给native的参数
// 回调给flutter, 建议使用实例指向,因为该block可以使用多次
return nil;
}
/// flutter不再接收
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
// arguments flutter给native的参数
NSLog(@"%@", arguments);
return nil;
}
3.实现音量监听
- (void)volumeChanged:(NSNotification *)notification
{
float volume = [notification.userInfo[@"AVSystemController_AudioVolumeNotificationParameter"] floatValue];
_eventSink(@(volume));
NSLog(@"当前音量%f@", volume);
}
三、总结
本人真的是一点都不了解ios,摸摸索索搞了很久,希望能帮助一些同样有这样需求的小白们。