服务器之家

服务器之家 > 正文

Android实现语音播放与录音功能

时间:2022-03-08 15:59     来源/作者:尽人事看天意

本文实例为大家分享了Android实现语音播放与录音的具体代码,供大家参考,具体内容如下

项目用到的技术点和亮点

  • 语音录音 (单个和列表)
  • 语音播放(单个和列表)
  • 语音录音封装
  • 语音播放器封装
  • 语音列表顺序播放
  • 语音列表单个播放 复用问题处理

因为安装原生录音不能录mp3格式文件 而mp3格式是安卓和ios公用的,所以我们需要的是能直接录取mp3文件或者录完的格式转成mp3格式

下面添加这个库 能直接录mp3文件,我觉得是最方便的

compile ‘com.czt.mp3recorder:library:1.0.3'

1. 语音录音封装

代码简单 自己看吧

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package com.video.zlc.audioplayer;
 
import com.czt.mp3recorder.MP3Recorder;
import com.video.zlc.audioplayer.utils.LogUtil;
 
import java.io.File;
import java.io.IOException;
import java.util.UUID;
/**
 * @author zlc
 */
public class AudioManage {
 
 private MP3Recorder mRecorder;
 private String mDir;    // 文件夹的名称
 private String mCurrentFilePath;
 private static AudioManage mInstance;
 
 private boolean isPrepared; // 标识MediaRecorder准备完毕
 private AudioManage(String dir) {
  mDir = dir;
  LogUtil.e("AudioManage=",mDir);
 }
 
 /**
  * 回调“准备完毕”
  * @author zlc
  */
 public interface AudioStateListenter {
  void wellPrepared(); // prepared完毕
 }
 
 public AudioStateListenter mListenter;
 
 public void setOnAudioStateListenter(AudioStateListenter audioStateListenter) {
  mListenter = audioStateListenter;
 }
 
 /**
  * 使用单例实现 AudioManage
  * @param dir
  * @return
  */
 public static AudioManage getInstance(String dir) {
  if (mInstance == null) {
   synchronized (AudioManage.class) { // 同步
    if (mInstance == null) {
     mInstance = new AudioManage(dir);
    }
   }
  }
  return mInstance;
 }
 
 /**
  * 准备录音
  */
 public void prepareAudio() {
 
  try {
   isPrepared = false;
   File dir = new File(mDir);
   if (!dir.exists()) {
    dir.mkdirs();
   }
   String fileName = GenerateFileName(); // 文件名字
   File file = new File(dir, fileName); // 路径+文件名字
   //MediaRecorder可以实现录音和录像。需要严格遵守API说明中的函数调用先后顺序.
   mRecorder = new MP3Recorder(file);
   mCurrentFilePath = file.getAbsolutePath();
//   mMediaRecorder = new MediaRecorder();
//   mCurrentFilePath = file.getAbsolutePath();
//   mMediaRecorder.setOutputFile(file.getAbsolutePath()); // 设置输出文件
//   mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置MediaRecorder的音频源为麦克风
//   mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); // 设置音频的格式
//   mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置音频的编码为AMR_NB
//   mMediaRecorder.prepare();
//   mMediaRecorder.start();
   mRecorder.start(); //开始录音
   isPrepared = true; // 准备结束
   if (mListenter != null) {
    mListenter.wellPrepared();
   }
  } catch (Exception e) {
   e.printStackTrace();
   LogUtil.e("prepareAudio",e.getMessage());
  }
 
 }
 
