Android 使用MediaRecorder录音调用stop()方法的时候报错

相逢意气为君饮,系马高楼垂柳边。这篇文章主要讲述Android 使用MediaRecorder录音调用stop()方法的时候报错相关的知识,希望能为你提供帮助。
本文转载自:http://blog.csdn.net/u014737138/article/details/49738827
这个问题在网上看到了太多的答案,一直提示说按照官网的api的顺序来,其实解决问题的方法不是这样的,那样没法解决问题,照着那个顺序来也米有用
 
我们得知道为什么它停止不了,为什么停止闪退了,
 
这里面有个结论就是:闪退必然是出现了控制值的错误,在Java中就是java.lang.NullXXException的错误
 
好像没有其他的原因导致闪退把,
 
stop 就删除,是因为stop的对象不存在,这个懂把,
stop对象不存在,说明对象new失败,这个懂吧,
stop的对象new失败,那就需要看new执行了哪些操作了:
 
[java]  view plain  copy  

  1. < strong> < span  style="font-size:18px; "> mr=new  MediaRecorder();    
  2. mr.setAudiosource(MediaRecorder.AudioSource.MIC);    
  3. mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);    
  4. mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    
  5. mr.setMaxDuration(10000);    
  6. mr.setOutputFile(Environment.getExternalStorageDirectory().getPath()+File.separator+"fisii77s.3gp");    
  7. mr.prepare();    
  8. mr.start(); < /span> < /strong>    

我相信大家都是这样的做法,关键是我们前面包了一层if(mr==null)的判断了
 
我在代码中报错之前是这样写的:
 
[java]  view plain  copy  
  1. < strong> < span  style="font-size:18px; ">     public  void  start(Context  context,  String  name)  {   
  2.                 if  (!Environment.getExternalStorageState().equals(   
  3.                                 android.os.Environment.MEDIA_MOUNTED))  {   
  4.                         return;    
  5.                 }   
  6.                 if  (mRecorder  ==  null)  {   
  7.                         mRecorder  =  new  MediaRecorder();    
  8.                         mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);    
  9.                         mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);    
  10.                         mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    
  11.                         mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context,  name));    
  12.                         try  {   
  13.                                 mRecorder.prepare();    
  14.                                 mRecorder.start();    
  15.    
  16.                                 mEMA  =  0.0;    
  17.                         }  catch  (IllegalStateException  e)  {   
  18.                                 System.out.print(e.getMessage());    
  19.                         }  catch  (IOException  e)  {   
  20.                                 System.out.print(e.getMessage());    
  21.                         }   
  22.    
  23.                 }   
  24. }< /span> < /strong>    
也就是说如果对象存在,没有被销毁掉,我就不用创建了,按照常理说,确实应该这样判断对吧,可是常理一般都是错误的,
 
在java中 判断 一个对象是否为空确实是 == null   关键是 ==null是有谁来判断的   这个好像是说面试的时候经常这样考   我这里还是讲讲我一直那么理解的东西啊,本人还在读书,希望对以后找工作面试的时候有用 哈哈
== 这个判断是地址值比较的,equals是内容值比较的
【Android 使用MediaRecorder录音调用stop()方法的时候报错】== 这个地址值是指堆内存的,equals这个值是指在栈内存中的
 
在我们知道null判断的机制的了之后,我们就要去考虑,如果这个对象还存在,我们是否能直接用这个对象呢,经过测试答案是不行的,
 
接下来再接着说,如果我们第一次创建一个MediaRecorder对象,当我们录音结束之后肯定是停止并且释放了的,否则录音文件就不成功了,
停止,停止的是jni对象,释放,释放的jni里面的对象,同时也释放了java对象里面的栈内存的值,堆内存还保留着呢,引用为空   这里搞明白了,原因也就出来了,
关于这里面jni机制如果不懂,可以看我上篇文章,讲解的很详细
释放之后,如果马上执行第二次录音,这个时候上面的if代码就需要判断了,很明显if里面的语句是不会被执行的,因为堆内存没有被释放掉啊,但是jni里面的对象全部被释放掉了
 
这个时候如果你还用这个对象去录音,那么结果就是你对着空气说话,录的音也成了空气,然后你松开手指也就是录音对象停止的时候,无法停止了,因为jni对象是空的,不存在,怎么去停止呢,程序直接闪退,原因就是这样的了
 
解决办法就是这个时候如果你的对象不为空,你需要再重新创建一次,主要是保证你录音不会成为空气,
 
 
[java]  view plain  copy  
  1. < strong> < span  style="font-size:18px; ">     public  void  start(Context  context,  String  name)  {   
  2.                 if  (!Environment.getExternalStorageState().equals(   
  3.                                 android.os.Environment.MEDIA_MOUNTED))  {   
  4.                         return;    
  5.                 }   
  6.                 if  (mRecorder  ==  null)  {   
  7.                         mRecorder  =  new  MediaRecorder();    
  8.                         mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);    
  9.                         mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);    
  10.                         mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    
  11.                         mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context,  name));    
  12.                         try  {   
  13.                                 mRecorder.prepare();    
  14.                                 mRecorder.start();    
  15.    
  16.                                 mEMA  =  0.0;    
  17.                         }  catch  (IllegalStateException  e)  {   
  18.                                 System.out.print(e.getMessage());    
  19.                         }  catch  (IOException  e)  {   
  20.                                 System.out.print(e.getMessage());    
  21.                         }   
  22.    
  23.                 }else{   
  24.                         stop();    
  25.                         mRecorder  =  new  MediaRecorder();    
  26.                         mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);    
  27.                         mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);    
  28.                         mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    
  29.                         mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context,  name));    
  30.                         try  {   
  31.                                 mRecorder.prepare();    
  32.                         }  catch  (IllegalStateException  |  IOException  e)  {   
  33.                                 //  TODO  Auto-generated  catch  block   
  34.                                 e.printStackTrace();    
  35.                         }   
  36.                         mRecorder.start();    
  37.                 }   
  38.         }< /span> < /strong>    

代码就变成这样了,其实,这里面更简单点就是每次不判断,进来直接把原来的停止,然后再创建 可以省掉很多代码了
 
 
然后就是stop函数,一定要写对,否则还是报错的哦:
 
 
[java]  view plain  copy  
  1. < strong> < span  style="font-size:18px; ">     public  void  stop()  {   
  2.                 if  (mRecorder  !=  null)  {   
  3.                         try  {   
  4.                                 mRecorder.stop();    
  5.                         }  catch  (IllegalStateException  e)  {   
  6.                                 //  TODO  如果当前java状态和jni里面的状态不一致,   
  7.                                 //e.printStackTrace();    
  8.                                 mRecorder  =  null;    
  9.                                 mRecorder  =  new  MediaRecorder();    
  10.                         }   
  11.                         mRecorder.release();    
  12.                         mRecorder  =  null;    
  13.                 }   
  14.         }< /span> < /strong>    

这里面有人肯定问,你这里面stop已经搞了异常抛出,为什么上面的创建还加上else那样的代码呢,
 
 
这里面也是机型的原因然后导致我最终还是保留了这段代码   因为要保证你说的话,录音的音不会成为空气啊   这也是很重要的bug啊

    推荐阅读