標籤:cfile 無法 view hat encode message 順序 cli stat
本文轉載自:http://blog.csdn.net/u014737138/article/details/49738827
這個問題在網上看到了太多的答案,一直提示說按照官網的api的順序來,其實解決問題的方法不是這樣的,那樣沒法解決問題,照著那個順序來也米有用
我們得知道為什麼它停止不了,為什麼停止閃退了,
這裡面有個結論就是:閃退必然是出現了控制值的錯誤,在Java中就是java.lang.NullXXException的錯誤
好像沒有其他的原因導致閃退把,
stop 就刪除,是因為stop的對象不存在,這個懂把,
stop對象不存在,說明對象new失敗,這個懂吧,
stop的對象new失敗,那就需要看new執行了哪些操作了:
[java] view plain copy
- <strong><span style="font-size:18px;">mr=new MediaRecorder();
- mr.setAudioSource(MediaRecorder.AudioSource.MIC);
- mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mr.setMaxDuration(10000);
- mr.setOutputFile(Environment.getExternalStorageDirectory().getPath()+File.separator+"fisii77s.3gp");
- mr.prepare();
- mr.start();</span></strong>
我相信大家都是這樣的做法,關鍵是我們前麵包了一層if(mr==null)的判斷了
我在代碼中報錯之前是這樣寫的:
[java] view plain copy
- <strong><span style="font-size:18px;"> public void start(Context context, String name) {
- if (!Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED)) {
- return;
- }
- if (mRecorder == null) {
- mRecorder = new MediaRecorder();
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context, name));
- try {
- mRecorder.prepare();
- mRecorder.start();
-
- mEMA = 0.0;
- } catch (IllegalStateException e) {
- System.out.print(e.getMessage());
- } catch (IOException e) {
- System.out.print(e.getMessage());
- }
-
- }
- }</span></strong>
也就是說如果對象存在,沒有被銷毀掉,我就不用建立了,按照常理說,確實應該這樣判斷對吧,可是常理一般都是錯誤的,
在java中 判斷 一個對象是否為空白確實是 == null 關鍵是 ==null是有誰來判斷的 這個好像是說面試的時候經常這樣考 我這裡還是講講我一直那麼理解的東西啊,本人還在讀書,希望對以後找工作面試的時候有用 哈哈
== 這個判斷是地址值比較的,equals是內容值比較的
== 這個地址值是指堆記憶體的,equals這個值是指在棧記憶體中的
在我們知道null判斷的機制的了之後,我們就要去考慮,如果這個對象還存在,我們是否能直接用這個對象呢,經過測試答案是不行的,
接下來再接著說,如果我們第一次建立一個MediaRecorder對象,當我們錄音結束之後肯定是停止並且釋放了的,否則錄音檔案就不成功了,
停止,停止的是jni對象,釋放,釋放的jni裡面的對象,同時也釋放了java對象裡面的棧記憶體的值,堆記憶體還保留著呢,引用為空白 這裡搞明白了,原因也就出來了,
關於這裡面jni機制如果不懂,可以看我上篇文章,講解的很詳細
釋放之後,如果馬上執行第二次錄音,這個時候上面的if代碼就需要判斷了,很明顯if裡面的語句是不會被執行的,因為堆記憶體沒有被釋放掉啊,但是jni裡面的對象全部被釋放掉了
這個時候如果你還用這個對象去錄音,那麼結果就是你對著空氣說話,錄的音也成了空氣,然後你鬆開手指也就是錄音對象停止的時候,無法停止了,因為jni對象是空的,不存在,怎麼去停止呢,程式直接閃退,原因就是這樣的了
解決辦法就是這個時候如果你的對象不為空白,你需要再重新建立一次,主要是保證你錄音不會成為空白氣,
[java] view plain copy
- <strong><span style="font-size:18px;"> public void start(Context context, String name) {
- if (!Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED)) {
- return;
- }
- if (mRecorder == null) {
- mRecorder = new MediaRecorder();
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context, name));
- try {
- mRecorder.prepare();
- mRecorder.start();
-
- mEMA = 0.0;
- } catch (IllegalStateException e) {
- System.out.print(e.getMessage());
- } catch (IOException e) {
- System.out.print(e.getMessage());
- }
-
- }else{
- stop();
- mRecorder = new MediaRecorder();
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context, name));
- try {
- mRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- mRecorder.start();
- }
- }</span></strong>
代碼就變成這樣了,其實,這裡面更簡單點就是每次不判斷,進來直接把原來的停止,然後再建立 可以省掉很多代碼了
然後就是stop函數,一定要寫對,否則還是報錯的哦:
[java] view plain copy
- <strong><span style="font-size:18px;"> public void stop() {
- if (mRecorder != null) {
- try {
- mRecorder.stop();
- } catch (IllegalStateException e) {
- // TODO 如果當前java狀態和jni裡面的狀態不一致,
- //e.printStackTrace();
- mRecorder = null;
- mRecorder = new MediaRecorder();
- }
- mRecorder.release();
- mRecorder = null;
- }
- }</span></strong>
這裡面有人肯定問,你這裡面stop已經搞了異常拋出,為什麼上面的建立還加上else那樣的代碼呢,
這裡面也是機型的原因然後導致我最終還是保留了這段代碼 因為要保證你說的話,錄音的音不會成為空白氣啊 這也是很重要的bug啊
Android 使用MediaRecorder錄音調用stop()方法的時候報錯【轉】