无法连接到相机服务

13

我已将我的相机设置为this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);,它能正常工作,但是如果我将其更改为PORTRAIT而不是LANDSCAPE,那么它会崩溃并出现以下错误...

07-30 12:51:37.655: ERROR/AndroidRuntime(22069): FATAL EXCEPTION: main
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): java.lang.RuntimeException: Fail to connect to camera service
07-30 12:51:37.655: ERROR/AndroidRuntime(22069):     at android.hardware.Camera.native_setup(Native Method)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069):     at android.hardware.Camera.<init>(Camera.java:110)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069):     at android.hardware.Camera.open(Camera.java:90)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069):     at org.digital.com.CamLayer.surfaceCreated(CamLayer.java:3

它崩溃的方法是...

public void surfaceCreated(SurfaceHolder holder) {
    synchronized(this) {
        mCamera = Camera.open();

        Camera.Parameters p = mCamera.getParameters(); 
        p.setPreviewSize(800, 480);
        mCamera.setParameters(p);

        try {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException e) {
            Log.e("Camera", "mCamera.setPreviewDisplay(holder);");
        }

        mCamera.startPreview();
        mCamera.setPreviewCallback(this);
    }
}

当执行 mCamera = Camera.open(); 时,程序崩溃。

我的清单文件中已经添加了<uses-permission android:name="android.permission.CAMERA"></uses-permission>

如何修复这个问题,以便我可以在竖屏模式下查看我的应用程序?


1
你正在使用哪个设备和哪个SDK版本?据我所知,相机预览只能在横屏模式下正常工作,但在竖屏模式下无法正常工作。我也想在竖屏模式下使用它(在N1上,在三星Galaxy S上),但没有成功。请参见http://code.google.com/p/android/issues/detail?id=1193的错误跟踪器;尽管我从未遇到过像你上面提到的那样的错误。 - Mathias Conradt
你有别的设备来测试吗?在模拟器上可以运行吗?如果是一个小的apk,我可以帮你在我的N1和Galaxy S上测试。你的2.2是最终的2.2 FRF91吗? - Mathias Conradt
我在同一行遇到了同样的问题。异常并不总是发生,但有时会发生。有人能解释一下为什么它有时会崩溃而不总是吗……?我正在使用三星GT-S5360。 - picaso
Skizit,您能否帮我解决有关 http://stackoverflow.com/questions/26714771/android-camera-take-picture-failed-issue 的问题? - koutuk
8个回答

24

平台中存在一些并发问题:http://code.google.com/p/android/issues/detail?id=6201

解决方法是在释放相机之前清除回调函数,我建议使用以下清理代码:

    @Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if (mCam != null) {
        mCam.stopPreview();
        mCam.setPreviewCallback(null);
        mCam.release();
        mCam = null;
    }
}

Kangur,你能否帮我解决关于http://stackoverflow.com/questions/26714771/android-camera-take-picture-failed-issue的问题? - koutuk
抱歉,我已经三年没有做安卓开发了...现在它的工作原理我一点都不清楚 :) - Kangur

16

以下是我在我的应用程序中使用的SurfaceHolderCallBack内部类,它在Nexus One 2.2的纵向模式下工作正常 - 希望能帮到你。

编辑: "工作正常" = "没有崩溃"。尽管我还没有弄清楚如何正确旋转预览图像(请参见上面的第一条评论)。这就是为什么我实际上不得不使用横向和“转换”围绕预览表面的UI元素进入横向模式。 据我所知,仅在横向模式下才能使用带有正确旋转预览图像的预览。我尝试过的旋转和方向参数根本没有帮助。

class SurfaceHolderCallback implements SurfaceHolder.Callback {
    private static final int IMAGE_WIDTH = 512;
    private static final int IMAGE_HEIGHT = 384;
    private static final String ORIENTATION = "orientation";
    private static final String ROTATION = "rotation";
    private static final String PORTRAIT = "portrait";
    private static final String LANDSCAPE = "landscape";

