Android:Permission Denial:使用已撤销权限android.permission.CAMERA启动Intent

时间:2016-03-13 17:17:44

标签: android android-securityexception

我正在尝试启动 ACTION_IMAGE_CAPTURE 活动,以便在我的应用中拍照并且我在主题中收到错误。

堆栈跟踪:

FATAL EXCEPTION: main
Process: il.ac.shenkar.david.todolistex2, PID: 3293
java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity } from ProcessRecord{22b0eb2 3293:il.ac.shenkar.david.todolistex2/u0a126} (pid=3293, uid=10126) 
with revoked permission android.permission.CAMERA

摄像机权限已添加到manifest.xml fie:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

这是打开相机的电话:

RadioGroup radioGroup = (RadioGroup) findViewById(R.id.statusgroup);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId)
        {
            RadioButton rb = (RadioButton) findViewById(R.id.donestatusRBtn);
            if(rb.isChecked())
            {
                Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                    startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
                }
            }
        }
    });

10 个答案:

答案 0 :(得分:38)

删除此权限

  <uses-permission android:name="android.permission.CAMERA"/>

我在Android 7中执行我的应用程序时遇到此错误。测试后我注意到用户权限不在项目A中,但它在项目B中,我只在android 5设备中测试过。所以我删除了项目B中的权限,以便在其他针对android 7的设备上运行它,它最终可以打开。

在adittion中,我添加了Android在此处建议的文件提供者代码https://developer.android.com/training/camera/photobasics.html 希望这会有所帮助。

答案 1 :(得分:15)

您可以在清单文件中使用这些权限并获得其他权限,

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

如果仍然无法正常工作,那么您可能正在使用Android M,那么您需要以编程方式添加权限。

这是示例

嗨这里是安装Android M的几个步骤,并记住你也应该在清单文件中声明相同的权限。

步骤1.声明全局变量:

 public final int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 1;

//requests for runtime time permissions

 String CAMERA_PERMISSION = android.Manifest.permission.CAMERA;


 String READ_EXTERNAL_STORAGE_PERMISSION = android.Manifest.permission.READ_EXTERNAL_STORAGE;


String WRITE_EXTERNAL_STORAGE_PERMISSION = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;


// for security permissions
@DialogType
private int mDialogType;
private String mRequestPermissions = "We are requesting the camera and Gallery permission as it is absolutely necessary for the app to perform it\'s functionality.\nPlease select \"Grant Permission\" to try again and \"Cancel \" to exit the application.";
private String mRequsetSettings = "You have rejected the camera and Gallery permission for the application. As it is absolutely necessary for the app to perform you need to enable it in the settings of your device.\nPlease select \"Go to settings\" to go to application settings in your device and \"Cancel \" to exit the application.";
private String mGrantPermissions = "Grant Permissions";
private String mCancel = "Cancel";
private String mGoToSettings = "Go To Settings";
private String mPermissionRejectWarning = "Cannot Proceed Without Permissions</string>
<string name="explanation_permission_location_request">We are requesting the location permission as it is necessary for the app to perform search functionality properly.\nPlease select \"Grant Permission\" to try again and \"Cancel \" to deny permission.";

//创建这样的对话框。

// type of dialog opened in MainActivity
 @IntDef({DialogType.DIALOG_DENY, DialogType.DIALOG_NEVER_ASK})
 @Retention(RetentionPolicy.SOURCE)
 @interface DialogType {
    int DIALOG_DENY = 0, DIALOG_NEVER_ASK = 1;
 }

步骤2.在主要活动中使用此代码

