类似支付宝收款时候的语音播报功能: 当别人扫描你的收款码, 你收到钱之后, 就会听到支付宝到账 12.55 元的语音播报
要解决的问题
1. 播放单个语音文件
2. 播放完单个语音文件之后立即播放下一条, 这样才能连续
3. 当多个完整的语音序列都需要播报时的处理 (比如支付宝短时间内收到多条收款推送)
实现思路
播放单个文件选择 MediaPlayer
首先创建一个 MediaPlayer 实例
MediaPlayer player = new MediaPlayer();
然后设置数据源, 这里数据源从 assets 中获取, 当然也可以将语音文件放在 raw 文件夹里
- fd = FileUtils.getAssetFileDescription(path);
- player.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(),fd.getLength());
然后调用 prepareAsync() 方法, 异步加载, 并设置监听, 加载完毕之后开始播放 (与 prepare 方法区别开来)
- player.prepareAsync();
- player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
- @Override
- public void onPrepared(MediaPlayer mp) {
- mp.start();
- }
- });
由于播放的语音文件不止一个, 因此需要监听播放完成的状态, 在播放完成之后播放下一条语音
- player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(MediaPlayer mp) {
- mp.reset();
- counter[0]++;
- if (counter[0] < list.size()) {
- try {
- AssetFileDescriptor fileDescriptor = FileUtils.getAssetFileDescription(String.format("sound/tts_%s.mp3", list.get(counter[0])));
- mp.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getLength());
- mp.prepare();
- } catch (IOException e) {
- e.printStackTrace();
- latch.countDown();
- }
- } else {
- mp.release();
- latch.countDown();
- }
- }
- });
短时间多次播报请求, 开采用同步方式进行, 一条播完播放下一条, 这里采用
synchronized + notifyAll() 实现, 当然也可以用别的方法
代码封装
功能代码分为两部分, 一部分是语音序列组成的 List, 这里是 VoiceTemplate;
一部分是播放的功能封装, 接收 List, 然后播放语音, 这里叫做 VoiceSpeaker;
详细代码见文末
代码使用
比如要播放支付宝到账十二点一三元, 代码如下
- final List<String> list = new VoiceTemplate()
- .prefix("success")
- .numString("12.13")
- .suffix("yuan")
- .gen();
- VoiceSpeaker.getInstance().speak(list);
源码
- KTools:
- https://link.jianshu.com/?t=https://github.com/jiangkang/KTools
- https://github.com/jiangkang/KTools/blob/master/app/src/main/java/com/jiangkang/ktools/audio/VoiceSpeaker.java
- https://github.com/jiangkang/KTools/blob/master/app/src/main/java/com/jiangkang/ktools/audio/VoiceTemplate.java
来源: https://mp.weixin.qq.com/s/ql7UfOvJY55GL1hoK9wJbA