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

Posted

技术标签:

【中文标题】在 Android 6.0 中缺乏访问相机服务的权限【英文标题】:Lacking privileges to access camera service in Android 6.0 【发布时间】:2017-03-14 05:11:48 【问题描述】:

我在 android 6.0 中使用 Camera2API。我在 Android 5.0 中没有出错。但是,当我在 Android 6.0 中使用我的代码时,我遇到了一个问题。问题是有时我可以成功打开相机并拍照。但是,有时相机无法打开并且出现错误

java.lang.SecurityException: Lacking privileges to access camera service
    at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:108)

我添加运行时权限如下:

String[] PERMISSIONS = Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    if(!hasAllPermissions(this, PERMISSIONS))
        ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
    


public static boolean hasAllPermissions(Context context, String... permissions) 
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) 
        for (String permission : permissions) 
            if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) 
                return false;
            
        
    
    return true;

这是所有日志

FATAL EXCEPTION: main
Process: com.example.camera2api, PID: 5376
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.cancelRequest(Unknown Source)
at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:926)
at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:378)
at android.hardware.camera2.impl.CameraCaptureSessionImpl$2.onDisconnected(CameraCaptureSessionImpl.java:514)
at android.hardware.camera2.impl.CameraDeviceImpl$7.run(CameraDeviceImpl.java:228)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

更新:对于想要查看我的完整代码的人。我在这里上传我的完整代码

公共类 AndroidCamera 扩展 AppCompatActivity

private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

static 
    ORIENTATIONS.append(Surface.ROTATION_0, 90);
    ORIENTATIONS.append(Surface.ROTATION_90, 0);
    ORIENTATIONS.append(Surface.ROTATION_180, 270);
    ORIENTATIONS.append(Surface.ROTATION_270, 180);


private static final String TAG = "Camera2App";
private String mImageFileLocation = "";
private static final int STATE_PREVIEW = 0;
private static final int STATE_WAIT_LOCK = 1;
private static final int STATE_WAITING_PRECAPTURE = 2;
/**
 * Camera state: Waiting for the exposure state to be something other than precapture.
 */
private static final int STATE_WAITING_NON_PRECAPTURE = 3;

/**
 * Camera state: Picture was taken.
 */
private static final int STATE_PICTURE_TAKEN = 4;
private int mState;
private TextureView mTextureView;
private Size mPreviewSize;

private String mCameraId;
String[] PERMISSIONS = Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA;
private static final int PERMISSION_ALL = 105;
private  static final int REQUEST_CAMERA_RESULT = 106;
private boolean isRegistred=false;
private int mSensorOrientation;
private TextureView.SurfaceTextureListener mSurfaceTextureListener =
        new TextureView.SurfaceTextureListener() 
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) 
                if (!TextUtils.isEmpty(BleUtils.getCameraLens(AndroidCamera.this)))
                    setupCamera(width, height,BleUtils.getCameraLens(AndroidCamera.this));
                else
                    setupCamera(width, height,"1");
                openCamera();

            

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) 

            

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) 
                //closeCamera();

                return false;
            

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) 

            
        ;
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
private CameraDevice mCameraDevice;
private CameraDevice.StateCallback mCameraDeviceStateCallback =
        new CameraDevice.StateCallback() 
            @Override
            public void onOpened(CameraDevice camera) 
                mCameraOpenCloseLock.release();
                mCameraDevice = camera;
                //Toast.makeText(getApplicationContext(),"Camera Opened!", Toast.LENGTH_SHORT).show();
                createCameraPreviewSession();
            

            @Override
            public void onDisconnected(CameraDevice camera) 
                camera.close();
                mCameraDevice = null;

            

            @Override
            public void onError(CameraDevice camera, int error) 
                camera.close();
                mCameraDevice = null;

            
        ;
