Flutter音频焦点管理插件audio_focus_plugin的使用
Flutter音频焦点管理插件audio_focus_plugin的使用
本项目旨在展示如何在Flutter应用中使用audio_focus_plugin
插件来管理音频焦点。该插件允许应用请求和放弃音频焦点,从而更好地控制音频播放行为。
开始使用
首先,确保已经在项目的pubspec.yaml
文件中添加了audio_focus_plugin
依赖项:
dependencies:
audio_focus_plugin: ^x.x.x
然后运行flutter pub get
命令以获取依赖项。
完整示例代码
以下是一个完整的示例代码,展示了如何在Flutter应用中使用audio_focus_plugin
插件来管理音频焦点。
import 'dart:async';
import 'dart:io' show Platform;
import 'package:audio_focus_plugin/audio_focus_plugin.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
enum TtsState { playing, stopped, paused, continued }
class _MyAppState extends State<MyApp> {
late FlutterTts flutterTts;
String? language;
String? engine;
double volume = 0.5;
double pitch = 1.0;
double rate = 0.5;
bool isCurrentLanguageInstalled = false;
String? _newVoiceText = "测试,测试,测试,测试,测试,测试,测试,测试,测试,测试,测试,测试,";
int? _inputLength;
TtsState ttsState = TtsState.stopped;
get isPlaying => ttsState == TtsState.playing;
get isStopped => ttsState == TtsState.stopped;
get isPaused => ttsState == TtsState.paused;
get isContinued => ttsState == TtsState.continued;
bool get isIOS => !kIsWeb && Platform.isIOS;
bool get isAndroid => !kIsWeb && Platform.isAndroid;
bool get isWindows => !kIsWeb && Platform.isWindows;
bool get isWeb => kIsWeb;
final _audioFocusPlugin = AudioFocusPlugin();
@override
initState() {
super.initState();
initTts();
}
initTts() {
flutterTts = FlutterTts();
_setAwaitOptions();
if (isAndroid) {
_getDefaultEngine();
_getDefaultVoice();
}
flutterTts.setStartHandler(() {
setState(() {
print("Playing");
ttsState = TtsState.playing;
});
});
if (isAndroid) {
flutterTts.setInitHandler(() {
setState(() {
print("TTS Initialized");
});
});
}
flutterTts.setCompletionHandler(() {
setState(() {
print("Complete");
ttsState = TtsState.stopped;
});
});
flutterTts.setCancelHandler(() {
setState(() {
print("Cancel");
ttsState = TtsState.stopped;
});
});
flutterTts.setPauseHandler(() {
setState(() {
print("Paused");
ttsState = TtsState.paused;
});
});
flutterTts.setContinueHandler(() {
setState(() {
print("Continued");
ttsState = TtsState.continued;
});
});
flutterTts.setErrorHandler((msg) {
setState(() {
print("error: $msg");
ttsState = TtsState.stopped;
});
});
}
Future<dynamic> _getLanguages() async => await flutterTts.getLanguages;
Future<dynamic> _getEngines() async => await flutterTts.getEngines;
Future _getDefaultEngine() async {
var engine = await flutterTts.getDefaultEngine;
if (engine != null) {
print(engine);
}
}
Future _getDefaultVoice() async {
var voice = await flutterTts.getDefaultVoice;
if (voice != null) {
print(voice);
}
}
Future _speak() async {
await _audioFocusPlugin.requestAudioFocus();
await flutterTts.setVolume(volume);
await flutterTts.setSpeechRate(rate);
await flutterTts.setPitch(pitch);
if (_newVoiceText != null) {
if (_newVoiceText!.isNotEmpty) {
await flutterTts.speak(_newVoiceText!);
}
}
await _audioFocusPlugin.abandonAudioFocus();
}
Future _setAwaitOptions() async {
await flutterTts.awaitSpeakCompletion(true);
}
Future _stop() async {
var result = await flutterTts.stop();
if (result == 1) setState(() => ttsState = TtsState.stopped);
}
Future _pause() async {
var result = await flutterTts.pause();
if (result == 1) setState(() => ttsState = TtsState.paused);
}
@override
void dispose() {
super.dispose();
flutterTts.stop();
}
List<DropdownMenuItem<String>> getEnginesDropDownMenuItems(dynamic engines) {
var items = <DropdownMenuItem<String>>[];
for (dynamic type in engines) {
items.add(DropdownMenuItem(
value: type as String?, child: Text(type as String)));
}
return items;
}
void changedEnginesDropDownItem(String? selectedEngine) async {
await flutterTts.setEngine(selectedEngine!);
language = null;
setState(() {
engine = selectedEngine;
});
}
List<DropdownMenuItem<String>> getLanguageDropDownMenuItems(
dynamic languages) {
var items = <DropdownMenuItem<String>>[];
for (dynamic type in languages) {
items.add(DropdownMenuItem(
value: type as String?, child: Text(type as String)));
}
return items;
}
void changedLanguageDropDownItem(String? selectedType) {
setState(() {
language = selectedType;
flutterTts.setLanguage(language!);
if (isAndroid) {
flutterTts
.isLanguageInstalled(language!)
.then((value) => isCurrentLanguageInstalled = (value as bool));
}
});
}
void _onChange(String text) {
setState(() {
_newVoiceText = text;
});
}
Widget _engineSection() {
if (isAndroid) {
return FutureBuilder<dynamic>(
future: _getEngines(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
return _enginesDropDownSection(snapshot.data);
} else if (snapshot.hasError) {
return Text('Error loading engines...');
} else
return Text('Loading engines...');
});
} else
return Container(width: 0, height: 0);
}
Widget _futureBuilder() => FutureBuilder<dynamic>(
future: _getLanguages(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
return _languageDropDownSection(snapshot.data);
} else if (snapshot.hasError) {
return Text('Error loading languages...');
} else
return Text('Loading Languages...');
});
Widget _inputSection() => Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.only(top: 25.0, left: 25.0, right: 25.0),
child: TextField(
maxLines: 11,
minLines: 6,
onChanged: (String value) {
_onChange(value);
},
));
Widget _btnSection() {
return Container(
padding: EdgeInsets.only(top: 50.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(Colors.green, Colors.greenAccent, Icons.play_arrow,
'播放', _speak),
_buildButtonColumn(
Colors.red, Colors.redAccent, Icons.stop, '停止', _stop),
_buildButtonColumn(
Colors.blue, Colors.blueAccent, Icons.pause, '暂停', _pause),
],
),
);
}
Widget _enginesDropDownSection(dynamic engines) => Container(
padding: EdgeInsets.only(top: 50.0),
child: DropdownButton(
value: engine,
items: getEnginesDropDownMenuItems(engines),
onChanged: changedEnginesDropDownItem,
),
);
Widget _languageDropDownSection(dynamic languages) => Container(
padding: EdgeInsets.only(top: 10.0),
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
DropdownButton(
value: language,
items: getLanguageDropDownMenuItems(languages),
onChanged: changedLanguageDropDownItem,
),
Visibility(
visible: isAndroid,
child: Text("已安装: $isCurrentLanguageInstalled"),
),
]));
Column _buildButtonColumn(Color color, Color splashColor, IconData icon,
String label, Function func) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Icon(icon),
color: color,
splashColor: splashColor,
onPressed: () => func()),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(label,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: color)))
]);
}
Widget _getMaxSpeechInputLengthSection() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
child: Text('获取最大语音输入长度'),
onPressed: () async {
_inputLength = await flutterTts.getMaxSpeechInputLength;
setState(() {});
},
),
Text("$_inputLength 字符"),
],
);
}
Widget _buildSliders() {
return Column(
children: [_volume(), _pitch(), _rate()],
);
}
Widget _volume() {
return Slider(
value: volume,
onChanged: (newVolume) {
setState(() => volume = newVolume);
},
min: 0.0,
max: 1.0,
divisions: 10,
label: "音量: $volume");
}
Widget _pitch() {
return Slider(
value: pitch,
onChanged: (newPitch) {
setState(() => pitch = newPitch);
},
min: 0.5,
max: 2.0,
divisions: 15,
label: "音调: $pitch",
activeColor: Colors.red,
);
}
Widget _rate() {
return Slider(
value: rate,
onChanged: (newRate) {
setState(() => rate = newRate);
},
min: 0.0,
max: 1.0,
divisions: 10,
label: "语速: $rate",
activeColor: Colors.green,
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter TTS'),
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
_inputSection(),
_btnSection(),
_engineSection(),
_futureBuilder(),
_buildSliders(),
if (isAndroid) _getMaxSpeechInputLengthSection(),
],
),
),
),
);
}
}
代码说明
-
导入必要的库:
import 'dart:async'; import 'dart:io' show Platform; import 'package:audio_focus_plugin/audio_focus_plugin.dart'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/material.dart'; import 'package:flutter_tts/flutter_tts.dart';
-
初始化FlutterTts和请求音频焦点:
void initState() { super.initState(); initTts(); } void initTts() { flutterTts = FlutterTts(); // 设置各种回调函数 // ... } Future _speak() async { await _audioFocusPlugin.requestAudioFocus(); // 设置音量、语速和音调 // 调用speak方法开始朗读文本 await _audioFocusPlugin.abandonAudioFocus(); }
更多关于Flutter音频焦点管理插件audio_focus_plugin的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter音频焦点管理插件audio_focus_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter应用中,管理音频焦点是一项重要的任务,特别是在多个音频源(如音乐播放器、语音助手、通知等)同时运行时。audio_focus_plugin
是一个用于管理音频焦点的Flutter插件,它可以帮助你在应用中正确处理音频焦点的获取和释放。
以下是如何使用 audio_focus_plugin
的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 audio_focus_plugin
插件的依赖:
dependencies:
flutter:
sdk: flutter
audio_focus_plugin: ^0.0.1 # 请确保使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入插件
在你的Dart文件中导入 audio_focus_plugin
:
import 'package:audio_focus_plugin/audio_focus_plugin.dart';
3. 获取音频焦点
在需要获取音频焦点的地方,调用 requestAudioFocus
方法。例如,在播放音频之前:
AudioFocus audioFocus = AudioFocus();
Future<void> playAudio() async {
final focusRequestResult = await audioFocus.requestAudioFocus();
if (focusRequestResult == AudioFocusRequestResult.granted) {
// 成功获取音频焦点,可以开始播放音频
// 例如:audioPlayer.play();
} else {
// 未获取到音频焦点,处理相应逻辑
}
}
4. 释放音频焦点
当你不使用音频时,应该释放音频焦点,以便其他应用可以获取它。你可以调用 abandonAudioFocus
方法:
Future<void> stopAudio() async {
await audioFocus.abandonAudioFocus();
// 停止音频播放
// 例如:audioPlayer.stop();
}
5. 处理音频焦点变化
你可以监听音频焦点的变化,以便在焦点丢失或重新获取时执行相应操作。例如,当其他应用获取了音频焦点时,你可能需要暂停播放。
audioFocus.onAudioFocusChange.listen((focusChange) {
switch (focusChange) {
case AudioFocusChange.loss:
// 永久失去焦点,暂停播放
// 例如:audioPlayer.pause();
break;
case AudioFocusChange.lossTransient:
// 暂时失去焦点,暂停播放
// 例如:audioPlayer.pause();
break;
case AudioFocusChange.lossTransientCanDuck:
// 暂时失去焦点,降低音量
// 例如:audioPlayer.setVolume(0.5);
break;
case AudioFocusChange.gain:
// 重新获得焦点,恢复播放
// 例如:audioPlayer.play();
break;
}
});
6. 处理不同平台的差异
audio_focus_plugin
应该在Android和iOS上都能正常工作,但不同平台的行为可能有所不同。确保你在不同平台上测试你的应用,以确保音频焦点管理按预期工作。
示例代码
以下是一个完整的示例,展示了如何在Flutter应用中使用 audio_focus_plugin
:
import 'package:flutter/material.dart';
import 'package:audio_focus_plugin/audio_focus_plugin.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: AudioFocusExample(),
);
}
}
class AudioFocusExample extends StatefulWidget {
[@override](/user/override)
_AudioFocusExampleState createState() => _AudioFocusExampleState();
}
class _AudioFocusExampleState extends State<AudioFocusExample> {
AudioFocus audioFocus = AudioFocus();
[@override](/user/override)
void initState() {
super.initState();
audioFocus.onAudioFocusChange.listen((focusChange) {
switch (focusChange) {
case AudioFocusChange.loss:
// 永久失去焦点,暂停播放
break;
case AudioFocusChange.lossTransient:
// 暂时失去焦点,暂停播放
break;
case AudioFocusChange.lossTransientCanDuck:
// 暂时失去焦点,降低音量
break;
case AudioFocusChange.gain:
// 重新获得焦点,恢复播放
break;
}
});
}
Future<void> playAudio() async {
final focusRequestResult = await audioFocus.requestAudioFocus();
if (focusRequestResult == AudioFocusRequestResult.granted) {
// 成功获取音频焦点,开始播放
} else {
// 未获取到音频焦点,处理相应逻辑
}
}
Future<void> stopAudio() async {
await audioFocus.abandonAudioFocus();
// 停止音频播放
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Audio Focus Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: playAudio,
child: Text('Play Audio'),
),
ElevatedButton(
onPressed: stopAudio,
child: Text('Stop Audio'),
),
],
),
),
);
}
}