Android 筆記 camera.takePicture(),使用flashMode,改變focusMode,continuous-picture中遇到的問題

takePicture()的問題

在攝像頭舊API的使用中,如果要保存全尺寸圖像,只能通過takePicture()
分別是shutterCallback,pictureCallback,pictureCallback
第一個是快門鍵按下以後,第二個是RAW圖像(如果支持的話)生成以後,第三個是jpeg圖像生成以後
一般情況,在第三個Callback裏面操作保存jpeg的動作,然後操作其他動作,比如startPreview(),改變對焦方式,等等

現在發現一個問題,在我按照自己的想法設置好操作以後,如果啓用閃光燈拍照,會在拍照以後沒有重新開始預覽,也就是說startPreview()沒有效果,測試表明,所有的callback都沒有調用.
表現就是,預覽界面靜止不動,不能autofocus,但是可以切換攝像頭以後恢復預覽
而且,如果出現上述現象以後,再次重新開啓APP以後,不使用閃光燈的拍照也會出現問題
再而且,如果出現上述現象以後,使用其他(非原廠)APP拍照,也會出現這樣的問題。比如CAMERA360,NUBIA CAMERA等等
但是,手機重啓以後,在不使用自己的APP之前使用其他APP拍照,完全沒問題,使用閃光燈也沒問題。
總結來說就是,這個現象會影響到其他app,可以猜測是因爲某些全局因素的影響。

測試手機是note3 with android 5.0

mCamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                Toast.makeText(thisActivity, "picture taken", Toast.LENGTH_SHORT).show();
                camera.startPreview();
                isPreviewing = true;
                FileSystem.saveJpegFile(data);
               //以下是問題代碼
               mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                mCameraParameters.setFocusAreas(null);
                mCamera.setParameters(mCameraParameters);
            }
        });

上面的代碼就是問題代碼。經過測試,其他部分完全沒有問題。
如果把上訴代碼的問題部分刪除,那麼APP測試也完全沒有問題,但是添加這一段以後,就會出現如上面描述的問題。
這一段代碼的目的是,讓每次拍照以後把對焦模式設置爲continuous-picture。如果手動點擊屏幕對焦,那麼需要把模式設置爲auto,會運行一次完全的對焦過程,就像大部分拍照app做的那樣。但是對焦完成,拍照完成以後,對焦模式還是auto,不會像continuous-pictur那樣持續對焦,這樣的體驗不好。

需要在拍照以後把模式變成continuous-picture,這樣不需要點擊屏幕也可以對當前畫面對焦,大部分時候可以不需要點擊屏幕對焦也可以直接拍照。

這一段代碼的作用是很重要的,所以必須找到一個方法,能在閃光燈拍照以後切換對焦模式,又不會出現bug

解決問題的探索

以下問題的探索都建立在這個基礎上:使用閃光燈啓用模式,點擊屏幕自動對焦,然後拍照,在保存jpeg的callback裏面設置改變對焦模式功能,將auto模式變成continuous模式,希望能在改變模式以後恢復正常,而不會將preview畫面凍結住。(非閃光燈模式一直都是正常的,如前面描述)
1 將continuous-picture 變成continuous-video
無效

2, 設置一個handler,postdelay執行改變對焦模式,延遲設定在5000毫秒
無效
也就是說,在延遲一段時間以後再改變對焦模式無效,至少5000毫秒時間是不行的,更長的時間沒有測試。
如果設置一個按鍵手動決定什麼時候改變模式,基本上也跟這個postdelay一樣,沒有區別

3,把改變對焦模式的功能設置在callback外面,

mCamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {          
                Toast.makeText(thisActivity, "picture taken", Toast.LENGTH_SHORT).show();
                mCamera.startPreview();
                isPreviewing = true;
                FileSystem.saveJpegFile(data);
            }
        });
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
mCameraParameters.setFocusAreas(null);
mCamera.setParameters(mCameraParameters);
Toast.makeText(thisActivity, "continuous", Toast.LENGTH_SHORT).show();

有效,但是實際測試效果不好,閃光燈打開以後,對焦過程中的預覽看不見,有時候拍照會保存到沒有閃光燈覆蓋的畫面。也就是說,上述問題沒有了,但是不實用。捨棄。

4,設定一個異步runnable,然後執行異步動作
無效

5,乾脆將改變對焦模式功能捨棄,直接重新打開攝像頭。
有效
因爲在之前測試的時候發現,如果轉換攝像頭到前攝像頭,再轉回到後攝像頭以後,一切正常,所以想到這個方法

mCamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {         
                Toast.makeText(thisActivity, "picture taken", Toast.LENGTH_SHORT).show();
                //mCamera.startPreview();捨棄
                //isPreviewing = true;捨棄
                mCamera.release();
                openCamera();
                FileSystem.saveJpegFile(data);
            }
        });

這樣設置以後,程序執行正常了。但是有一個問題,實際拍攝的時候,拍照保存照片以後的延遲邊長,卡頓現象更加突出。本來takepicture以後就會卡頓,API文檔裏面說了會自動停止預覽,需要手動開啓預覽。但是像這樣設置以後,卡頓時間更長,使用體驗非常不理想(至少我本人覺得非常不好)。捨棄。

6,我想到,是不是應該在callback裏面首先設置一個cancelAutofocus()。API裏面說,這個可以退出自動對焦,可以讓continuous-picuture恢復正常持續對焦。
測試有效,效果很好,跟預想的一樣,和其他app一樣

mCamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                mCamera.cancelAutoFocus(); //這一句很關鍵
                //恢復對焦模式
                mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                mCameraParameters.setFocusAreas(null);
                mCamera.setParameters(mCameraParameters);
                //
                mCamera.startPreview();
                isPreviewing = true;
                FileSystem.saveJpegFile(data);
            }
        });

如上這樣,終於達到了預期效果。

總結

也就是說,在pictureCallback裏面,需要設置一個cancelAutofocus(),然後再設置其他功能,就可以恢復正常操作。而如果沒有這一句,會導致閃光燈模式下恢復continuous-picuture失敗,預覽畫面被凍結住,而且會後續影響其他app,直到重啓設備.

原因不得而知,可以猜想跟某個全局設置有關。爲什麼閃光燈模式會出現這樣的問題,猜想是因爲在閃光燈模式下,即便在continuous-picture模式下,程序也會像auto模式一樣自動對焦一次,然後再拍照,這可能會影響到某個全局變量。

所以,設置了cancelAutofocus()恢復正常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章