private CaptureRequest mPreviewCaptureRequest;
private CaptureRequest.Builder mPreviewCaptureRequestBuilder;
private CameraCaptureSession mCameraCaptureSession;
private CameraCaptureSession.CaptureCallback mSessionCaptureCallback
        = new CameraCaptureSession.CaptureCallback() 

    private void process(CaptureResult result)

        switch (mState)
            case STATE_PREVIEW:
                break;
            case STATE_WAIT_LOCK:
                Integer afState=result.get(CaptureResult.CONTROL_AF_STATE);
                if(afState==CaptureRequest.CONTROL_AF_STATE_FOCUSED_LOCKED)
                    captureStillImage();
                
                else
                    captureStillImage();
                

                break;
        


    

    @Override
    public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) 
        super.onCaptureStarted(session, request, timestamp, frameNumber);
    

    @Override
    public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) 
        super.onCaptureCompleted(session, request, result);

        process(result);
    

    @Override
    public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) 
        super.onCaptureFailed(session, request, failure);
        Handler mHandler = new Handler(getMainLooper());
        mHandler.post(new Runnable() 
            @Override
            public void run() 
                Toast.makeText(getApplicationContext(), "Focus Lock UnSuccesful", Toast.LENGTH_SHORT).show();
            
        );

    
;

private HandlerThread mBackgroundThread;
private Handler mBackgroundHandler;
private static File mImageFile;
private ImageReader mImageReader;
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener =
        new ImageReader.OnImageAvailableListener() 
            @Override
            public void onImageAvailable(ImageReader reader) 

                mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage()));
            
        ;

private static class ImageSaver implements Runnable 


    private final Image mImage;

    private ImageSaver(Image image) 
        mImage = image;
    

    @Override
    public void run() 

        ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);

        FileOutputStream fileOutputStream = null;

        try 

            fileOutputStream = new FileOutputStream(mImageFile);
            fileOutputStream.write(bytes);

         catch (IOException e) 
            e.printStackTrace();
         finally 

            mImage.close();
            if (fileOutputStream != null) 
                try 
                    fileOutputStream.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            

        

    


@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.camera_activity);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        if(!hasAllPermissions(this, PERMISSIONS))
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        
    




    mTextureView = (TextureView) findViewById(R.id.texture);

public static boolean hasAllPermissions(Context context, String... permissions) 
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) 
        for (String permission : permissions) 
            if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) 
                return false;
            
        
    
    return true;

@Override
public void onStart() 
    super.onStart();
    if (!EventBus.getDefault().isRegistered(this)) 
        EventBus.getDefault().register(this);
    

//onStop
@Override
public void onStop() 
    super.onStop();
    EventBus.getDefault().unregister(this);



@Subscribe
public void onCaptureNumberReceived(OnCaptureEvent event) 
    //get the phone number value here and do something with it
    String capturecode = event.getCodeCapture();
    Log.d(TAG, capturecode);
    if (capturecode.equals("capture")) 
        try 
            mImageFile = createImageFile();

         catch (IOException e) 
            e.printStackTrace();
        

        lockFocus();
        MediaActionSound sound = new MediaActionSound();
        sound.play(MediaActionSound.SHUTTER_CLICK);
    
    else if(capturecode.equals("end_capture")) 
        finish(); // call this to finish the current activity
        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
        homeIntent.addCategory( Intent.CATEGORY_HOME );
        homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(homeIntent);
    



public void takepicture(View view) 

    try 
        mImageFile = createImageFile();
        Log.d("TAG","=====Take picture=====");

     catch (IOException e) 
        e.printStackTrace();
    

    lockFocus();
    MediaActionSound sound = new MediaActionSound();
    sound.play(MediaActionSound.SHUTTER_CLICK);


public void switch_camera(View view) 
    closeCamera();
    //swap the id of the camera to be used
    if(mCameraId == String.valueOf(Camera.CameraInfo.CAMERA_FACING_BACK))
        mCameraId = String.valueOf(Camera.CameraInfo.CAMERA_FACING_FRONT);
    
    else 
        mCameraId = String.valueOf(Camera.CameraInfo.CAMERA_FACING_BACK);
    
    BleUtils.setCameraLens(this, mCameraId);
    if (mTextureView.isAvailable()) 

        setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),mCameraId);
        openCamera();
     else 
        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
    



