【问题标题】:Android camera API app crashes at onResumeAndroid 相机 API 应用程序在 onResume 时崩溃
【发布时间】:2013-01-07 06:36:38
【问题描述】:

我正在使用相机 API 编写应用程序:显示预览并拍照。 第一个版本运行良好。 在类 Preview extends SurfaceView 中实现 SurfaceHolder.Callback

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.
    camera = Camera.open();
    try {
        camera.setPreviewDisplay(holder);
        camera.startPreview();

    } catch (IOException e) {
        e.printStackTrace();
    }

    hasSurface = true;
}


public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // It will be called immediately after surfaceCreated
    // I move it to Resume.
    setCameraPreviewParameters();

    camera.startPreview();

}

在主要活动中:

public class CameraDemo extends Activity

我还设置了一个成员: 相机单元用户界面; 它是:

public class CameraUnit extends LinearLayout

在onCreate中,

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ui = new CameraUnit(this);
    setContentView((View) ui); 

    Log.d(TAG, "onCreate'd");
}

它创建一个LinearLayout对象,其中包含surfaceView和一个相机按钮。

onResume 是:

    @Override
protected void onResume() {
    super.onResume();
}

虽然它有效,但我认为 onResume 不应该为空。我还看到 famous Android app example OCRTest 中的 surfaceCreated 和 surfaceChanged 是空的 所以我认为将surfaceCreated和surfaceChanged中的命令移动到onResume会更好也更可行。

我认为我的应用程序第一版的流程聊天应该是: 主要活动 onCreate(创建 LinearLayout 及其表面视图、相机按钮的位置), 调用surfaceCreated 和surfaceChanged, onResume。

所以我可以简单地将surfaceCreated 和surfaceChanged 中的命令移动到onResume。 但它不起作用! 我使用 Debug 发现表面为空。我认为没有调用surfaceCreatd。我的应用程序是不同的 OCRTest,它在主要活动中实现 SurfaceHolder.Callback。我在 SurfaceView 中实现 SurfaceHolder.Callback:

class Preview extends SurfaceView implements SurfaceHolder.Callback

所以我在 onResume 中添加了另外两行

        ui.preview.surfaceCreated(ui.preview.mHolder);
    ui.preview.surfaceChanged(ui.preview.mHolder, 0, 800, 400);

我随机设置最后三个整数参数。当我启动 Activity 时,会弹出 Android 手机中的错误窗口。 它说“引起:java.lang.RuntimeException:无法连接到相机服务”。 但是怎么解决???? 非常感谢!

错误是:

    01-07 00:27:57.173: W/dalvikvm(11625): threadid=1: thread exiting with uncaught exception (group=0x4001d5a0)
01-07 00:27:57.173: E/AndroidRuntime(11625): FATAL EXCEPTION: main
01-07 00:27:57.173: E/AndroidRuntime(11625): java.lang.RuntimeException: Unable to resume activity {com.example/com.example.CameraDemo}: java.lang.RuntimeException: Fail to connect to camera service
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2460)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2481)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1847)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.ActivityThread.access$1500(ActivityThread.java:132)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1038)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.os.Looper.loop(Looper.java:150)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.ActivityThread.main(ActivityThread.java:4263)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at java.lang.reflect.Method.invokeNative(Native Method)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at java.lang.reflect.Method.invoke(Method.java:507)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at dalvik.system.NativeStart.main(Native Method)
01-07 00:27:57.173: E/AndroidRuntime(11625): Caused by: java.lang.RuntimeException: Fail to connect to camera service
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.hardware.Camera.native_setup(Native Method)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.hardware.Camera.<init>(Camera.java:265)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.hardware.Camera.open(Camera.java:241)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at com.example.Preview.surfaceCreated(Preview.java:60)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at com.example.CameraDemo.onResume(CameraDemo.java:64)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1242)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.Activity.performResume(Activity.java:3904)
01-07 00:27:57.173: E/AndroidRuntime(11625):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2450)
01-07 00:27:57.173: E/AndroidRuntime(11625):    ... 12 more
01-07 00:27:59.455: I/Process(11625): Sending signal. PID: 11625 SIG: 9

【问题讨论】:

  • 感觉可能和Acitivity的onCreate、onResume的实现顺序以及surface的创建等有关。好像surfaceView类实现了SurfaceHolder.Callback,即使当surface没有准备好我们正处于 Activity 的 onResume 点。那我们什么时候准备好?如果Activity实现了SurfaceHolder.Callback,其内在顺序是什么?救命!!!!

标签: android android-camera


【解决方案1】:

你明白了

java.lang.RuntimeException: Fail to connect to camera service

例外,当相机被其他应用程序使用时。但我相信其他应用程序就是您的应用程序本身。你必须释放相机。

这些是你应该释放相机的情况:

在预览类中:

public void surfaceDestroyed(SurfaceHolder holder) {

    // empty. Take care of releasing the Camera preview in your activity.
    if (mCamera != null) {
        mCamera.release();
    }
}

在活动中:

@Override
public void onBackPressed() {
    super.onBackPressed();
    if (myCamera != null) {
        myCamera.release();
    }
    finish();
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    if (myCamera != null) {
        myCamera.release();
    }
}

点击取消时,以及当您完成使用相机时,即当图像被捕获并返回活动时。

也试试这个:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

    if (mHolder.getSurface() == null) {
        return;
    }

    try {
        mCamera.stopPreview();
    } catch (Exception e) {
        //You can ignore this, because this means the Preview doesn't Exist
        //So, no need to try stopping
    }

    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        //Catch this
    }
}

【讨论】:

  • 非常感谢。我在那些地方包含了这些相机释放功能。我的应用程序的第一个版本运行良好。正如我所说,我想将surfaceCreated 和surfaceChanged 中的命令移动到onResume。问题是第一次调用 onResume 不起作用。所以我想这可能与 onResume 和表面调用之间的关系有关。你的意见呢?
【解决方案2】:

所以我创建了一个使用相机但使用不同启动图标的应用程序来访问设置页面。 因此,每次我暂停并最小化应用程序以更改设置并返回时,它也会因此错误而崩溃。 因此,经过大量研究,我仍然没有答案。然后我意识到这与相机生命周期的管理有关。所以去看看生命周期,特别是Pausing。 所以我意识到,我们都在用错误的方法做这件事。我们在 onResume 上做的地方,我们应该在 onStart 上做。和砰!成功了。

这是我的应用程序代码。

@Override
    protected void onPause() {
        super.onPause();
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
        if (mPreview != null) {
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_viewer);
            preview.removeView(mPreview);
            mPreview = null;
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
        if (mPreview != null) {
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_viewer);
            preview.removeView(mPreview);
            mPreview = null;
        }
    }
    @Override
    protected void onResume() {
        super.onResume();

    }

    @Override
    protected void onStart(){
        super.onStart();
//Check if the camera exists or not so it does not clash with the onCreate
        if(mCamera == null){
            dir_string =  new File("/storage/sdcard1/app");
            Log.d("TAG",dir_string.toString());
            mCamera = getCameraInstance();
            mPreview = new CameraPreview(this, mCamera);
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_viewer);
            preview.addView(mPreview);
        }
    }

希望这至少对某人有所帮助。

【讨论】:

    【解决方案3】:

    我发现在一些示例中,相机打开代码既包含在 surfaceChanged 中,也包含在 onResume 中,使用 if 语句来避免重复。也许这是解决问题的一种方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多