2013-02-13 80 views
3

我從方法surfaceChanged()調用Camera.setParameters()時出現RuntimeException錯誤。我看到了同一個問題的其他職位,但沒有找到一個明確的解決方案: Issue with setting the parameters to camera在setChanged()中傳遞的寬度和高度不受setParameters()支持?

我的問題是:

  1. 爲什麼要surfaceChanged()來surfaceCreated之後稱爲()?這是直觀的(至少對我來說)在surfaceCreated()中啓動預覽,只是停止它並重新啓動surfaceChanged()中的另一個。

  2. 當第一次調用surfaceChanged()時,什麼決定傳入的寬度和高度?正如前面提到的文章中所建議的,並且在我的實驗中進行了驗證,Camera.setParameters()不一定支持這些值。請參閱下面的代碼片段和日誌信息。

  3. 在調用surfaceChanged()之前,有沒有辦法確保Camera.setParameters()支持寬度和高度值?可以在surfaceChanged()中添加代碼來確保。例如,可以將w和h與所有支持的預覽尺寸進行比較,並將其更改爲最接近的支持值。但是,這樣做會妨礙性能。

以下列表是我的代碼片段和LogCat輸出。日誌記錄信息表明surfaceChanged()中的Camera.setParameters()導致錯誤。如果我註釋掉setParameters()被調用的那一行,我不會再看到錯誤消息。

[編輯:我正在測試亞馬遜Kindle Fire HD。 Android版本是4.0.3,API 15]

代碼片段:

public void surfaceCreated(SurfaceHolder holder) { 
    // Log & debug 
    Log.d(TAG, "surfaceCreated() is called"); 

    // The Surface has been created, now tell the camera where to draw the preview. 
    try { 
     mCamera.setPreviewDisplay(mHolder); 
     mCamera.startPreview(); 
    } catch (IOException e) { 
     Log.d(TAG, "surfaceCreated(): " + e.getMessage()); 
    } 

    if (mHolder.getSurface() == null) { 
     Log.d(TAG, "surfaceCreated(): preview surface does not exist yet!"); 
    } 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    // Log & debug 
    Log.d(TAG, "surfaceDestroyed() is called"); 

    // Stop preview and release camera 
    if (holder.getSurface() != null) { 
     mCamera.stopPreview(); 
     //mCamera.release(); //should we release camera here? 
     //mCamera = null; 
    } 
    else { 
     Log.d(TAG, "surfaceDestroyed(): preview surface does not exist"); 
    } 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    // Log and debug 
    Log.d(TAG, "surfaceChanged() is called with width = " + w); 
    Log.d(TAG, "surfaceChanged() is called with height = " + h); 

    // If your preview can change or rotate, take care of those events here. 
    // Make sure to stop the preview before resizing or reformatting it. 
    if (holder.getSurface() == null) { 
     Log.d(TAG, "surfaceChanged(): preview surface does not exist"); 
     return; 
    } 

    // stop preview before making changes 
    try { 
     mCamera.stopPreview(); 
    } catch (Exception e) { 
     Log.d(TAG, "surfaceChanged(): tried to stop a non-existent preview " + e.getMessage()); 
    } 

    // set preview size and make any resize, rotate or 
    // reformatting changes here 
    Camera.Parameters params = mCamera.getParameters(); 
    List<Size> mSizes = params.getSupportedPreviewSizes(); 

    // list all 25 supported preview sizes 
    // i==25 will cause an "IndexOutofBoundsException" 
    for (int i=0; i<25; i++) { 
     Size mSize = mSizes.get(i); 
     if (mSize == null) break; 
     Log.d(TAG, "surfaceChanged() i = " + i); 
     Log.d(TAG, "surfaceChanged() preview width = " + mSize.width); 
     Log.d(TAG, "surfaceChanged() preview height = " + mSize.height); 
    } 
    Size  mSize = mSizes.get(0); 
    if(mSize != null) { //make sure we don't pull a NullException. 
     if (w > mSize.width) w = mSize.width; 
     if (h > mSize.height) h = mSize.height; 
     params.setPreviewSize(w, h); //set the size, since we know it. 
    } 
    mCamera.setParameters(params); //set the parameters now. 

    // start preview with new settings 
    try { 
     mCamera.setPreviewDisplay(holder); 
     mCamera.startPreview(); 
    } catch (Exception e){ 
     Log.d(TAG, "surfaceChanged() restart preview " + e.getMessage()); 
    } 
} 

logcat的輸出:那你可能會得到這樣的問題

