Android使用AudioRecord遇到的问题与解决方法

问题:

1、android判断是否禁用了录音权限

      通过判断分贝值是否大于0,在代码中搜索 volume > 0

2、部分手机在调用 audioRecord.startRecording(); 和audioRecord.stop();方法时会抛出异常,例如联想手机

3、部分手机(例如联想)会抛出java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.

      解决方法来源于:http://www.cnblogs.com/mythou/p/3241925.html

       原因:

       

出现上面问题的原因是录音的硬件资源被申请了,但是没有释放,然后你再次申请资源,导致初始化失败。这里需要注意的是不仅仅需要调用Release()方法。还需要把AudioRecord对象置为null,否则还是释放失败。下面是Android 开发网上面的一个对于AudioRecord的释放说明。

Releases the native AudioRecord resources. The object can no longer be used and the reference should be set to null after a call to release()。
扫描二维码关注公众号,回复: 2973343 查看本文章

解决方法在代码中:

 
  1. package com.androidleaf.audiorecord;

  2.  
  3. import android.app.ProgressDialog;

  4. import android.content.Context;

  5. import android.media.AudioFormat;

  6. import android.media.AudioRecord;

  7. import android.media.MediaRecorder;

  8. import android.os.AsyncTask;

  9. import android.os.Bundle;

  10. import android.os.Handler;

  11. import android.os.Message;

  12. import android.util.Log;

  13.  
  14. import com.hisun.phone.core.voice.Device;

  15. import com.todoroo.aacenc.AACEncoder;

  16. import com.todoroo.aacenc.AACToM4A;

  17.  
  18. import java.io.DataInputStream;

  19. import java.io.File;

  20. import java.io.FileInputStream;

  21. import java.io.FileNotFoundException;

  22. import java.io.IOException;

  23. import java.io.RandomAccessFile;

  24.  
  25. import app.jimu.zhiyu.activity.question.AnswerActivity;

  26.  
  27. public class AudioRecordUtils {

  28.  
  29. private final int audioSource = MediaRecorder.AudioSource.MIC;

  30. // 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025

  31. private final int sampleRateInHz = 16000;

  32. // 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道

  33. private final int channelConfig = AudioFormat.CHANNEL_IN_STEREO;

  34. // 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。

  35. private final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

  36.  
  37. private int inBufSize = 0;

  38.  
  39. private AudioRecord audioRecord;

  40.  
  41. private AACEncoder encoder = null;

  42.  
  43. private ProgressDialog mProgressDialog = null;

  44.  
  45. private boolean isRecord = false;

  46.  
  47. private Context mContext;

  48. /**

  49. * 录制的音频文件名称

  50. */

  51. private String mAudioRecordFileName;

  52.  
  53. private static final int RECORDED_INIT_DELETE = 0;

  54.  
  55. private static final int RECORDED_COMPLETED_DELETE = 1;

  56.  
  57. private Handler mHandler;

  58.  
  59. /**

  60. * 是否可以录音 true 可以录音

  61. */

  62. private boolean recordEnable = false;

  63.  
  64. public AudioRecordUtils(Context context,String audioRecordFileName, Handler handler){

  65. mContext = context;

  66. mAudioRecordFileName = audioRecordFileName;

  67. mHandler = handler;

  68. initAudioRecord();

  69. }

  70.  
  71. /**

  72. * 初始化对象

  73. */

  74. private void initAudioRecord(){

  75.  
  76. inBufSize = AudioRecord.getMinBufferSize(

  77. sampleRateInHz,

  78. channelConfig,

  79. audioFormat);

  80.  
  81. audioRecord = new AudioRecord(

  82. audioSource,

  83. sampleRateInHz,

  84. channelConfig,

  85. audioFormat,

  86. inBufSize);

  87.  
  88. encoder = new AACEncoder();

  89. deleteAllFiles(RECORDED_INIT_DELETE);

  90.  
  91. mProgressDialog = new ProgressDialog(mContext);

  92. mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

  93. mProgressDialog.setCanceledOnTouchOutside(false);

  94. mProgressDialog.setCancelable(false);

  95. mProgressDialog.setTitle("提示");

  96. mProgressDialog.setMessage("正在保存录音,请耐心等候......");

  97.  
  98. }

  99.  
  100. /**

  101. * 开始录音

  102. */

  103. public void startRecord(){

  104. new AudioRecordTask().execute();

  105. }

  106.  
  107. /**

  108. * 暂停录音

  109. */

  110. public void pauseRecord(){

  111. isRecord = false;

  112. }

  113.  
  114. /**

  115. * 停止录音

  116. */

  117. public void stopRecord(){

  118. new AudioEncoderTask().execute();

  119. }

  120.  
  121. /**

  122. * 重新录制

  123. */

  124. public void reRecord(){

  125. //重新录制时,删除录音文件夹中的全部文件

  126. deleteAllFiles(RECORDED_INIT_DELETE);

  127. }

  128.  
  129. private void encodeAudio(){

  130. try {

  131. //读取录制的pcm音频文件

  132. DataInputStream mDataInputStream = new DataInputStream(new FileInputStream(

  133. FileUtils.getPcmFilePath(mAudioRecordFileName)));

  134. byte[] b = new byte[(int) new File(FileUtils.

  135. getPcmFilePath(mAudioRecordFileName)).length()];

  136. mDataInputStream.read(b);

  137. //初始化编码配置

  138. encoder.init(32000, 2, sampleRateInHz, 16, FileUtils.

  139. getAAcFilePath(mAudioRecordFileName));

  140. //对二进制代码进行编码

  141. encoder.encode(b);

  142. //编码完成

  143. encoder.uninit();

  144. //关闭流

  145. mDataInputStream.close();

  146. try {

  147. //将aac文件转码成m4a文件

  148. new AACToM4A().convert(mContext, FileUtils.getAAcFilePath(mAudioRecordFileName),

  149. FileUtils.getM4aFilePath(mAudioRecordFileName));

  150. } catch (IOException e) {

  151. Log.e("ERROR", "error converting", e);

  152. }

  153. deleteAllFiles(RECORDED_COMPLETED_DELETE);

  154. } catch (FileNotFoundException e) {

  155. // TODO Auto-generated catch block

  156. e.printStackTrace();

  157. } catch (IOException e1) {

  158. // TODO Auto-generated catch block

  159. e1.printStackTrace();

  160. }

  161. }

  162.  
  163. class AudioRecordTask extends AsyncTask<Void, Void, Void>{

  164.  
  165. @Override

  166. protected Void doInBackground(Void... params) {

  167. // TODO Auto-generated method stub

  168. if(audioRecord == null){

  169. initAudioRecord();

  170. }

  171. RandomAccessFile mRandomAccessFile = null;

  172. try {

  173. mRandomAccessFile = new RandomAccessFile(new File(

  174. FileUtils.getPcmFilePath(mAudioRecordFileName)), "rw");

  175. byte[] b = new byte[inBufSize/4];

  176. //开始录制音频

  177. try{

  178. // 防止某些手机崩溃,例如联想

  179. audioRecord.startRecording();

  180. }catch (IllegalStateException e){

  181. e.printStackTrace();

  182. }

  183.  
  184. //判断是否正在录制

  185. isRecord = true;

  186. long wait = 0;

  187. long maxWait = 10;

  188. while(isRecord){

  189. //r是实际读取的数据长度,一般而言r会小于buffersize

  190. int r = audioRecord.read(b, 0, b.length);

  191. long v = 0;

  192. // 将 buffer 内容取出,进行平方和运算

  193. for (int i = 0; i < b.length; i++) {

  194. v += b[i] * b[i];

  195. }

  196. // 平方和除以数据总长度,得到音量大小。

  197. double mean = v / (double) r;

  198. double volume = 10 * Math.log10(mean);

  199.  
  200. wait++;

  201. if(wait > maxWait){

  202. wait = 0;

  203. Log.d(this.getClass().getName(), "分贝值:" + volume + " " + (volume > 0));

  204. if(volume > 0){

  205. recordEnable = true;

  206. }

  207. Message msg = new Message();

  208. msg.what = AnswerActivity.STATUS_PREPARE;

  209. Bundle bundle = new Bundle();

  210. bundle.putDouble(Device.VOICE_AMPLITUDE, volume);

  211. msg.obj = bundle;

  212. mHandler.sendMessage(msg);

  213. }

  214.  
  215. //向文件中追加内容

  216. mRandomAccessFile.seek(mRandomAccessFile.length());

  217. mRandomAccessFile.write(b, 0, b.length);

  218. }

  219. //停止录制

  220. try {

  221. // 防止某些手机崩溃,例如联想

  222. audioRecord.stop();

  223. // 彻底释放资源

  224. audioRecord.release();

  225. audioRecord = null;

  226. }catch (IllegalStateException e){

  227. e.printStackTrace();

  228. }

  229. mRandomAccessFile.close();

  230. } catch (FileNotFoundException e) {

  231. // TODO Auto-generated catch block

  232. e.printStackTrace();

  233. } catch (IOException e) {

  234. // TODO Auto-generated catch block

  235. e.printStackTrace();

  236. }

  237. return null;

  238. }

  239. }

  240.  
  241. class AudioEncoderTask extends AsyncTask<Void, Void, Long>{

  242.  
  243. @Override

  244. protected void onPreExecute() {

  245. // TODO Auto-generated method stub

  246. super.onPreExecute();

  247. if(mProgressDialog != null && !mProgressDialog.isShowing()){

  248. // mProgressDialog.show();

  249. Message msg = new Message();

  250. msg.what = 2;

  251. mHandler.sendMessage(msg);

  252. }

  253. }

  254.  
  255. @Override

  256. protected Long doInBackground(Void... params) {

  257. // TODO Auto-generated method stub

  258. encodeAudio();

  259. return null;

  260. }

  261.  
  262. @Override

  263. protected void onPostExecute(Long result) {

  264. // TODO Auto-generated method stub

  265. super.onPostExecute(result);

  266. if(mProgressDialog.isShowing()){

  267. mProgressDialog.cancel();

  268. mProgressDialog.dismiss();

  269. }

  270. }

  271. }

  272.  
  273. /**

  274. * 清空音频录制文件夹中的所有文件

  275. * @param isRecorded

  276. */

  277. public void deleteAllFiles(int isRecorded){

  278. File[] files = new File(FileUtils.getAudioRecordFilePath()).listFiles();

  279. switch (isRecorded) {

  280. case RECORDED_INIT_DELETE:

  281. for(File file: files){

  282. file.delete();

  283. }

  284. break;

  285. case RECORDED_COMPLETED_DELETE:

  286. for(File file: files){

  287. if(!file.getName().equals(mAudioRecordFileName + Constants.M4A_SUFFIX)){

  288. file.delete();

  289. }

  290. }

  291. break;

  292. default:

  293. break;

  294. }

  295. }

  296.  
  297. public boolean isRecordEnable() {

  298. return recordEnable;

  299. }

  300.  

猜你喜欢

转载自blog.csdn.net/ssllkkyyaa/article/details/81903271