在Nexus One上使用Camera.setParameters()时出现RuntimeException

27

我从这里的答案复制了代码,但我在我的Nexus One上仍然遇到一个RuntimeException:setParameters failed错误。我的清单文件具有相机和wake_lock权限。这在模拟器上有效,在Droid上没有错误,但它确实存在旋转问题。

7个回答

41

您很可能请求了一个无效的预览尺寸。如果您检查adb logcat的结果,您可能会看到类似以下的内容:

E/QualcommCameraHardware(22732): Invalid preview size requested: 480x724
解决方案是请求与所需预览尺寸最接近的可用尺寸;您可以通过调用由Camera.getParameters返回的Camera.Parameters对象中的getSupportedPreviewSizes方法来获取可用的预览尺寸列表。

你说得没错,只是它试图将其设置为320x480,而480x320也可以工作。这让我想到了下一个问题,为什么SurfaceHolder.Callback.surfaceChanged()方法被调用时分辨率如此之低,甚至不匹配设备的纵横比? - Erik B
2
@Erik B -- 我知道这个回复对你的评论来说太晚了,但很可能是因为你的应用程序处于兼容模式,系统将你的应用程序中的像素视为实际设备分辨率的0.66倍。因此,480x800将被呈现为320x533,除非你的活动是全屏的,否则可能会在水平或垂直方向上删减一些像素以适应状态栏。 - Roman Nurik
在 API 版本 5 之前,你该怎么做?(比如说我想要兼容 Android 1.5) - uvgroovy
谢谢,伙计。现在需要找到一种动态地在多个设备上运行的方法。 :D - stackflow

26

我按照 Roman 所说的方法进行了更正,使用了以下代码:

   Camera.Parameters parameters = camera.getParameters();  
   List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();  
   Camera.Size cs = sizes.get(0);  
   parameters.setPreviewSize(cs.width, cs.height);  
   camera.setParameters(parameters);

10

说实话,我的问题源头在于我试图调用parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);之前没有先验证闪光模式是否受支持,需要检查 parameters.getFlashMode() != null

由于存在多种原因导致此异常文档不完整,因此请检查所有参数,而不仅仅是使用了supportedPreviewSize


1
如果(!getBaseContext()。getPackageManager()。hasSystemFeature( PackageManager.FEATURE_CAMERA_FLASH)){ // 设备上不可用闪光灯 } - Dhananjay M

3

以上方法都没有解决我的问题。但在设置参数之前添加以下代码可以解决。

// stop preview before making changes
    try {
        mCamera.stopPreview();
    } catch (Exception e){
        // ignore: tried to stop a non-existent preview
    }

//now set your parameters

2

对我来说,这种情况发生在我拍照后预览界面会卡住,直到我更新了参数设置为以下内容。在遇到此错误时,始终重要的是确保您检查相机要求设置的所有参数,以确保您要求相机设置自身的每个参数都对相机可行。

Camera.Parameters parameters = myCamera.getParameters();

预览大小为:

if (myCamera.getParameters().getSupportedPreviewSizes() != null){
     Camera.Size previewSize = getOptimalPreviewSize(myCamera.getParameters().getSupportedPreviewSizes(), width, height);;
     parameters.setPreviewSize(previewSize.width, previewSize.height);
}

使用闪光灯/对焦模式:

if(parameters.getSupportedFocusModes() != null && parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)){
     parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}

if (parameters.getSupportedFlashModes() != null && parameters.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_AUTO)){
    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);

}

myCamera.setParameters(parameters);

等等,所有这些都包含在一个很好的try{}catch(){}中运行得很好。祝你好运。

这里是从这篇优秀教程中获取OptimalPreview Size的方法:

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height)
    {
        // Source: https://dev59.com/m-o6XIcBkEYKwwoYSCc1
        Camera.Size optimalSize = null;

        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) height / width;

        // Try to find a size match which suits the whole screen minus the menu on the left.
        for (Camera.Size size : sizes){

            if (size.height != width) continue;
            double ratio = (double) size.width / size.height;
            if (ratio <= targetRatio + ASPECT_TOLERANCE && ratio >= targetRatio - ASPECT_TOLERANCE){
                optimalSize = size;
            }
        }

        // If we cannot find the one that matches the aspect ratio, ignore the requirement.
        if (optimalSize == null) {
            // TODO : Backup in case we don't get a size.
        }

        return optimalSize;
    }

0

Sam的解决方案是正确的,但在一些平板设备上输出图像仍然有点缩放。我在互联网上找到的最佳实践之一是,在Camera主机中设置属性,以便每次恢复相机时都可以重用这些属性。以下是在CameraHost中实现的方法:

@Override
        public Parameters adjustPreviewParameters(Parameters parameters) {
            List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
            Camera.Size cs = sizes.get(0);
            parameters.setPreviewSize(cs.width, cs.height);
            return super.adjustPreviewParameters(parameters);
        }

0
一些开源相机项目,如opencamera,总是使用try-catch来调用Camera.setParameters:
private void setCameraParameters(Camera.Parameters parameters) {
    if( MyDebug.LOG )
        Log.d(TAG, "setCameraParameters");
    try {
        camera.setParameters(parameters);
        if( MyDebug.LOG )
            Log.d(TAG, "done");
    } catch (RuntimeException e) {
        // just in case something has gone wrong
        if( MyDebug.LOG )
            Log.d(TAG, "failed to set parameters");
        e.printStackTrace();
        count_camera_parameters_exception++;
    }
}

此外,在调用setParameters之前,始终获取最新的getParameters,如下所示:

void setRotation(int rotation) {
    Camera.Parameters parameters = this.getParameters();
    parameters.setRotation(rotation);
    setCameraParameters(parameters);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接