    public void surfaceCreated(SurfaceHolder holder) {
        try {
            // This case can actually happen if the user opens and closes the camera too frequently.
            // The problem is that we cannot really prevent this from happening as the user can easily
            // get into a chain of activites and tries to escape using the back button.
            // The most sensible solution would be to quit the entire EPostcard flow once the picture is sent.
            camera = Camera.open();
        } catch(Exception e) {
            finish();
            return;
        }

        //Surface.setOrientation(Display.DEFAULT_DISPLAY,Surface.ROTATION_90);
        Parameters p = camera.getParameters();
        p.setPictureSize(IMAGE_WIDTH, IMAGE_HEIGHT);

        camera.getParameters().setRotation(90);

        Camera.Size s = p.getSupportedPreviewSizes().get(0);
        p.setPreviewSize( s.width, s.height );

        p.setPictureFormat(PixelFormat.JPEG);
        p.set("flash-mode", "auto");
        camera.setParameters(p);

        try {
            camera.setPreviewDisplay(surfaceHolder);
        } catch (Throwable ignored) {
            Log.e(APP, "set preview error.", ignored);
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
        if (isPreviewRunning) {
            camera.stopPreview();
        }
        try {
            camera.startPreview();
        } catch(Exception e) {
            Log.d(APP, "Cannot start preview", e);    
        }
        isPreviewRunning = true;
    }

    public void surfaceDestroyed(SurfaceHolder arg0) {
        if(isPreviewRunning && camera != null) {
            if(camera!=null) {
                camera.stopPreview();
                camera.release();  
                camera = null;
            }
            isPreviewRunning = false;
        }
    }
}

Mathias Lin,你能帮我解决关于http://stackoverflow.com/questions/26714771/android-camera-take-picture-failed-issue的问题吗? - koutuk
你在哪里实现了finish方法(在catch块中),它是用来做什么的? - emin deniz

13

你在 AndroidManifest.xml 文件中设置了这个吗?

uses-permission android:name="android.permission.CAMERA"

2
谢谢您发布这篇文章,即使它很明显,对于一些寻找此类信息的人(比如我),这是一个有用的提示。 - Dimitris
Romain Hippeau...您能帮我解决关于http://stackoverflow.com/questions/26714771/android-camera-take-picture-failed-issue的问题吗? - koutuk

2

使用以下方法代替:

<uses-permission
    android:name="android.permission.FLASHLIGHT"/>

尝试使用以下方法:

<uses-permission
    android:name="android.permission.FLASHLIGHT"
    android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
    android:protectionLevel="normal" />

不要忘记添加相机权限:
<uses-permission android:name="android.permission.CAMERA" />

似乎对我的Nexus 7(Android 5.0)有所帮助。额外的“group”和“level”行是什么意思? - Violet Giraffe

1
如果您正在使用Android模拟器,另一个可能性是在Android虚拟设备设置中,前置和后置摄像头被定义为“无”。

0

我认为你的问题在于当你旋转相机时,它没有被正确或完全释放。如果你从横屏切换到竖屏,那么Intent会再次启动。如果此时相机没有被释放和重新打开,你就会尝试打开已经打开的相机,这会引发错误。


0

这可能会起作用...

   @Override public void surfaceDestroyed(SurfaceHolder holder) {
    Log.d("surfaceDestroyed", "");
    cameraSource.stop();   //check if you have this line
  }

-1

我看到你将预览区域设置为800 x 480。在纵向模式下,这个尺寸是无效的,可能是API中存在bug导致崩溃。

尝试将预览区域设置为200x200。


1
我在上面的代码示例中尝试了800x480的预览大小,在Nexus One 2.2上运行得很好。实际上,当调用p.getSupportedPreviewSizes().get(0)时,800x480是您在N1上获得的默认大小,因此它是一个正确的预览大小。 - Mathias Conradt
是的,这并没有解决任何问题。它破坏了我的设置参数。 - Skizit
1
你需要找到最佳的预览尺寸,获取所有尺寸并进行比较,然后选择最大的一个即可。这样就可以正常工作了。 - Toshe
the100rabh...你能帮我解决关于http://stackoverflow.com/questions/26714771/android-camera-take-picture-failed-issue的问题吗? - koutuk

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