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 :)
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
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;
}
}
Few points I can say :
- 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.)
Make sure that your safely close/ release the camera inside your code.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With