 /**
  * 随机生成文件名称
  * @return
  */
 private String GenerateFileName() {
  // TODO Auto-generated method stub
  return UUID.randomUUID().toString() + ".mp3"; // 音频文件格式
 }
 
 
 /**
  * 获得音量等级——通过mMediaRecorder获得振幅,然后换算成声音Level
  * maxLevel最大为7;
  * @return
  */
 public int getVoiceLevel(int maxLevel) {
  if (isPrepared) {
   try {
    mRecorder.getMaxVolume();
    return maxLevel * mRecorder.getMaxVolume() / 32768 + 1;
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
  return 1;
 }
 
 /**
  * 释放资源
  */
 public void release() {
  if(mRecorder != null) {
   mRecorder.stop();
   mRecorder = null;
  }
 }
 
 /**
  * 停止录音
  */
 public void stop(){
  if(mRecorder!=null && mRecorder.isRecording()){
   mRecorder.stop();
  }
 }
 
 /**
  * 取消(释放资源+删除文件)
  */
 public void delete() {
  release();
  if (mCurrentFilePath != null) {
   File file = new File(mCurrentFilePath);
   file.delete(); //删除录音文件
   mCurrentFilePath = null;
  }
 }
 
 public String getCurrentFilePath() {
  return mCurrentFilePath;
 }
 
 public int getMaxVolume(){
  return mRecorder.getMaxVolume();
 }
 
 public int getVolume(){
  return mRecorder.getVolume();
 }
}

2. 语音播放器封装

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package com.video.zlc.audioplayer.utils;
 
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
 
/**
 *
 * @author zlc
 *
 */
public class MediaManager {
 
 private static MediaPlayer mMediaPlayer; //播放录音文件
 private static boolean isPause = false;
 
 static {
  if(mMediaPlayer==null){
   mMediaPlayer=new MediaPlayer();
   mMediaPlayer.setOnErrorListener( new MediaPlayer.OnErrorListener() {
 
    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
     mMediaPlayer.reset();
     return false;
    }
   });
  }
 }
 
 
 /**
  * 播放音频
  * @param filePath
  * @param onCompletionListenter
  */
 public static void playSound(Context context,String filePath, MediaPlayer.OnCompletionListener onCompletionListenter){
 
  if(mMediaPlayer==null){
   mMediaPlayer = new MediaPlayer();
   mMediaPlayer.setOnErrorListener( new MediaPlayer.OnErrorListener() {
    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
     mMediaPlayer.reset();
     return false;
    }
   });
  }else{
   mMediaPlayer.reset();
  }
  try {
   //详见“MediaPlayer”调用过程图
   mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
   mMediaPlayer.setOnCompletionListener(onCompletionListenter);
   mMediaPlayer.setDataSource(filePath);
   mMediaPlayer.prepare();
   mMediaPlayer.start();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   LogUtil.e("语音error==",e.getMessage());
  }
 }
 
 
 /**
  * 暂停
  */
 public synchronized static void pause(){
  if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
   mMediaPlayer.pause();
   isPause=true;
  }
 }
 
 //停止
 public synchronized static void stop(){
  if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
   mMediaPlayer.stop();
   isPause=false;
  }
 }
 
 /**
  * resume继续
  */
 public synchronized static void resume(){
  if(mMediaPlayer!=null && isPause){
   mMediaPlayer.start();
   isPause=false;
  }
 }
 
 public static boolean isPause(){
  return isPause;
 }
 
 public static void setPause(boolean isPause) {
  MediaManager.isPause = isPause;
 }
 
 /**
  * release释放资源
  */
 public static void release(){
  if(mMediaPlayer!=null){
   isPause = false;
   mMediaPlayer.stop();
   mMediaPlayer.release();
   mMediaPlayer = null;
  }
 }
 
 public synchronized static void reset(){
  if(mMediaPlayer!=null) {
   mMediaPlayer.reset();
   isPause = false;
  }
 }
 
 /**
  * 判断是否在播放视频
  * @return
  */
 public synchronized static boolean isPlaying(){
 
  return mMediaPlayer != null && mMediaPlayer.isPlaying();
 }
}