File createImageFile() throws IOException 

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "BLE_" + timeStamp + "_";
    File storageDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    if(!storageDirectory.exists())
        if(!storageDirectory.mkdirs())
            Log.e("Dir", "Failed to create directory");
            Log.d("MAKE DIR", storageDirectory.mkdir() + "" +  storageDirectory.getParentFile() + "");
            return null;
        
    
    File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
    mImageFileLocation = image.getAbsolutePath();

    return image;


@Override
public void onResume() 
    super.onResume();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        if(!hasAllPermissions(this, PERMISSIONS))
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        
    
    openBackgroundThread();
    if (mTextureView.isAvailable()) 
        if (!TextUtils.isEmpty(BleUtils.getCameraLens(AndroidCamera.this)))
            setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),BleUtils.getCameraLens(AndroidCamera.this));
        else
            setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),"1");
        closeCamera();
        openCamera();
     else 
        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
    

@Override
public void onDestroy() 
    super.onDestroy();
    Log.d(TAG,"onDestroy");

public void onPause() 
    Log.d(TAG,"onPause");
    closeCamera();

    closeBackgroundThread();
    super.onPause();


private void setupCamera(int width, int height, String cameraId) 
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try 
            CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

            Size largestImageSize = Collections.max(
                    Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
                    new Comparator<Size>() 
                        @Override
                        public int compare(Size lhs, Size rhs) 
                            return Long.signum(lhs.getWidth() * lhs.getHeight() -
                                    rhs.getWidth() * rhs.getHeight());
                        
                    
            );
            mImageReader = ImageReader.newInstance(largestImageSize.getWidth(),
                    largestImageSize.getHeight(),
                    ImageFormat.JPEG,
                    1);
            mImageReader.setOnImageAvailableListener(mOnImageAvailableListener,
                    mBackgroundHandler);
            mPreviewSize = getPreferredPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height);
            mCameraId = cameraId;
            Log.d("CAMERA_ID",String.valueOf(mCameraId));
    //    

     catch (CameraAccessException e) 
        e.printStackTrace();
    


private Size getPreferredPreviewSize(Size[] mapSizes, int width, int height) 
    List<Size> collectorSizes = new ArrayList<>();
    for (Size option : mapSizes) 
        if (width > height) 
            if (option.getWidth() > width &&
                    option.getHeight() > height) 
                collectorSizes.add(option);
            
         else 
            if (option.getWidth() > height &&
                    option.getHeight() > width) 
                collectorSizes.add(option);
            
        
    
    if (collectorSizes.size() > 0) 
        return Collections.min(collectorSizes, new Comparator<Size>() 
            @Override
            public int compare(Size lhs, Size rhs) 
                return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight());
            
        );
    
    return mapSizes[0];



private void openCamera() 
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try 
        Log.v("CAMERA", mCameraId + " " + mCameraDeviceStateCallback);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
                    == PackageManager.PERMISSION_GRANTED)
                cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback,mBackgroundHandler);
            
            else 
                if (shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA))
                    Toast.makeText(this,"No Permission to use the Camera services", Toast.LENGTH_SHORT).show();
                
                requestPermissions(new String[] android.Manifest.permission.CAMERA,REQUEST_CAMERA_RESULT);
            
        
        else 
            cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
        
     catch (CameraAccessException e) 
        e.printStackTrace();
    



@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 
    switch (requestCode)
        case  REQUEST_CAMERA_RESULT:
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED)
                Toast.makeText(this, "Cannot run application because camera service permission have not been granted", Toast.LENGTH_SHORT).show();
            
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            break;
    

private void closeCamera()
    if(mCameraCaptureSession!=null)
        mCameraCaptureSession.close();
        mCameraCaptureSession=null;
    
    if (mCameraDevice!=null)
        mCameraDevice.close();
        mCameraDevice=null;

        if(mImageReader!=null)

            mImageReader.close();
            mImageReader=null;

        
    

