安卓AudioRecord实现录音和播放,可以暂停和获取声音的大小,格式为amr和wav,可以对音频进行加密
来源:互联网 发布:手机网络抓包工具 编辑:程序博客网 时间:2024/05/22 10:28
最近项目要求做一个录音功能,要可以暂停的,然后对音频进行加密解密,还要根据声音大小做一个自定义的柱形图,废话不多说,下面进行录音功能实现:
项目大概长这样:
设计的思路:
由于自带的AudioRecord没有pauseRecord()方法,我把开始录音-->(暂停/继续录音)...-->停止录音叫做一次录音,点击一次暂停就会产生一个文件(.pcm),再点击的时候对文件进行继续写入。
对类的说明:
- AudioRecorder:封装了录音的方法:创建录音对象、开始、暂停、停止、取消,使用静态枚举类Status来记录录音的状态。
- AudioFileUtils:文件工具类,用于文件路径的获取
- AudioEncoder:对文件进行转码的父类,采用mvp模式,具体实现看子类的
- AmrEncoder:继承AudioEncoder,实现父类的转码方法,amr格式。
- WavEncoder:继承AudioEncoder,实现父类的转码方法,wav格式。
- WaveHeader: wav文件头
- onVoluneListener:监听录音分贝大小,用于拓展业务的处理。
- RecordService:将录音功能集成封装在服务里面,暴露几个方法调用的接口
- AESUtils:用aes对音频文件进行加解密,提高用户信息的安全性。
开始之前记得添加权限:
<!-- 获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 假如我们要保存录音,还需要以下权限 -->
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- SD卡权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 假如我们要保存录音,还需要以下权限 -->
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- SD卡权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
接下来就是关键代码:
1、AudioRecorder类:
package com.zqr.snake.mytest.record3;import android.media.AudioFormat;import android.media.AudioRecord;import android.media.MediaRecorder;import android.text.TextUtils;import android.util.Log;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class AudioRecorder { private static final String TAG = "AudioRecorder"; private int audioInput = MediaRecorder.AudioSource.MIC;//来源 private int audioSampleRate = 8000;//频率 private int audioChannel = AudioFormat.CHANNEL_IN_MONO;//声道 private int audioEncode = AudioFormat.ENCODING_PCM_16BIT;//编码样式 private int bufferSizeInBytes = 0; private AudioRecord audioRecord; private Status status = Status.STATUS_NO_READY; protected String pcmFileName; private Timer timer; private TimerTask timerTask; private int currentPosition = 0; private CallBack callBack; private int lastVolumn = 0;//录音的分贝 private AudioEncoder encoder;//编码格式 public AudioRecorder(CallBack callBack, AudioEncoder encoder) { String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); pcmFileName = AudioFileUtils.getPcmFileAbsolutePath(fileName); this.encoder = encoder;// encoder.init(audioSampleRate, 16, 1); File file = new File(pcmFileName); if (file.exists()) { file.delete(); } status = Status.STATUS_READY; this.callBack = callBack; } public void setAudioInput(int audioInput) { this.audioInput = audioInput; } public void setAudioSampleRate(int audioSampleRate) { this.audioSampleRate = audioSampleRate; } public void setAudioChannel(int audioChannel) { this.audioChannel = audioChannel; } public void setEncoder(AudioEncoder encoder) { this.encoder = encoder; } private void startTimer() { if (timer == null) timer = new Timer(); if (timerTask != null) { timerTask.cancel(); } timerTask = new TimerTask() { @Override public void run() { currentPosition++; if (callBack != null && status == Status.STATUS_START) { callBack.recordProgress(currentPosition); callBack.volumn(lastVolumn); } } }; timer.schedule(timerTask, 0, 100); } private void stopTimer() { if (timer != null) { timer.cancel(); timer = null; } if (timerTask != null) { timerTask.cancel(); timerTask = null; } } public void startRecord() { bufferSizeInBytes = AudioRecord.getMinBufferSize(audioSampleRate, audioChannel, audioEncode); audioRecord = new AudioRecord(audioInput, audioSampleRate, audioChannel, audioEncode, bufferSizeInBytes); if (status == Status.STATUS_NO_READY) { return;// throw new IllegalStateException("not init"); } if (status == Status.STATUS_START) { return;// throw new IllegalStateException("is recording "); } Log.d("AudioRecorder2", "===startRecord===" + audioRecord.getState()); audioRecord.startRecording(); new Thread(new Runnable() { @Override public void run() { recordToFile(); } }).start(); startTimer(); } public void stop() { currentPosition = 0; if (status != Status.STATUS_START && status != Status.STATUS_PAUSE) { return;// throw new IllegalStateException("not recording"); } else { stopRecorder(); makeDestFile(); status = Status.STATUS_READY; } } //文件进行转码 private void makeDestFile() { if (encoder == null) return; new Thread() { @Override public void run() { encoder.init(audioSampleRate, audioSampleRate * 16 * audioRecord.getChannelCount(), audioRecord.getChannelCount()); encoder.encode(pcmFileName); releaseRecorder(); } }.run(); } /** * 取消录音 */ public void release() { Log.d("AudioRecorder2", "===release==="); stopRecorder(); releaseRecorder(); status = Status.STATUS_READY; clearFiles(); } //释放资源 private void releaseRecorder() { if (audioRecord != null) { audioRecord.release(); audioRecord = null; } } //停止录音 private void stopRecorder() { stopTimer(); if (audioRecord != null) { try { audioRecord.stop(); } catch (Exception e) { e.printStackTrace(); } } } /** * 清除文件 */ public void clearFiles() { try { File pcmfile = new File(pcmFileName); if (pcmfile.exists()) pcmfile.delete(); if (encoder != null && !TextUtils.isEmpty(encoder.getDestFile())) { File file = new File(encoder.getDestFile()); if (file.exists()) file.delete(); } }catch (Exception e){ e.printStackTrace(); } } //将音频写入文件 private void recordToFile() { byte[] audiodata = new byte[bufferSizeInBytes]; FileOutputStream fos = null; int readsize = 0; try { fos = new FileOutputStream(pcmFileName, true); } catch (FileNotFoundException e) { Log.e("AudioRecorder", e.getMessage()); } status = Status.STATUS_START; while (status == Status.STATUS_START && audioRecord != null) { readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes); if (AudioRecord.ERROR_INVALID_OPERATION != readsize && fos != null) { try { //get the volumn 1--10 int sum = 0; for (int i = 0; i < readsize; i++) { sum += Math.abs(audiodata[i]); } if (readsize > 0) { int raw = sum / readsize; lastVolumn = raw > 10 ? raw - 10 : 0; Log.i(TAG, "writeDataTOFile: volumn -- " + raw + " / lastvolumn -- " + lastVolumn); } if (readsize > 0 && readsize <= audiodata.length) fos.write(audiodata, 0, readsize); } catch (IOException e) { Log.e("AudioRecorder", e.getMessage()); } } } try { if (fos != null) { fos.close(); } } catch (IOException e) { Log.e("AudioRecorder", e.getMessage()); } } public int getCurrentPosition() { return currentPosition; } /** * 获取当前的录音状态 * @return */ public Status getStatus() { return status; } /** * 获取当前的录音文件的位置 * @return */ public String getVoiceFilePath() { return encoder == null ? pcmFileName : encoder.getDestFile(); } /** * 录音的状态 */ public enum Status { STATUS_NO_READY, STATUS_READY, STATUS_START, STATUS_PAUSE, STATUS_STOP } public interface CallBack { public void recordProgress(int progress); public void volumn(int volumn); } /** * 暂停录音 */ public void pauseRecord() { Log.d("AudioRecorder2","===pauseRecord==="); if (status != Status.STATUS_START) { throw new IllegalStateException("没有在录音"); } else { stopRecorder();// audioRecord.stop(); status = Status.STATUS_PAUSE; } }}
2.AudioEncoder类:
package com.zqr.snake.mytest.record3;import android.annotation.TargetApi;import android.media.MediaExtractor;import android.media.MediaFormat;import android.os.Build;import android.support.annotation.NonNull;import java.io.IOException;/** * */public abstract class AudioEncoder { protected int SAMPLE_RATE = 8000; protected int BIT_RATE = 64; protected int CHANNEL_COUNT = 1; protected String destinationFile; public void init(int SAMPLE_RATE, int BIT_RATE, int CHANNEL_COUNT) { this.SAMPLE_RATE = SAMPLE_RATE; this.BIT_RATE = BIT_RATE; this.CHANNEL_COUNT = CHANNEL_COUNT; } public String getDestFile() { return destinationFile; } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @NonNull protected MediaFormat getMediaFormat(String sourceFile) throws IOException { MediaExtractor mex = new MediaExtractor(); mex.setDataSource(sourceFile); return mex.getTrackFormat(0); } public abstract void encode(String sourceFile);}3.AmrEncoder(这里我只分享amr的类)
package com.zqr.snake.mytest.record3;import android.annotation.SuppressLint;import android.annotation.TargetApi;import android.media.MediaCodec;import android.media.MediaFormat;import android.os.Build;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.nio.ByteBuffer;import java.text.SimpleDateFormat;import java.util.Date;/** * */public class AmrEncoder extends AudioEncoder { private static byte[] header = new byte[]{'#', '!', 'A', 'M', 'R', '\n'}; @Override public void init(int SAMPLE_RATE, int BIT_RATE, int CHANNEL_COUNT) { super.init(SAMPLE_RATE, BIT_RATE, CHANNEL_COUNT); String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); destinationFile = AudioFileUtils.getAmrFileAbsolutePath(fileName); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @SuppressLint("WrongConstant") @Override public void encode(String sourceFile) { try { MediaCodec encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AMR_NB); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_NB); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, SAMPLE_RATE); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, CHANNEL_COUNT); format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE); encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); File pcmFile = new File(sourceFile); FileInputStream fis = new FileInputStream(pcmFile); File armFIle = new File(destinationFile); FileOutputStream fos = new FileOutputStream(armFIle); fos.write(header); encoder.start(); ByteBuffer[] codecInputBuffers = encoder.getInputBuffers(); ByteBuffer[] codecOutputBuffers = encoder.getOutputBuffers(); byte[] tempBuffer = new byte[88200]; boolean hasMoreData = true; MediaCodec.BufferInfo outBuffInfo = new MediaCodec.BufferInfo(); double presentationTimeUs = 0; int totalBytesRead = 0; do { int inputBufIndex = 0; while (inputBufIndex != -1 && hasMoreData) { inputBufIndex = encoder.dequeueInputBuffer(0); if (inputBufIndex >= 0) { ByteBuffer dstBuf = codecInputBuffers[inputBufIndex]; dstBuf.clear(); int bytesRead = fis.read(tempBuffer, 0, dstBuf.limit()); if (bytesRead == -1) { // -1 implies EOS hasMoreData = false; encoder.queueInputBuffer(inputBufIndex, 0, 0, (long) presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); } else { totalBytesRead += bytesRead; dstBuf.put(tempBuffer, 0, bytesRead); encoder.queueInputBuffer(inputBufIndex, 0, bytesRead, (long) presentationTimeUs, 0); presentationTimeUs = 1000000l * (totalBytesRead / 2) / SAMPLE_RATE; } } } // Drain audio int outputBufIndex = 0; while (outputBufIndex != MediaCodec.INFO_TRY_AGAIN_LATER) { outputBufIndex = encoder.dequeueOutputBuffer(outBuffInfo, 0); if (outputBufIndex >= 0) { ByteBuffer encodedData = codecOutputBuffers[outputBufIndex]; encodedData.position(outBuffInfo.offset); encodedData.limit(outBuffInfo.offset + outBuffInfo.size); byte[] outData = new byte[outBuffInfo.size]; encodedData.get(outData, 0, outBuffInfo.size); fos.write(outData, 0, outBuffInfo.size); encoder.releaseOutputBuffer(outputBufIndex, false); } } } while (outBuffInfo.flags != MediaCodec.BUFFER_FLAG_END_OF_STREAM); if (fis != null) { fis.close(); fis = null; } if (fos != null) { fos.flush(); fos.close(); } File oldfile = new File(sourceFile); if (oldfile.exists()) { oldfile.delete(); } AESUtils.Encrypt(destinationFile,"key"); } catch (Exception e) { e.printStackTrace(); } }}
4.AudioFileUtils(文件管理的类)
package com.zqr.snake.mytest.record3;import android.os.Environment;import android.text.TextUtils;import java.io.File;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class AudioFileUtils { private static String rootPath = "audiorecord"; private final static String AUDIO_PCM_BASEPATH = "/" + rootPath + "/pcm/"; private final static String AUDIO_WAV_BASEPATH = "/" + rootPath + "/wav/"; private final static String AUDIO_AMR_BASEPATH = "/" + rootPath + "/amr/"; private final static String AUDIO_TEMP_BASEPATH = "/" + rootPath + "/temp/";//临时文件 public static void setRootPath(String rootPath) { AudioFileUtils.rootPath = rootPath; } public static String getPcmFileAbsolutePath(String fileName) { if (TextUtils.isEmpty(fileName)) { throw new NullPointerException("fileName isEmpty"); } String mAudioRawPath = ""; if (!fileName.endsWith(".pcm")) { fileName = fileName + ".pcm"; } String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + rootPath + "/pcm/"; File file = new File(fileBasePath); if (!file.exists()) { file.mkdirs(); } mAudioRawPath = fileBasePath + fileName; return mAudioRawPath; } public static String getWavFileAbsolutePath(String fileName) { if (fileName == null) { throw new NullPointerException("fileName can't be null"); } String mAudioWavPath = ""; if (!fileName.endsWith(".wav")) { fileName = fileName + ".wav"; } String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + rootPath + "/wav/"; File file = new File(fileBasePath); if (!file.exists()) { file.mkdirs(); } mAudioWavPath = fileBasePath + fileName; return mAudioWavPath; } public static String getAmrFileAbsolutePath(String fileName) { if (fileName == null) { throw new NullPointerException("fileName can't be null"); } String mAudioWavPath = ""; if (!fileName.endsWith(".amr")) { fileName = fileName + ".amr"; } String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + rootPath + "/amr/"; File file = new File(fileBasePath); if (!file.exists()) { file.mkdirs(); } mAudioWavPath = fileBasePath + fileName; return mAudioWavPath; } //获取临时文件的方法名字 public static String getTempFileAbsolutePath(String fileName) { if (fileName == null) { throw new NullPointerException("fileName can't be null"); } String mAudioWavPath = ""; if (!fileName.endsWith(".amr")) { fileName = fileName + ".amr"; } String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + rootPath + "/temp/"; File file = new File(fileBasePath); if (!file.exists()) { file.mkdirs(); } mAudioWavPath = fileBasePath + fileName; return mAudioWavPath; } /** * 获取全部amr文件列表 * * @return */ public static List<File> getAmrFiles() { List<File> list = new ArrayList<>(); String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + rootPath + "/amr/"; File rootFile = new File(fileBasePath); if (!rootFile.exists()) { } else { File[] files = rootFile.listFiles(); for (File file : files) { list.add(file); } } Collections.reverse(list); //倒序排列 return list; }}
5.对音频文件进行加解密的类AESUtils:
package com.zqr.snake.mytest.record3;import android.util.Log;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.security.SecureRandom;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;public class AESUtils { /* 加密 */ private static byte[] encryptVoice(String seed, byte[] clearbyte) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = encrypt(rawKey, clearbyte); return result; } /* 解密 */ private static byte[] decryptVoice(String seed, byte[] encrypted) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = decrypt(rawKey, encrypted); return result; } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr.setSeed(seed); kgen.init(128, sr); SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] encrypted = cipher.doFinal(clear); return encrypted; } private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } /** * 加密 - AES */ public static void Encrypt(String Path,String seed) {// Log.d("加密 - AES", "----加密开始时间: " + new Date().getTime()/1000); FileInputStream fis = null; FileOutputStream fos = null; boolean isSuccess = true; try { File oldFile = new File(Path); fis = new FileInputStream(oldFile); byte[] oldByte = new byte[(int) oldFile.length()]; fis.read(oldByte); // 读取 byte[] newByte = AESUtils.encryptVoice(seed, oldByte); // 加密 fos = new FileOutputStream(oldFile); fos.write(newByte); } catch (FileNotFoundException e) { isSuccess = false; e.printStackTrace(); } catch (IOException e) { isSuccess = false; e.printStackTrace(); } catch (Exception e) { isSuccess = false; e.printStackTrace(); } finally { try { fis.close(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (isSuccess) Log.d("加密 - AES", "加密成功"); else Log.d("加密 - AES", "加密失败");// Log.d("加密 - AES", "----加密结束时间: " + new Date().getTime()/1000);// Log.i("加密 - AES", "保存成功"); } /** * 解密 - AES */ public static String Decrypt(String playerPath,String seed) {// Log.d("解密 - AES", "----解密开始时间: " + new Date().getTime()); File oldFile = new File(playerPath);// File tempFile = new File(AudioFileUtils.getTempFileAbsolutePath(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()))); File tempFile = new File(AudioFileUtils.getTempFileAbsolutePath(oldFile.getName())); FileInputStream fis = null; FileOutputStream fos = null; boolean isSuccess = true; byte[] oldByte = new byte[(int) oldFile.length()]; try { fis = new FileInputStream(oldFile); fis.read(oldByte); byte[] newByte = AESUtils.decryptVoice(seed, oldByte); // 解密 fos = new FileOutputStream(tempFile); fos.write(newByte); } catch (FileNotFoundException e) { isSuccess = false; e.printStackTrace(); } catch (IOException e) { isSuccess = false; e.printStackTrace(); } catch (Exception e) { isSuccess = false; e.printStackTrace(); } try { fis.close(); fos.close(); } catch (Exception e) { e.printStackTrace(); }// Log.d("解密 - AES", "----解密结束时间: " + new Date().getTime()); if (isSuccess){ Log.i("解密 - AES", "解密成功"); return tempFile.getPath(); } else { Log.i("解密 - AES", "解密失败"); return ""; } }}
最后就是对这些功能进行封装在服务RecordService:
package com.zqr.snake.mytest.record3;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.Binder;import android.os.IBinder;import android.text.TextUtils;import android.util.Log;import java.io.File;public class RecordService extends Service { private MyIBinder myIBinder; private AudioRecorder audioRecorder; private MediaPlayer mediaPlayer; private int mVolume; private String currentPlayPath; /** * 更新分贝的回调接口 */ private onVoluneListener listener; /** * 注册回调接口的方法,供外部调用 * @param onProgressListener */ public void setOnProgressListener(onVoluneListener onProgressListener) { this.listener = onProgressListener; } @Override public IBinder onBind(Intent intent) { return myIBinder; //返回的MyIBinder对象会在onServiceConnected()中调用 } @Override public void onCreate() { super.onCreate(); myIBinder =new MyIBinder();//启动服务时即创建Binder对象 initRecorder(); initPlayer(); } @Override public void onDestroy() { super.onDestroy(); } private void initPlayer() { mediaPlayer = new MediaPlayer(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mediaPlayer.start(); } }); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { if (!TextUtils.isEmpty(currentPlayPath)){ File file = new File(currentPlayPath); if (file.exists()) file.delete(); currentPlayPath = ""; } } }); } private void initRecorder() { audioRecorder = new AudioRecorder(new AudioRecorder.CallBack() { @Override public void recordProgress(final int progress) { if (listener != null){ listener.recordProgress(progress); } } @Override public void volumn(int volumn) { if (listener != null){ listener.volume(volumn); } } }, new AmrEncoder()); } //代理人 public class MyIBinder extends Binder implements RecordInterface{ /** * 获取当前Service的实例 * @return */ public RecordService getService(){ return RecordService.this; } /** * 开始录制 */ @Override public void start() { RecordService.this.startReecrd(); } /** * 暂停录制 */ @Override public AudioRecorder.Status pause() { return RecordService.this.pauseReecrd(); } /** * 开始播放 */ @Override public void paly() { RecordService.this.palyReecrd(); } /** * 取消录制 */ @Override public void cancle() { RecordService.this.cancleReecrd(); } /** * 停止录制 */ @Override public void stop() { RecordService.this.stopReecrd(); } /** * 获取实时分贝大小 */ @Override public int getVolume() { return mVolume; } /** * 设置录制保存路径 */ @Override public void setPath(String path) { RecordService.this.setRootPath(path); } /** * 停止播放 */ @Override public void stopPlay() { RecordService.this.stopPalyReecrd(); } } public void startReecrd(){ audioRecorder.startRecord(); } public void cancleReecrd(){ audioRecorder.release(); } public AudioRecorder.Status pauseReecrd(){ try { if (audioRecorder.getStatus() == AudioRecorder.Status.STATUS_START) { //暂停录音 audioRecorder.pauseRecord();// btn_pause.setText("继续录音"); } else { audioRecorder.startRecord();// btn_pause.setText("暂停录音"); } } catch (IllegalStateException e) { e.printStackTrace(); }finally { return audioRecorder.getStatus(); } } public void stopReecrd(){ audioRecorder.stop(); } public void setRootPath(String path){ AudioFileUtils.setRootPath(path); } public void palyReecrd(){ try { if (mediaPlayer == null) initPlayer(); String path = AESUtils.Decrypt(audioRecorder.getVoiceFilePath(),"key"); if (TextUtils.isEmpty(path)) return; mediaPlayer.reset(); mediaPlayer.setDataSource(path); currentPlayPath = path; mediaPlayer.prepareAsync(); } catch (Exception e) { e.printStackTrace(); } } public void stopPalyReecrd(){ if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } } public interface RecordInterface { void start(); AudioRecorder.Status pause(); void paly(); void cancle(); void stop(); int getVolume(); void setPath(String path); void stopPlay(); }}
最后项目源码下载地址:http://download.csdn.net/download/zqr772791008/10108309
欢迎大家一起来学习!!!
阅读全文
0 0
- 安卓AudioRecord实现录音和播放,可以暂停和获取声音的大小,格式为amr和wav,可以对音频进行加密
- 安卓录音amr文件在PC端进行格式转换和播放
- Android AMR格式录音和播放,仿微信
- 支持暂停和继续操作的WAV音频播放
- java.media类实现的可以播放WAV和MP3格式的文件
- AudioRecord、AudioTractor实现音频的录制和播放
- ALSA的WAV播放和录音程序
- 使用AudioRecord和 AudioTrack实现录音并播放
- android 使用 audiorecord 和 audiotrack 实现实时录音播放
- Android两种录音方式MediaRecorder和AudioRecord实现了实时获取音量大小
- 播放音频的点击播放和暂停
- MFC 声音的播放和录音的实现(一)
- MFC 声音的播放和录音的实现(一)
- 即时通讯收发语音,兼容安卓wav和amr格式互转
- 耳机上按键可以播放和暂停音乐的?
- MFC播放声音和录音的实现(二)
- MFC播放声音和录音的实现(三)
- Android Multimedia实战(六)音频 MediaRecorder和AudioRecord录音与MediaPlayer和AudioTrack播放
- selenium-Python之unittest(三)
- 二叉苹果树
- 关于byte与Mat类型的互换
- Oracle:序列
- JS-引用类型
- 安卓AudioRecord实现录音和播放,可以暂停和获取声音的大小,格式为amr和wav,可以对音频进行加密
- 浅析debugfs文件系统调试阶段gpio使用范例
- HNOI2008 BZOJ1010 玩具装箱toy
- 基于opencv的图像拼接(四): 基于stitch类的离线图像拼接
- Direct3D9之二学习资源篇
- 多态(Polymorphism)的实现机制(下)--Java篇
- docker报错FATA [0000] Get http:///var/run/docker.sock/v1.17/version:dial unix /var/run/docker.sock(FAT
- 【hdu 2066】 一个人的旅行
- 运算符与分支结构