【问题标题】:Android Camera2 API SecurityExceptionAndroid Camera2 API 安全异常
【发布时间】:2017-05-25 16:22:39
【问题描述】:

我正在尝试使用新的 Android camera2 api。我从本教程的源代码开始:http://jylee-world.blogspot.com/2014/12/a-tutorial-of-androidhardwarecamera2.html。当我尝试将它通过 USB 调试部署到任何手机时,我从 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)

【问题讨论】:

  • 您是否在 Android 6 上运行该应用程序?
  • @Alex 是的,我在 6.1 上运行它
  • 您申请过许可吗?如果您的应用程序目标 API 23,那么您需要请求许可。或者至少对于这个测试,如果你现在不想实现额外的东西,你需要去设置并授予权限。但你将不得不稍后
  • @Alex 谢谢,这看起来是个问题。这是我第一次使用 23 ...我想知道为什么其他权限似乎有效。
  • 现在有危险和非危险权限。你应该阅读它们。

标签: android camera android-permissions android-camera2


【解决方案1】:

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

检查权限:

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

如果app有权限,该方法返回PackageManager.PERMISSION_GRANTED,app可以继续操作。如果应用没有权限,该方法返回PERMISSION_DENIED,应用需要显式向用户请求权限。

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

【讨论】:

    【解决方案2】:

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

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

    安全异常将得到修复

    【讨论】:

    • 你能解释清楚吗?为什么用cameraDevice.close()关闭摄像头不会抛出安全异常?
    【解决方案3】:

    当您在 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

    这个库使权限处理变得容易

    【讨论】:

      【解决方案4】:

      断断续续地为此苦苦挣扎了好几个星期,几次想我已经解决了这个问题。最后,我在这里读到的所有“修复”都没有奏效。然后,在我的 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();
                  }
              });
          }
      }
      

      因此,虽然此语句中没有调用相机,但可能是因为线程安全,当我调用 showToast('some crap'); 时,Android 5.x 和 6.x 会引发安全错误

      将其注释掉并仅使用 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
                      }
                  });
      

      【讨论】:

        猜你喜欢
        • 2012-02-25
        • 1970-01-01
        • 2023-03-26
        • 2015-09-02
        • 1970-01-01
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 2014-07-04
        相关资源
        最近更新 更多