private void createCameraPreviewSession()
    try
        SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
        surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight());
        Surface previewSurface= new Surface(surfaceTexture);
        mPreviewCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        mPreviewCaptureRequestBuilder.addTarget(previewSurface);
        mPreviewCaptureRequestBuilder.set(CaptureRequest.JPEG_QUALITY, (byte)100);
        mCameraDevice.createCaptureSession(Arrays.asList(previewSurface,mImageReader.getSurface()),
                new CameraCaptureSession.StateCallback() 
                    @Override
                    public void onConfigured(CameraCaptureSession session) 
                        if(mCameraDevice==null)
                            return;
                        
                        try 
                            mPreviewCaptureRequest = mPreviewCaptureRequestBuilder.build();
                            mCameraCaptureSession = session;
                            mCameraCaptureSession.setRepeatingRequest(
                                    mPreviewCaptureRequest,
                                    mSessionCaptureCallback,
                                    mBackgroundHandler
                            );

                        catch (CameraAccessException e)
                            e.printStackTrace();
                        

                    

                    @Override
                    public void onConfigureFailed(CameraCaptureSession session) 
                        Handler mHandler = new Handler(getMainLooper());
                        mHandler.post(new Runnable() 
                            @Override
                            public void run() 
                                Toast.makeText(
                                        getApplicationContext(),
                                        "create camera session failed!",
                                        Toast.LENGTH_SHORT
                                ).show();
                            
                        );

                    
                ,null);

    catch (CameraAccessException e)
        e.printStackTrace();
    


private void openBackgroundThread()
    mBackgroundThread=new HandlerThread("Camera2 background thread");
    mBackgroundThread.start();
    mBackgroundHandler = new Handler(mBackgroundThread.getLooper());

private  void closeBackgroundThread()

    mBackgroundThread.quitSafely();
    try

        mBackgroundThread.join();
        mBackgroundThread=null;
        mBackgroundHandler=null;

    catch (InterruptedException e)
        e.printStackTrace();
    



private void lockFocus()
    try

        mState=STATE_WAIT_LOCK;
        mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CaptureRequest.CONTROL_AF_TRIGGER_START);
        mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),
                mSessionCaptureCallback,mBackgroundHandler);

    catch (CameraAccessException e)
        e.printStackTrace();
    


private void unLockFocus()
    try

        mState=STATE_PREVIEW;
        mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
        mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),
                mSessionCaptureCallback,mBackgroundHandler);

    catch (CameraAccessException e)
        e.printStackTrace();
    


private void captureStillImage()
    try 

        CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        captureStillBuilder.addTarget(mImageReader.getSurface());

        // Use the same AE and AF modes as the preview.
        captureStillBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
       // setAutoFlash(captureBuilder);

        // Orientation
        int rotation=0;
        //Front camera
        if(mCameraId.equals("1")) 
            rotation = this.getWindowManager().getDefaultDisplay().getRotation();
            captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
        
        else 
            rotation = this.getWindowManager().getDefaultDisplay().getRotation();
            captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION,
                    ORIENTATIONS.get(rotation));
        

        CameraCaptureSession.CaptureCallback captureCallback =
                new CameraCaptureSession.CaptureCallback() 
                    @Override
                    public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) 
                        super.onCaptureCompleted(session, request, result);

                        //Toast.makeText(getApplicationContext(),"Image Captured",Toast.LENGTH_SHORT).show();

                        unLockFocus();
                    
                ;

        mCameraCaptureSession.capture(

                captureStillBuilder.build(),captureCallback,null
        );

    catch (CameraAccessException e)
        e.printStackTrace();
    


private int getOrientation(int rotation) 
    return (ORIENTATIONS.get(rotation) + mSensorOrientation +180) % 360;

【问题讨论】:

你可以看看这个解决方案***.com/a/34841433/1840795 在授予权限之前您是否正在启动相机? 不,先生,我之前检查过许可。有时我成功地拍照了。但是,有时我失败了。 您能告诉我们您使用的是哪款智能手机/模拟器吗?如果您在另一台设备上测试过您的代码? 是的,我使用的是 Galaxy S7 和 Android M。我在 Android 5.0 中测试没有错误 【参考方案1】:

setupCamera() 直接从onSurfaceTextureAvailable 调用,可以早于授予权限。

您需要做的是跟踪权限是否被授予以及表面纹理是否在两个回调中可用。