@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED && grantResults[2] == PackageManager.PERMISSION_GRANTED) {
                // Call your camera here.
            } else {
                boolean showRationale1 = shouldShowRequestPermissionRationale(CAMERA_PERMISSION);
                boolean showRationale2 = shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE_PERMISSION);
                boolean showRationale3 = shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE_PERMISSION);
                if (showRationale1 && showRationale2 && showRationale3) {
                    //explain to user why we need the permissions
                    mDialogType = ValueConstants.DialogType.DIALOG_DENY;
                    // Show dialog with 
                    openAlertDialog(mRequestPermissions, mGrantPermissions, mCancel, this, MyActivity.this);
                } else {
                    //explain to user why we need the permissions and ask him to go to settings to enable it
                    mDialogType = ValueConstants.DialogType.DIALOG_NEVER_ASK;
                    openAlertDialog(mRequsetSettings, mGoToSettings, mCancel, this, MyActivity.this);
                }
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

//check for camera and storage access permissions
@TargetApi(Build.VERSION_CODES.M)
private void checkMultiplePermissions(int permissionCode, Context context) {

    String[] PERMISSIONS = {CAMERA_PERMISSION, READ_EXTERNAL_STORAGE_PERMISSION, WRITE_EXTERNAL_STORAGE_PERMISSION};
    if (!hasPermissions(context, PERMISSIONS)) {
        ActivityCompat.requestPermissions((Activity) context, PERMISSIONS, permissionCode);
    } else {
        // Open your camera here.
    }
}

private boolean hasPermissions(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;
}

步骤3.在oncreate方法中调用此方法,

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            checkMultiplePermissions(REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS, MyActivity.this);
   } else {
            // Open your camera here.
   }

步骤4.权限拒绝的对话框

public static void openAlertDialog(String message, String positiveBtnText, String negativeBtnText,
                            final OnDialogButtonClickListener listener,Context mContext) {

    AlertDialog.Builder builder = new AlertDialog.Builder(mContext, R.style.AlertDialogCustom);
    builder.setPositiveButton(positiveBtnText, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            dialogInterface.dismiss();
            listener.onPositiveButtonClicked();
        }
    });
    builder.setPositiveButton(positiveBtnText, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            dialogInterface.dismiss();
            listener.onNegativeButtonClicked();
        }
    });

    builder.setTitle(mContext.getResources().getString(R.string.app_name));
    builder.setMessage(message);
    builder.setIcon(android.R.drawable.ic_dialog_alert);
    builder.setCancelable(false);
    builder.create().show();
}

//创建此界面

public interface OnDialogButtonClickListener {

void onPositiveButtonClicked();

void onNegativeButtonClicked();
}

并在需要添加权限的活动中实现此功能。

@Override
public void onPositiveButtonClicked() {
    switch (mDialogType) {
        case ValueConstants.DialogType.DIALOG_DENY:
            checkMultiplePermissions(REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS, MyActivity.this);
            break;
        case ValueConstants.DialogType.DIALOG_NEVER_ASK:
            redirectToAppSettings(MyActivity.this);
            break;

    }
}

@Override
public void onNegativeButtonClicked() {

}

你可以从这里调用任何权限,你可以在覆盖方法onRequestPermissionsResult中获得每个结果。

三江源

希望这会对你有所帮助(Y)。

答案 2 :(得分:6)

在我的情况下,问题与我的模拟器权限有关,

解决问题:

  

1-转到模拟器的设置。

     

2-查找应用和通知。

     

3-单击“添加权限”。

     

见图片:https://i.stack.imgur.com/z4GfK.png

     

4-选择列表的摄像头。

     

5-在提供的列表中查找您的应用程序。

     

6-启用相机。

     

见图片:https://i.stack.imgur.com/dJ8wG.pngEnjoy

现在您可以在模拟器上使用相机了:)

答案 3 :(得分:6)

这是我如何解决我的问题:

首先,我 认为 ,当您尝试在没有FULL权限的情况下在SDK <26上使用设备Camera时,就会出现此问题。

是的,即使您已经包含了此权限:

<uses-permission android:name="android.permission.CAMERA"/>

为解决此问题,我将那个更改为这个

<uses-permission android:name="android.permission.CAMERA" 
                 android:required="true" 
                 android:requiredFeature="true"/>

Android文档中的这些信息可能真的很有帮助

