Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android "Permission Denial: can't use the camera"

I'm following a tutorial on utilizing the camera in an Android app. I am getting the error "Permission Denial: can't use the camera" when running debug, both on emulator and physical device. I have tried a variety of permissions in my manifest file. It seems most people who have had this error have had a typo, a missing permission, or the permissions not in the right place in their manifest.

Here's my manifest file:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.karudo.dbzrealpowerup" >

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".DBZHome"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".DBZStartPowerUp"
            android:label="@string/title_activity_dbzstart_power_up" >
        </activity>
    </application>

</manifest>

Here's my activity:

package com.example.karudo.dbzrealpowerup;

import android.app.Activity;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Bundle;
import android.util.Size;
import android.view.Menu;
import android.view.MenuItem;
import android.view.TextureView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class DBZStartPowerUp extends Activity {

    private Size mPreviewSize;
    private String mCameraId;
    private TextureView mTextureView;
    private TextureView.SurfaceTextureListener mSurfaceTextureListener =
            new TextureView.SurfaceTextureListener() {

                @Override
                public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                    setupCamera(width, height);
                    openCamera();
                }

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

                }

                @Override
                public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                    return false;
                }

                @Override
                public void onSurfaceTextureUpdated(SurfaceTexture surface) {

                }
            };

    private CameraDevice mCameraDevice;
    private CameraDevice.StateCallback mCameraDeviceStateCallback
            = new CameraDevice.StateCallback() {

        @Override
        public void onOpened(CameraDevice camera) {
            mCameraDevice = camera;
            Toast.makeText(getApplicationContext(), "Camera Opened!", Toast.LENGTH_SHORT).show();
        }

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

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dbzstartpowerup);
        mTextureView = (TextureView) findViewById(R.id.dbzCameraPreview);
    }

    @Override
    public void onResume() {
        super.onResume();
        if(mTextureView.isAvailable()) {

        } else {
            mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_dbzstartpowerup, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void setupCamera(int width, int height) {
        CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            for(String cameraId : cameraManager.getCameraIdList()) {
                CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
                if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
                        CameraCharacteristics.LENS_FACING_FRONT) {
                    continue;
                }
                StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                mPreviewSize = getPreferredPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height);
                mCameraId = cameraId;
                return;
            }
        } 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 {
            cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
}

And the error in my logcat:

10-04 03:15:02.740     961-8780/? E/CameraService﹕ Permission Denial: can't use the camera pid=20601, uid=10059
10-04 03:15:02.741  20601-20601/com.example.karudo.dbzrealpowerup E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.karudo.dbzrealpowerup, PID: 20601
    java.lang.SecurityException: Lacking privileges to access camera service
            at 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:324)
            at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:454)
            at com.example.karudo.dbzrealpowerup.DBZStartPowerUp.openCamera(DBZStartPowerUp.java:163)
            at com.example.karudo.dbzrealpowerup.DBZStartPowerUp.access$100(DBZStartPowerUp.java:23)
            at com.example.karudo.dbzrealpowerup.DBZStartPowerUp$1.onSurfaceTextureAvailable(DBZStartPowerUp.java:34)
            at android.view.TextureView.getHardwareLayer(TextureView.java:368)
            at android.view.View.updateDisplayListIfDirty(View.java:15151)
            at android.view.View.draw(View.java:15948)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
            at android.view.View.updateDisplayListIfDirty(View.java:15169)
            at android.view.View.draw(View.java:15948)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
            at android.view.View.updateDisplayListIfDirty(View.java:15169)
            at android.view.View.draw(View.java:15948)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
            at android.view.View.updateDisplayListIfDirty(View.java:15169)
            at android.view.View.draw(View.java:15948)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
            at android.view.View.draw(View.java:16181)
            at com.android.internal.policy.PhoneWindow$DecorView.draw(PhoneWindow.java:2690)
            at android.view.View.updateDisplayListIfDirty(View.java:15174)
            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:2615)
            at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
            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:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:148)
            at android.app.ActivityThread.main(ActivityThread.java:5417)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

I'm new to app development and admittedly I'm no good at debugging, but my manifest permissions appear to be correct from what I've seen of other people's files (and the tutorial which is only 4 months old).

Can anyone please tell me what I've done wrong?

Cheers, Lee.

UPDATE: I found via debugging that it crashes as soon as it reaches this method...

private void openCamera() {
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }

}

... specifically as soon as it runs the try statement.

UPDATE 2: If I comment out the try/catch statements, the app doesn't crash, but the expected result (which is to print "Camera Opened!") doesn't happen. Any ideas?

UPDATE 3: My apologies, I just realized how dumb my above edit was. It's obvious why it no longer crashes, but at least I now know I have to debug my cameraManager.openCamera parameters. The code is there if anyone can have a look :)

like image 919
Lee Valentine Avatar asked Oct 04 '15 03:10

Lee Valentine


3 Answers

If you're using Android 6 Marshmallow this issue could be caused by the new permission management. In my case I solved the problem by overriding the following activity method:

@Override
public void onRequestPermissionsResult(int requestCode,  String permissions[], int[] grantResults) {
    switch (requestCode) {
        case CAMERA_PERMISSION:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if(mClss != null) {
                    Intent intent = new Intent(this, ClassUsingCamera);
                    startActivity(intent);
                }
            } else {
                Toast.makeText(this, "Please grant camera permission to use the QR Scanner", Toast.LENGTH_SHORT).show();
            }
            return;
    }
}

I then launched the activity that requires the camera (ClassUsingCamera) with the following code:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
     ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION);
} else {
       Intent intent = new Intent(this, ClassUsingCamera);
       startActivity(intent);
        }

On the first app launch you'll get the popup asking you to grant the access to the camera.

Another option is to use the PermissionsDispatcher as explained here https://github.com/hotchemi/PermissionsDispatcher

like image 159
Roberto Avatar answered Sep 27 '22 19:09

Roberto


i got the same error only when i tried the app on devices with (Android 6.0.0) or emulator with (API 23). But with others it works fine.

that's because of android above M makes some changes in granted permissions on run-time application.

to do it, follow this few steps.

first : add this static variable.

private static final int REQUEST_CAMERA_RESULT = 1;

then modify your openCamera method

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();
    }
}

feel free to change mBackgroundHandler to null, i just made it to handle camera work in background thread.

And,then Override this method

@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;
    }
}
like image 20
Fady Emad Avatar answered Sep 27 '22 17:09

Fady Emad


Few points I can say :

  1. If connection to the camera service is fails (For example if the camera is used by anyother application or device manger has disable the camera or any of the application could not able to release the camera.)
  1. Make sure that your safely close/ release the camera inside your code.

  2. Have you tried checking if the camera is being used by something else or if your policy manager has some setting where the camera is turned off?

like image 25
Bhavdip Sagar Avatar answered Sep 27 '22 19:09

Bhavdip Sagar