为检查这些条件和设置相机创建一个条目

private boolean mSurfaceTextureAvailable;
private boolean mPermissionsGranted;
private boolean mCameraOpened;

private void setupCameraIfPossible() 
    if (!mCameraOpened && mSurfaceTextureAvailable && mPermissionsGranted) 
        String cameraLens = BleUtils.getCameraLens(AndroidCamera.this);
        if (TextUtils.isEmpty(cameraLens)) 
            cameraLens = "1";
        
        setupCamera(mTextureView.getWidth(), mTextureView.getHeight(), cameraLens);
        openCamera();
    


private final TextureView.SurfaceTextureListener mSurfaceTextureListener =
        new TextureView.SurfaceTextureListener() 
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) 
                mSurfaceTextureAvailable = true;
                setupCameraIfPossible();
            

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) 

            

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) 
                //closeCamera();
                mSurfaceTextureAvailable = false;
                return false;
            

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) 

            
        ;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.camera_activity);
    openBackgroundThread();

    // Make sure the boolean flag is set. Will be true for lower SDK
    mPermissionsGranted = hasAllPermissions(this, PERMISSIONS);
    if (!mPermissionsGranted) 
        ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
    
    mTextureView = (TextureView) findViewById(R.id.texture);

onResume() 中,您不需要检查权限。如果他们在后台被拒绝,您的 Activity 将被终止,您将再次通过onCreate()

删除onPause()onResume()中的代码!

//    @Override
//    public void onResume() 
//        super.onResume();
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
//            if(!hasAllPermissions(this, PERMISSIONS))
//                ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
//            
//        
//        openBackgroundThread();
//        if (mTextureView.isAvailable()) 
//            if (!TextUtils.isEmpty(BleUtils.getCameraLens(AndroidCamera.this)))
//                setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),BleUtils.getCameraLens(AndroidCamera.this));
//            else
//                setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),"1");
//            closeCamera();
//            openCamera();
//         else 
//            mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
//        
//    

//    public void onPause() 
//        Log.d(TAG,"onPause");
//        closeCamera();
//
//        closeBackgroundThread();
//        super.onPause();
//    

将此添加到onStart()

@Override
public void onStart() 
    super.onStart();
    openCameraIfPossible();

将关闭相机移动到onStop()

@Override
public void onStop() 
    super.onStop();
    closeCamera();


private void closeCamera() 
    mCameraOpened = false; // set a field indicating it is closed
    ...


private void openCamera() 
    ...
    mCameraOpened = true; // If successful, set a field indicating it is opened

现在我发现的另一件事是,您实际上必须检查 onRequestPermissionsResult() 中的权限,而不是使用 grantResults 标志

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
        case REQUEST_CAMERA_RESULT:
            mPermissionsGranted = hasAllPermissions(this, PERMISSIONS);
            setupCameraIfPossible();
            break;

        default:
            break;
    

【讨论】:

谢谢。我想你错过了调用函数openBackgroundThread。其次,仍然是上述问题的错误。 @user3051460 是的,对不起,我错过了。编辑并添加到 onCreate()。你确定错误日志和上面一样吗?我无法运行您的代码,因为我没有 BleUtils 和您的布局。 等我一下。我会创建一个项目让你知道 终于,我得到了解决方案。问题是我在屏幕未准备好时开始预览(屏幕关闭然后打开)。为了解决这个问题,我添加了一个计时器来设置延迟时间。这是我的代码。您可以贡献并提供比使用计时器更好的解决方案。谢谢github.com/mjohn123/Camera2APIM 我接受了它以感谢您的帮助。此外,我需要将openBackgroundThread 移动到onResume 函数上,而不是onCreate. 让我们查看我的代码了解更多详情

以上是关于在 Android 6.0 中缺乏访问相机服务的权限的主要内容,如果未能解决你的问题,请参考以下文章

Android 6.0 RuntimeException:无法连接到相机服务

Android 6.0 运行时权限处理

Android 6.0系统动态请求系统相机和读取手机存储权限

Android学习之相机权限适配问题详解

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

在 Android > 6.0 中,第二次从图库中访问图像时出现安全权限异常