插件介绍:
flutter_sound
这个插件能够实现iOS和Android
平台的录音和播映功能。即能够播映本地音频文件,也能够播映远程URL文件。在这儿我讲介绍这个插件的用法以及碰到的一些常见问题怎么处理。
-
flutter_sound支撑多种录音格局
-
flutter_sound支撑多种播映格局
-
flutter_sound支撑音频振幅大小
插件信息:
插件地址:github.com/ryanheise/a…
插件版别:9.2.9
插件运用前的准备工作
设置麦克风权限描绘
- iOS:需要在info.plist文件添加一下权限
<key>NSMicrophoneUsageDescription</key>
<string>描绘你运用麦克风用来干嘛</string>
留意:还需要在Podfile文件中配置
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
## dart: PermissionGroup.microphone
'PERMISSION_MICROPHONE=1',
]
end
end
end
还需要在iOS工程中添加libc++.tbd
库,具体途径
- Android:需要设置
AndroidManifest.xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这儿还用了下面几个插件
权限办理插件 permission_handler
插件信息:permission_handler: ^9.2.0
插件地址:pub.flutter-io.cn/packages/pe…
音频硬件配置插件 audio_session
插件信息:audio_session: ^0.1.6
插件地址:github.com/ryanheise/a…
动画插件
插件信息:lottie: 1.2.1
插件地址:pub.flutter-io.cn/packages/fl…
常用的办法
录音常见的办法
初始化录音对象
FlutterSoundRecorder recorderModule = FlutterSoundRecorder();
开启录音
Future<void> init() async {
//开启录音
await recorderModule.openRecorder();
//设置订阅计时器
await recorderModule
.setSubscriptionDuration(const Duration(milliseconds: 10));
//初始化日期插件
await initializeDateFormatting();
}
麦克风权限
Future<bool> getPermissionStatus() async {
Permission permission = Permission.microphone;
//granted 通过,denied 被回绝,permanentlyDenied 回绝且不在提示
PermissionStatus status = await permission.status;
if (status.isGranted) {
return true;
} else if (status.isDenied) {
requestPermission(permission);
} else if (status.isPermanentlyDenied) {
openAppSettings();
} else if (status.isRestricted) {
requestPermission(permission);
} else {}
return false;
}
///申请权限
void requestPermission(Permission permission) async {
PermissionStatus status = await permission.request();
if (status.isPermanentlyDenied) {
openAppSettings();
}
}
开端录音
/// 开端录音
_startRecorder() async {
try {
//获取麦克风权限
await getPermissionStatus().then((value) async {
if (!value) {
return;
}
//用户允许运用麦克风之后开端录音
Directory tempDir = await getTemporaryDirectory();
var time = DateTime.now().millisecondsSinceEpoch;
String path = '${tempDir.path}/$time${ext[Codec.aacADTS.index]}';
//这儿我录制的是aac格局的,还有其他格局
await recorderModule.startRecorder(
toFile: path,
codec: Codec.aacADTS,
bitRate: 8000,
numChannels: 1,
sampleRate: 8000,
);
/// 监听录音
_recorderSubscription = recorderModule.onProgress!.listen((e) {
var date = DateTime.fromMillisecondsSinceEpoch(
e.duration.inMilliseconds,
isUtc: true);
var txt = DateFormat('mm:ss:SS', 'en_GB').format(date);
//设置了最大录音时长
if (date.second >= _maxLength) {
_stopRecorder();
return;
}
setState(() {
//更新录音时长
_recordText = txt.substring(1, 5);
});
});
setState(() {
//更新录音状况和录音文件途径
_state = RecordPlayState.recording;
_path = path;
});
});
} catch (err) {
setState(() {
_stopRecorder();
_state = RecordPlayState.record;
_cancelRecorderSubscriptions();
});
}
}
完毕录音
/// 完毕录音
_stopRecorder() async {
try {
await recorderModule!.stopRecorder().then((value) {
_cancelRecorderSubscriptions();
});
} catch (err) {}
setState(() {
_state = RecordPlayState.record;
});
}
///毁掉录音
void dispose() {
super.dispose();
_cancelRecorderSubscriptions();
_releaseFlauto();
}
/// 撤销录音监听
void _cancelRecorderSubscriptions() {
if (_recorderSubscription != null) {
_recorderSubscription!.cancel();
_recorderSubscription = null;
}
}
/// 开释录音
Future<void> _releaseFlauto() async {
try {
await recorderModule.closeRecorder();
} catch (e) {}
}
/// 判别文件是否存在
Future<bool> _fileExists(String path) async {
return await File(path).exists();
}
播映常见的办法
初始化播映器
FlutterSoundPlayer playerModule = FlutterSoundPlayer();
初始化操作
init() async {
await playerModule.openPlayer();
await playerModule
.setSubscriptionDuration(const Duration(milliseconds: 10));
//这块是设置音频,暂时没用到能够不用设置
final session = await AudioSession.instance;
await session.configure(AudioSessionConfiguration(
avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
avAudioSessionCategoryOptions:
AVAudioSessionCategoryOptions.allowBluetooth |
AVAudioSessionCategoryOptions.defaultToSpeaker,
avAudioSessionMode: AVAudioSessionMode.spokenAudio,
avAudioSessionRouteSharingPolicy:
AVAudioSessionRouteSharingPolicy.defaultPolicy,
avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
androidAudioAttributes: const AndroidAudioAttributes(
contentType: AndroidAudioContentType.speech,
flags: AndroidAudioFlags.none,
usage: AndroidAudioUsage.voiceCommunication,
),
androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
androidWillPauseWhenDucked: true,
));
}
开端播映
///开端播映,这儿做了一个播映状况的回调
void startPlayer(PlayStateBack callBack) async {
try {
if (path.contains('http')) {
await playerModule.startPlayer(
fromURI: path,
codec: Codec.mp3,
sampleRate: 44000,
whenFinished: () {
stopPlayer();
callBack(0);
});
} else {
//判别文件是否存在
if (await _fileExists(path)) {
if (playerModule.isPlaying) {
playerModule.stopPlayer();
}
await playerModule.startPlayer(
fromURI: path,
codec: Codec.aacADTS,
sampleRate: 44000,
whenFinished: () {
stopPlayer();
callBack(0);
});
} else {}
}
//监听播映进展
_playerSubscription = playerModule.onProgress!.listen((e) {});
callBack(1);
} catch (err) {
callBack(0);
}
}
完毕播映
/// 完毕播映
void stopPlayer() async {
try {
await playerModule.stopPlayer();
cancelPlayerSubscriptions();
} catch (err) {}
}
/// 撤销播映监听
void cancelPlayerSubscriptions() {
if (_playerSubscription != null) {
_playerSubscription!.cancel();
_playerSubscription = null;
}
}
///获取播映状况
Future<PlayerState> getPlayState() async {
return await playerModule.getPlayerState();
}
/// 开释播映器
void releaseFlauto() async {
try {
await playerModule!.closePlayer().then((value){
cancelPlayerSubscriptions();
if(playerModule != null){
playerModule = null;
}
});
} catch (e) {
print(e);
}
}
/// 判别文件是否存在
Future<bool> _fileExists(String path) async {
return await File(path).exists();
}
动画实现
在进行录音和播映的过程中难免运用到动画,这儿我说下怎么加载gif和动画文件
加载GIF动画
Visibility(
visible: (item.playing.value == 1) ? true : false,
child: Image.asset('assets/-comm/comm_audio_paly.gif', width: 20, height: 20,),
replacement: const Image(
image: AssetImage('assets/-comm/comm_audio_icon.png'),
width: 20,
height: 20,
),
)
加载动画文件
Lottie.asset('assets/-comm/record_audio_animation.json',
height: 25,
width: ScreenAdapter.screenWidth() -ScreenAdapter.width(160),
animate: true)
上传文件
上传音频文件
var map = {
"file": MultipartFile.fromBytes(
await File.fromUri(Uri(path: path)).readAsBytes(),
filename: "$fileName.mp3",
contentType: MediaType.parse("audio/mp3"))
};
留意
在9.2.13版别曾经
,假如是iOS和Flutter混编项目,如果首次进入Flutter模块,这个插件运用是没有问题的,可是当脱离这个模块第2次进入就会出现注册插件犯错、初始化失利
的状况。报错如下:
ERROR during registerWithRegistrar: flutterSoundPlayerManager != nil
MissingPluginException(No implementation found for method resetPlugin on channel com.dooboolab.flutter_sound_player)
这是插件确实存在的bug,目前作者已经在最新版别9.2.13
上做了修正。
总结
上面介绍了怎么录音,怎么播映本地和远程音频文件,以及怎么实现动画,在录制完音频文件后怎么上传,这些都是咱们往常运用这个功能会遇到的问题。在运用的过程中遇到的问题也有列出,希望对您有所帮助。