Android Camera2 API SecurityException

时间:2016-05-23 18:07:38

标签: android camera android-permissions android-camera2

我试图使用新的Android camera2 api。我从本教程的源代码开始:http://jylee-world.blogspot.com/2014/12/a-tutorial-of-androidhardwarecamera2.html。当我尝试将usb-debug-deploy部署到任何手机时,我从CameraManager.openCamera(...)获得了一个SecurityException。

我的AndroidManifest看起来像这样:

<uses-feature android:name="com.android.hardware.camera2.full"/>
<uses-permission android:name="android.permission.CAMERA"/>

这似乎是我能找到的每个教程都能做到的。我可以获得其他行动的许可;例如,我可以让相机振动得很好。我也可以使用CameraManager.getCameraIdLists()枚举相机,但我不确定这是否真的需要许可。但我不能openCamera

我需要一些额外的权限吗?我做错了吗?

感谢您的帮助!

这是我的完整堆栈跟踪:

SecurityException
java.lang.SecurityException: Lacking privileges to access camera serviceat android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:108)
        at android.hardware.camera2.legacy.CameraDeviceUserShim.connectBinderShim(CameraDeviceUserShim.java:336)
        at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:327)
        at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:457)
        at com.example.quinnfreedman.camera2test.MainActivity$1.onSurfaceTextureAvailable(MainActivity.java:74)
        at android.view.TextureView.getHardwareLayer(TextureView.java:368)
        at android.view.View.updateDisplayListIfDirty(View.java:15167)
        at android.view.View.draw(View.java:15964)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3612)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3402)
        at android.view.View.updateDisplayListIfDirty(View.java:15185)
        at android.view.View.draw(View.java:15964)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3612)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3402)
        at android.view.View.updateDisplayListIfDirty(View.java:15185)
        at android.view.View.draw(View.java:15964)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3612)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3402)
        at android.view.View.updateDisplayListIfDirty(View.java:15185)
        at android.view.View.draw(View.java:15964)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3612)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3402)
        at android.view.View.draw(View.java:16197)
        at com.android.internal.policy.PhoneWindow$DecorView.draw(PhoneWindow.java:2690)
        at android.view.View.updateDisplayListIfDirty(View.java:15190)
        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2627)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2446)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2079)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1119)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6060)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
        at android.view.Choreographer.doCallbacks(Choreographer.java:670)
        at android.view.Choreographer.doFrame(Choreographer.java:606)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
        at android.os.Handler.handleCallback(Handler.java:746)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5443)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

4 个答案:

答案 0 :(得分:3)

在Android M中,危险权限需要运行时权限检查。您可以看到危险权限here

检查权限:

// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.CAMERA);

如果应用具有权限,则该方法返回PackageManager.PERMISSION_GRANTED,应用可以继续操作。如果应用程序没有权限,则该方法返回PERMISSION_DENIED,应用程序必须明确要求用户许可。

详细信息:https://developer.android.com/training/permissions/requesting.html#perm-request

答案 1 :(得分:1)

只需在onSurfaceTextureDestroyed函数中关闭相机设备

即可
 onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture){cameraDevice.close();cameraDevice = null;}

安全例外将得到修复

答案 2 :(得分:0)

当您在android 6+上运行应用程序时,您需要提供着名的运行时权限。 https://developer.android.com/training/permissions/requesting.html

您尝试提供的权限被视为危险权限android。 https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous

关于运行时权限的其他响应不同,我建议您使用此https://github.com/Karumi/Dexter

此lib可轻松处理权限

答案 3 :(得分:0)

挣扎了几个星期,几次思考我已经解决了这个问题。最后,我在这里读到的所有“修复”都没有奏效。然后,在我的Java中输入~100个Log.v语句后,我意识到这是一个线程问题,可能会或可能不会根据摄像头上的事件启动此错误。基本上,我认为,主程序是在主线程上运行的,但是有一个额外的线程被以下语句启动:

//this code seems to be the culprit  ... commenting it out solve my problem
private void showToast(final String text) {
    final Activity activity = MyStupidProgram.this;
    if (activity != null) {
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(activity, text, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

所以虽然这句话中没有任何内容可以调用相机,也许是因为线程安全,Android 5.x和6.x在我调用showToast('some crap')时会出现安全错误;

评论出来并只使用Toast.makeText('blah blah');声明,我能够摆脱安全错误。

此外,我将此添加到页面上的代码onCreate();声明,以捕获主线程上的任何问题:

    Thread.setDefaultUncaughtExceptionHandler(
            new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(
                        Thread paramThread,
                        Throwable paramThrowable
                ) {
                    //Do your own error handling here

                    if (exceptionHandler != null)
                        exceptionHandler.uncaughtException(
                                paramThread,
                                paramThrowable
                        ); //Delegates to Android's error handling
                    else
                        System.exit(2); //Prevents the service/app from freezing
                }
            });