没有权限访问相机服务并获得许可

Posted

技术标签:

【中文标题】没有权限访问相机服务并获得许可【英文标题】:Lacking privileges to access camera service with permission granted 【发布时间】:2017-04-18 00:33:56 【问题描述】:

我正在尝试使用 Google 示例在我的应用中添加相机 2 API。我的应用程序有权使用相机,旧 API 可以正常工作。在执行 android 引发异常的代码之前,我已经检查了不止一个权限,但我仍然获得了访问相机服务的权限。

private void createCameraPreviewSession() 
    try
        SurfaceTexture texture = mTextureView.getSurfaceTexture();
        //assert texture != null;

        Log.d(TAG,String.format("Textureview is null: %b, texture is null: %b",mTextureView==null, texture==null));
        // We configure the size of default buffer to be the size of camera preview we want.
        texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());

        // This is the output Surface we need to start preview.
        Surface surface = new Surface(texture);

        // We set up a CaptureRequest.Builder with the output Surface.

        if (ActivityCompat.checkSelfPermission(a, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) 
            Log.d(TAG, "Permission granted");
            mPreviewRequestBuilder= mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            Log.d(TAG, "Capture request created");
        
        else
            return ;
        

        mPreviewRequestBuilder.addTarget(surface);

        // Here, we create a CameraCaptureSession for camera preview.

        mCameraDevice.createCaptureSession(Arrays.asList(surface),
            new CameraCaptureSession.StateCallback() 

                @Override
                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) 
                    // The camera is already closed
                    if (null == mCameraDevice) 
                        return;
                    

                    // When the session is ready, we start displaying the preview.
                    mCaptureSession = cameraCaptureSession;
                    try 
                        // Auto focus should be continuous for camera preview.
                        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                                CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

                        // Finally, we start displaying the camera preview.
                        mPreviewRequest = mPreviewRequestBuilder.build();
                        mCaptureSession.setRepeatingRequest(mPreviewRequest, null, null);
                     catch (CameraAccessException e) 
                        e.printStackTrace();
                    
                

                @Override
                public void onConfigureFailed(
                        @NonNull CameraCaptureSession cameraCaptureSession) 
                    Toast.makeText(a,a.getString(R.string.error_configuring_camera),Toast.LENGTH_LONG).show();
                
            , null);
     catch (CameraAccessException e) 
        e.printStackTrace();
    

这是日志:

12-02 20:30:07.427 697-697/kiam.cameraintentpractice.pendant D/ICAMERA2: Textureview is null: false, texture is null: false
12-02 20:30:07.428 697-697/kiam.cameraintentpractice.pendant D/ICAMERA2: Permission granted
12-02 20:30:07.429 697-697/kiam.cameraintentpractice.pendant D/AndroidRuntime: Shutting down VM
12-02 20:30:07.430 697-697/kiam.cameraintentpractice.pendant E/AndroidRuntime: FATAL EXCEPTION: main
   Process: kiam.cameraintentpractice.pendant, PID: 697
   java.lang.SecurityException: Lacking privileges to access camera service
       at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:108)
       at android.hardware.camera2.utils.CameraBinderDecorator$CameraBinderDecoratorListener.onAfterInvocation(CameraBinderDecorator.java:73)
       at android.hardware.camera2.utils.Decorator.invoke(Decorator.java:81)
       at java.lang.reflect.Proxy.invoke(Proxy.java:393)
       at $Proxy2.createDefaultRequest(Unknown Source)
       at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureRequest(CameraDeviceImpl.java:636)
       at kiam.cameraintentpractice.model.CameraV2.createCameraPreviewSession(CameraV2.java:377)
       at kiam.cameraintentpractice.model.CameraV2.access$400(CameraV2.java:55)
       at kiam.cameraintentpractice.model.CameraV2$2.onOpened(CameraV2.java:340)
       at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:134)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:5525)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
12-02 20:30:08.752 697-797/kiam.cameraintentpractice.pendant D/TaskManager: Error processing queue - Call: 3

代码在这里被称为表单:

