2013-02-13 74 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