02-13 10:46:08.113: D/CameraPreview(2886): surfaceCreated() is called 
02-13 10:46:08.496: D/CameraPreview(2886): surfaceChanged() is called with width = 1072 
02-13 10:46:08.496: D/CameraPreview(2886): surfaceChanged() is called with height = 705 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 0 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 1280 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 720 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 1 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 960 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 720 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 2 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 800 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 480 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 3 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 720 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 576 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 4 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 720 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 480 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 5 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 768 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 576 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 6 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 640 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 480 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 7 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 320 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 240 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 8 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 352 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 288 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 9 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 240 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 160 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 10 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 176 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 144 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 11 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 160 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 120 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 12 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 128 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 96 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 13 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 720 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 1280 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 14 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 480 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 800 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 15 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 576 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 720 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 16 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 576 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 768 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 17 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 480 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 720 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 18 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 480 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 640 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 19 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 288 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 352 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 20 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 240 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 320 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 21 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 240 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 160 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 22 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 144 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 176 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 23 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 120 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 160 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() i = 24 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview width = 96 
02-13 10:46:08.941: D/CameraPreview(2886): surfaceChanged() preview height = 128 
02-13 10:46:08.957: D/AndroidRuntime(2886): Shutting down VM 
02-13 10:46:08.957: W/dalvikvm(2886): threadid=1: thread exiting with uncaught exception (group=0x40a6c1f8) 
02-13 10:46:08.965: E/AndroidRuntime(2886): FATAL EXCEPTION: main 
02-13 10:46:08.965: E/AndroidRuntime(2886): java.lang.RuntimeException: setParameters failed 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.hardware.Camera.native_setParameters(Native Method) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.hardware.Camera.setParameters(Camera.java:1295) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at com.xyz.camera.CameraPreview.surfaceChanged(CameraPreview.java:109) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.view.SurfaceView.updateWindow(SurfaceView.java:544) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.view.SurfaceView.access$000(SurfaceView.java:81) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:169) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:590) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1630) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2462) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.os.Handler.dispatchMessage(Handler.java:99) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.os.Looper.loop(Looper.java:137) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at android.app.ActivityThread.main(ActivityThread.java:4486) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at java.lang.reflect.Method.invokeNative(Native Method) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at java.lang.reflect.Method.invoke(Method.java:511) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
02-13 10:46:08.965: E/AndroidRuntime(2886):  at dalvik.system.NativeStart.main(Native Method) 
+0

哪個API是你編譯和你測試哪個設備? – Raigex 2013-02-13 19:44:01

+0

@Raigex:很好的問題。亞馬遜Kindle Fire HD(android 4.0.3,API 15)。 – hubeir 2013-02-13 19:50:36

+0

任何人都知道答案問題1? – hubeir 2013-02-13 23:20:12

回答

0

那麼一個是事實由於您使用的是api 15,因此您應該使用getSupportedVideoSizes(),因爲它來自api 11.我在設置某些設備(那些運行honeycomb及更高版本的設備)上的參數時遇到了類似的問題,因爲預覽大小和支持的視頻大小不是總是一樣。

編輯::關於您的意見: 我會輸出所有supportedpreviewsizes爲您的測試設備。你已經有了。然後,我會採取一個(例如:第二,你得到)和靜態設置它用於測試目的

如:

for int (i = 0; i < mSizes.size(); i ++) 
    { 
     Log each size; 
    } 

採取隨機尺寸如此:如480 * 800,並將其設置

params.setPreviewSize(480, 800); 

這會告訴你如果設置預覽大小使得顯示正確的大小。

EDIT2: 我會再次更新我的回答澄清我的評論

內onSurfaceChanged 有兩個變量

int width = 0; 
int height = 0; 

然後在if語句

if (w > mSize.width) width = mSize.width; 
if (h > mSize.height) height = mSize.height; 

而且你是什麼這樣做是相當於

mSizes.get(mSize.size()-1)。因爲你w和h總是會大於mSize.width和mSize.height

編輯3: 確定根據你的意見。 您想在onSufaceCreated() 中初始化攝像頭,並將setPreviewSize(w,h)更改爲setPreviewSize(mSizes.get(mSizes.size()-1).width,mSizes.get(mSizes.size()-1 )。高度);

然後添加設置surfaceView到任何你想要的大小()

surfaceParams = surfaceView.getLayoutParameters(); 
surfaceParams.setWidth(somewidthyouwant); 
surfaceParams.setHeight(someHeightYouWant); 
surfaceView.setLayoutParams(surfaceParams); 

的功能,這將設置你surfaceview到任何大小你想要它。

+0

不幸的是,getSupportedVideoSizes()返回null。這似乎是一個確認的Android錯誤。儘管在仿真器上報告了該錯誤,但我也在Kindle設備上獲得了空指針。 http://stackoverflow.com/questions/13932199/android-getsupportedvideosizes-returns-null-on-emulator – hubeir 2013-02-13 20:09:23

+0

@hubeir檢查我的編輯。 – Raigex 2013-02-13 21:34:32

+0

我使用以下代碼片段進行了驗證。 setPreviewSize(800,480)工作正常,但setPreviewSize(w,h)與我的OP中顯示的相同的錯誤崩潰。 \t大小mSize = mSizes.get(0); \t if(mSize!= null){//確保我們不拉取NullException。 \t \t params.setPreviewSize(800,480); //設置大小,因爲我們知道它。 \t \t //params.setPreviewSize(w,h); //設置大小,因爲我們知道它。 \t} \t mCamera.setParameters(params); //現在設置參數。 – hubeir 2013-02-13 22:12:08