【问题标题】:Android camera locked after force closeAndroid相机在强制关闭后锁定
【发布时间】:2013-06-23 12:10:57
【问题描述】:

我有一个使用设备相机的应用程序。

现在我只在正常流程中释放相机。

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    if(camera != null) {
        camera.stopPreview();
        camera.release();
    } 
} 

因此,应用程序以意想不到的方式退出相机模式 - 即强制关闭(由于OutOfMemoryError) - 相机被锁定。释放它的唯一方法是重启设备。

申请开始后,我得到: RuntimeException: Fail to connect to camera service

我怎么能确定,无论如何,那台相机已经被释放了?

【问题讨论】:

  • 您是否尝试卸载您的应用程序?如果我没记错的话,这在过去对我有帮助。
  • 这不是我问的。我需要确保在任何情况下都释放Camera。无需卸载应用程序或重新启动设备。
  • 我猜你需要使用Thread.setDefaultUncaughtExceptionHandler() 来安排对此类崩溃的控制,以便能够关闭相机。
  • 是的,就可以了。或者,如果您正在使用 Bugsense - 让您的活动实现 com.bugsense.trace.ExceptionCallback 并在 lastBreath() 中释放相机

标签: android android-camera


【解决方案1】:

由于保留部分代码以便您以后找到它的最佳方法是将其发布在“网络”中,

private UnexpectedTerminationHelper mUnexpectedTerminationHelper = new UnexpectedTerminationHelper();
private class UnexpectedTerminationHelper {
    private Thread mThread;
    private Thread.UncaughtExceptionHandler mOldUncaughtExceptionHandler = null;
    private Thread.UncaughtExceptionHandler mUncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread thread, Throwable ex) { // gets called on the same (main) thread
            XXXX.closeCamera(); // TODO: write appropriate code here
            if(mOldUncaughtExceptionHandler != null) {
                // it displays the "force close" dialog
                mOldUncaughtExceptionHandler.uncaughtException(thread, ex);
            }
        }
    };
    void init() {
        mThread = Thread.currentThread();
        mOldUncaughtExceptionHandler = mThread.getUncaughtExceptionHandler();
        mThread.setUncaughtExceptionHandler(mUncaughtExceptionHandler);
    }
    void fini() {
        mThread.setUncaughtExceptionHandler(mOldUncaughtExceptionHandler);
        mOldUncaughtExceptionHandler = null;
        mThread = null;
    }
}

并且,在主线程的适当位置:

    mUnexpectedTerminationHelper.init();

    mUnexpectedTerminationHelper.fini();

【讨论】:

  • 这是所有必要的代码吗?我将在哪里运行代码来关闭相机?为什么在未捕获异常处理程序代码本身中没有呢?您有更多相关信息的链接吗?
  • @msj121 OOP 是关于职责分离的。这个助手负责对未捕获的异常做出反应。另一个助手应该负责相机的东西(你看到XXXX.closeCamera(); 行)。在一个 Activity 的最简单情况下,您将 XXXX.openCamera()mUnexpectedTerminationHelper.init(); 放在 onResume() 中,并将结束的东西放在 onPause() 中。请注意,您从帮助程序和 onPause() 都调用了XXXX.closeCamera();。现实世界的应用程序通常比仅一个 Activity 更复杂,并且包含一些难以解释的内容。
  • 对不起,我错过了近距离相机的线路。谢谢
【解决方案2】:

正如@CommonsWare 建议的那样,如果您想确保您的应用程序在崩溃之前释放相机,您应该使用Thread.setDefaultUncaughtExceptionHandler()

或者,如果您使用的是 Bugsense:

private class MyCameraActivity extends Activity implements SurfaceHolder.Callback, ExceptionCallback {

    @Override
    protected void onCreate(Bundle sSavedInstanceState) {
        super.onCreate(sSavedInstanceState);

        BugSenseHandler.setExceptionCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        this.camera = open();

        try {
            camera.setPreviewDisplay(holder);
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }

        // other camera stuff
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        releaseCamera();
    }

    @Override
    public void lastBreath() {
        releaseCamera();
    }

    private void releaseCamera() {
        if (camera != null) {
            camera.stopPreview();
            camera.release();
        }
    }
} 

【讨论】:

    【解决方案3】:

    内存不足错误是因为您尝试保存的图像超出限制,通常在您尝试处理位图时出现。

    您可以尝试这些方法来避免相机无法释放。

    相机我的相机;

    在发生错误的地方使用日志和查找 添加 try catch 块并在 catch 块中添加 myCamera.stopPreview();myCamera.release(); 同时覆盖 ondestroy 和 onpause 方法和add myCamera.stopPreview();myCamera.release();

    希望这对您有所帮助或至少给了您一个想法。

    【讨论】:

    • 我正在使用日志记录来确定OutOfMemoryError 发生的位置,但问题仍然存在——用户不应该因为我的错误而受苦。从长远来看,我会处理所有错误,但即使应用程序崩溃,我也想释放相机。
    【解决方案4】:
    private void stopPreviewAndFreeCamera() {
    
    if (mCamera != null) {
        /*
          Call stopPreview() to stop updating the preview surface.
        */
        mCamera.stopPreview();
    
        /*
          Important: Call release() to release the camera for use by other applications. 
          Applications should release the camera immediately in onPause() (and re-open() it in
          onResume()).
        */
        mCamera.release();
    
        mCamera = null;
    }}
    

    这样做。

    【讨论】:

    • 我猜你没有把它放在你的代码中,即 mCamera = null;
    • 移除对对象的引用并不意味着该相机已被释放。
    • @MartynasJurkus 让你的相机变量为空。就像我一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    相关资源
    最近更新 更多