3. 语音列表顺序播放

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private int lastPos = -1;
 //播放语音
 private void playVoice(final int position, String from) {
 
  LogUtil.e("playVoice position",position+"");
  if(position >= records.size()) {
   LogUtil.e("playVoice","全部播放完了");
   stopAnimation();
   MediaManager.reset();
   return;
  }
 
  String voicePath = records.get(position).getPath();
  LogUtil.e("playVoice",voicePath);
  if(TextUtils.isEmpty(voicePath) || !voicePath.contains(".mp3")){
   Toast.makeText(this,"语音文件不合法",Toast.LENGTH_LONG).show();
   return;
  }
 
  if(lastPos != position && "itemClick".equals(from)){
   stopAnimation();
   MediaManager.reset();
  }
  lastPos = position;
 
//获取listview某一个条目的图片控件
  int pos = position - id_list_voice.getFirstVisiblePosition();
  View view = id_list_voice.getChildAt(pos);
  id_iv_voice = (ImageView) view.findViewById(R.id.id_iv_voice);
  LogUtil.e("playVoice position",pos+"");
 
  if(MediaManager.isPlaying()){
   MediaManager.pause();
   stopAnimation();
  }else if(MediaManager.isPause()){
   startAnimation();
   MediaManager.resume();
  }else{
   startAnimation();
   MediaManager.playSound(this,voicePath, new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
     //播放完停止动画 重置MediaManager
     stopAnimation();
     MediaManager.reset();
 
     playVoice(position + 1, "loop");
    }
   });
  }
 }

4. 语音列表单个播放 复用问题处理

播放逻辑基本同上

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
private int lastPosition = -1;
 private void playVoice(FendaListInfo.ObjsEntity obj, int position) {
  String videoPath = obj.path;
  if(TextUtils.isEmpty(videoPath) || !videoPath.contains(".mp3")){
   Toast.makeText(this,"语音文件不合法",Toast.LENGTH_LONG).show();
   return;
  }
  if(position != lastPosition){ //点击不同条目先停止动画 重置音频资源
   stopAnimation();
   MediaManager.reset();
  }
  if(mAdapter!=null)
   mAdapter.selectItem(position, lastPosition);
  lastPosition = position;
 
  id_iv_voice.setBackgroundResource(R.drawable.animation_voice);
  animationDrawable = (AnimationDrawable) id_iv_voice.getBackground();
  if(MediaManager.isPlaying()){
   stopAnimation();
   MediaManager.pause();
  }else if(MediaManager.isPause()){
   startAnimation();
   MediaManager.resume();
  }else{
   startAnimation();
   MediaManager.playSound(this,videoPath, new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mp) {
     LogUtil.e("onCompletion","播放完成");
     stopAnimation();
     MediaManager.stop();
    }
   });
  }
 }
 
//核心方法
 //点击了某一个条目 这个条目isSelect=true 上一个条目isSelect需要改为false 防止滑动过程中 帧动画复用问题
 public void selectItem(int position, int lastPosition) {
 
  LogUtil.e("selectItem"," ;lastPosition="+lastPosition+" ;position="+position);
  if(lastPosition >= 0 && lastPosition < mDatas.size() && lastPosition != position){
   FendaListInfo.ObjsEntity bean = mDatas.get(lastPosition);
   bean.isSelect = false;
   mDatas.set(lastPosition, bean);
   notifyDataSetChanged();
  }
 
  if(position < mDatas.size() && position != lastPosition){
   FendaListInfo.ObjsEntity bean = mDatas.get(position);
   bean.isSelect = true;
   mDatas.set(position,bean);
  }
 }
/**
 * 适配器图片播放的动画处理
 */
private void setVoiceAnimation(ImageView iv_voice, FendaListInfo.ObjsEntity obj) {
 
  //处理动画复用问题
  AnimationDrawable animationDrawable;
  if(obj.isSelect){
   iv_voice.setBackgroundResource(R.drawable.animation_voice);
   animationDrawable = (AnimationDrawable) iv_voice.getBackground();
   if(MediaManager.isPlaying() && animationDrawable!=null){
    animationDrawable.start();
   }else{
    iv_voice.setBackgroundResource(R.drawable.voice_listen);
    animationDrawable.stop();
   }
  }else{
   iv_voice.setBackgroundResource(R.drawable.voice_listen);
  }
}

5.下载地址

Android实现语音播放与录音

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/rjgcszlc/article/details/78036010

标签:

相关文章

热门资讯

2022年最旺的微信头像大全 微信头像2022年最新版图片
2022年最旺的微信头像大全 微信头像2022年最新版图片 2022-01-10
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
返回顶部