如果您的应用程序使用相机,但不需要照相机即可运行,请将android:required设置为false。这样,Google Play将允许没有摄像头的设备下载您的应用程序。然后,您有责任通过调用hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)在运行时检查相机的可用性。如果没有相机,则应禁用相机功能。

答案 4 :(得分:2)

supportActionBar?.hide()

在您的private String [] permissions = {"android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.ACCESS_FINE_LOCATION", "android.permission.READ_PHONE_STATE", "android.permission.SYSTEM_ALERT_WINDOW","android.permission.CAMERA"}; 上添加以下内容:

OnCreate

答案 5 :(得分:2)

简短答案 ...它正在寻找权限,权限失败后会引发异常;此外,在这种情况下,它正在寻找两个权限,即第一存储和第二摄像机。

长答案.....给它权限写入方式以在所有版本的Android上都可以使用。我循环获取权限Storage和Camera,以便它可以与Intent一起使用。

  1. 保留在AndroidManifest.xml中
<uses-feature
        android:name="android.hardware.camera.any"
        android:required="true" />
    <uses-feature
        android:name="android.hardware.camera.autofocus"
        android:required="false" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  1. 通过以下方式检查或请求权限
  private void myStoragePermission() {
        if (ContextCompat.checkSelfPermission(Activity_Scan_QR.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            myCameraPermission();
        } else {
            //changed here
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
            }
        }
    }

    //+10 changed its sinature as Fragment; without it  onRequestPermissionsResult won't bbe called
    private void myCameraPermission() {
        if (ContextCompat.checkSelfPermission(Activity_Scan_QR.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            takePicture();
        } else {
            //changed here
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
            }
        }
    }

  1. 添加onRequestPermissionsResult
 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_WRITE_PERMISSION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    myStoragePermission();
                } else {

                    showSnackbar(R.string.act_ScanQR_txt13, R.string.settings,
                            new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    // Build intent that displays the App settings screen.
                                    Intent intent = new Intent();
                                    intent.setAction(
                                            Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                    Uri uri = Uri.fromParts("package",
                                            BuildConfig.APPLICATION_ID, null);
                                    intent.setData(uri);
                                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                    startActivity(intent);
                                }
                            });
                }
            case REQUEST_CAMERA_PERMISSION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    takePicture();
                } else {

                    showSnackbar(R.string.act_ScanQR_txt14, R.string.settings,
                            new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    // Build intent that displays the App settings screen.
                                    Intent intent = new Intent();
                                    intent.setAction(
                                            Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                    Uri uri = Uri.fromParts("package",
                                            BuildConfig.APPLICATION_ID, null);
                                    intent.setData(uri);
                                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                    startActivity(intent);
                                }
                            });

                }
        }
    }

以上代码中的takePicture();获得存储和摄像头权限后,我就在这里调用intent(开始意图)。

不要因为阅读过多的错误而感到困惑;)

答案 6 :(得分:1)

正如某些人指出的那样,一种解决方案是从AndroidManifest.xml中删除“摄像机权限”,即删除这一行:

<uses-permission android:name="android.permission.CAMERA" />

但是,这对我来说还不够,因为我需要对我的应用程序中的其他内容使用“摄影机权限”。因此,对我有用的是将该权限标记为不需要的权限,例如:

<uses-permission android:name="android.permission.CAMERA" android:required="false" />

答案 7 :(得分:0)

供以后参考,如果有人在与flutter相关的android项目中遇到问题:

https://github.com/apptreesoftware/flutter_barcode_reader/issues/32#issuecomment-420516729

答案 8 :(得分:0)

万一其他人遇到了这个问题,我的问题是我运行该应用时未请求任何权限。似乎小米设备会自动拒绝对通过adb安装的应用程序的权限。我只是通过设置启用了权限,并且有效。

答案 9 :(得分:-7)

在你的androidManifest中,你必须添加:

 <uses-feature android:name="android.hardware.camera" />

here是Android相机项目的完整清单示例