private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() 

    @Override
    public void onOpened(@NonNull CameraDevice cameraDevice) 
        // This method is called when the camera is opened.  We start camera preview here.
        mCameraOpenCloseLock.release();
        mCameraDevice = cameraDevice;
        createCameraPreviewSession();
    

    @Override
    public void onDisconnected(@NonNull CameraDevice cameraDevice) 
        mCameraOpenCloseLock.release();
        cameraDevice.close();
        mCameraDevice = null;
    

    @Override
    public void onError(@NonNull CameraDevice cameraDevice, int error) 
        mCameraOpenCloseLock.release();
        cameraDevice.close();
        mCameraDevice = null;
        Toast.makeText(a, a.getString(R.string.error_using_camera), Toast.LENGTH_SHORT).show();
        a.finish();
    
;

这里的回调继续表单:

private void openCamera(int width, int height) 

    if (ContextCompat.checkSelfPermission(a, Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) 
        Log.d(TAG, "Permission denied");
        return;
    
    setUpCameraOutputs(width, height);
    configureTransform(width, height);

    try 
        /*if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) 
            throw new RuntimeException("Time out waiting to lock camera opening.");
        */
        if (ActivityCompat.checkSelfPermission(a, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) 
            Log.d(TAG, "Permission accepted");
            CameraManager manager = (CameraManager) a.getSystemService(Context.CAMERA_SERVICE);
            manager.openCamera(mCameraId, mStateCallback, null);
        
        else
            Log.d(TAG, "Permission denied");
            return;
        

     catch (CameraAccessException e) 
        e.printStackTrace();
     /*catch (InterruptedException e) 
        throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
    */

编辑 - 按要求发布清单

    <?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-feature
    android:name="android.hardware.camera"
    android:required="false" />
<uses-feature
    android:name="android.hardware.camera.front"
    android:required="false" />
<uses-feature
    android:name="android.hardware.camera.autofocus"
    android:required="false" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:screenOrientation="reversePortrait"
    android:hardwareAccelerated="true">
    <activity
        android:name=".UI.ImageAcquisition"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:screenOrientation="reversePortrait"
    />
    <activity
        android:name=".UI.ImageManipulation"
        android:label="@string/title_activity_image_manuplation"
        android:launchMode="singleTop"
        android:screenOrientation="reversePortrait"
        android:theme="@style/AppTheme" />
    <activity
        android:name=".UI.ProjectsActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:screenOrientation="reversePortrait">
        <intent-filter android:label="@string/app_name">
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".UI.IndividualProjectDetailActivity"
        android:label="@string/title_activity_individual_project_detail"
        android:parentActivityName=".UI.ProjectsActivity"
        android:theme="@style/AppTheme"
        android:screenOrientation="reversePortrait">

        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="kiam.cameraintentpractice.UI.ProjectsActivity" />
    </activity>

    <service
        android:name=".model.CalculatorService"
        android:enabled="true"
        android:exported="true"></service>
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
</application>

【问题讨论】:

请发布您的清单。 【参考方案1】:

不要延迟打开相机。只需在 SurfaceTextureListener 的 onSurfaceTextureDestroyed() 方法中 closeCamera() 即可。

【讨论】:

【参考方案2】:

我在三星 Galaxy S7 等设备上遇到了同样的问题。我通过在打开相机之前添加延迟来解决它,如下所示:

TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() 
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) 
        mSurfaceTextureAvailable = true;
        if (ContextCompat.checkSelfPermission(CameraActivity.this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) 
            ActivityCompat.requestPermissions(CameraActivity.this, new String[]Manifest.permission.CAMERA, REQUEST_CAMERA_PERMISSION);
            return;
        else 
            mPermissionsGranted = true;

            // Execute some code after 500 milliseconds have passed
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() 
                @Override
                public void run() 
                    setupCameraIfPossible();
                
            , 500);


        

    
...

这是我打开相机的方法:

 private void setupCameraIfPossible() 
    if (mSurfaceTextureAvailable && mPermissionsGranted) 
        openCamera();
    
 

希望对你有帮助

【讨论】:

以上是关于没有权限访问相机服务并获得许可的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 6.0 中缺乏访问相机服务的权限

Appcelerator 中的相机权限

文件共享后没有访问权限是怎么回事?

如何在android中获得相机的权限。(特别是棉花糖)

世博会缺少相机胶卷权限

WCF 休息服务 - 获得对 HTTP 响应标头的访问权限