Android:权限被拒绝:以已撤销的权限启动 Intent android.permission.CAMERA

Android: Permission Denial: starting Intent with revoked permission android.permission.CAMERA

我正在尝试启动 ACTION_IMAGE_CAPTURE activity 以便在我的应用程序中拍照,但我在主题。

堆栈跟踪:

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文件中:

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

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

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

here 是 android 相机项目

的完整清单示例

您好,您可以在清单文件中使用这些权限和其他权限,

<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 设置权限的几个步骤,请记住您也应该在清单文件中声明相同的权限。

第一步,声明全局变量:

 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 步。在您的主程序中使用此代码 activity

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

并在您的 activity 需要添加权限的地方实施。

@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 中获得每个结果。

更新:

现在我们有非常有序的权限处理方式。所以,这是步骤。我在这里为 kotlin 添加了。

第 1 步。将其声明为全局变量或任何位置。

private val permissions = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { granted ->
        granted.entries.forEach {
            when (it.value) {
                true -> {
                    // Call whatever you want to do when someone allow the permission. 
                }
                false -> {
                    showPermissionSettingsAlert(requireContext())
                }
            }
        }
    }

第 2 步

// You can put this line in constant.
val storagePermission = arrayOf(
    Manifest.permission.READ_EXTERNAL_STORAGE
)

// You can put this in AppUtil. 
fun checkPermissionStorage(context: Context): Boolean {
        val result =
            ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE)

        return result == PackageManager.PERMISSION_GRANTED
 }


// Put this where you need Permission check. 

    if (!checkPermissionStorage(requireContext())) {
        permissions.launch(
                storagePermission
        )
    } else {
        // Permission is already added. 
    }

步骤 3. 权限拒绝对话框。如果你愿意,你可以使用这个。

fun showPermissionSettingsAlert(context: Context) {
    val builder = AlertDialog.Builder(context)
    builder.setTitle("Grant Permission")
    builder.setMessage("You have rejected the Storage 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. Please select \"Go to settings\" to go to application settings in your device.")
    builder.setPositiveButton("Allow") { dialog, which ->
        val intent = Intent()
        intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
        val uri = Uri.fromParts("package", context.packageName, null)
        intent.data = uri
        context.startActivity(intent)
    }
    builder.setNeutralButton("Deny") { dialog, which ->

        dialog.dismiss()
    }
    val dialog = builder.create()
    dialog.show()
}

谢谢

希望对您有所帮助 (Y)。

删除此权限

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

我在 android 7 中执行我的应用程序时遇到了这个错误。经过测试,我注意到 用户权限 不在项目 A 中,而是在项目 B 中,即我只在 android 5 台设备上进行了测试。因此,我删除了项目 B 中的该权限,以便 运行 在其他以 android 7 为目标的设备上,它终于可以打开了。

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

在我的例子中,问题与我的模拟器权限有关,

解决问题:

1- Go to Settings of your emulator.

2- Look for Apps and Notifications.

3- Click on Add Permission.

see the pic : https://i.stack.imgur.com/z4GfK.png

4- Select Camera of the list.

5- Look for your Application in the provided list.

6- Enable Camera.

see the pic : https://i.stack.imgur.com/dJ8wG.pngEnjoy

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

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 上添加:

int requestCode = 200;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    requestPermissions(permissions, requestCode);
}

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

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

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

简答 ...它正在寻找权限,如果权限失败,它会抛出异常;此外,在这种情况下,它正在寻找两个权限,即第一个存储和第二个相机。

长答案.....给它权限写入方式来处理Android.I的所有版本我正在循环获取权限存储和相机,这样它就可以与 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. 通过
  2. 检查或请求权限
  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();是我在获得存储和相机权限后要求意图(开始意图)的地方。

不要因阅读大量错误而感到困惑 ;)

我是这样解决的:

首先我认为 当您尝试在 (SDK < 26) 上使用您的设备相机时没有完全权限.

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

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

为了解决这个问题,我将 that 更改为 this:

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

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

If your application uses, but does not require a camera in order to function, instead set android:required to false. In doing so, Google Play will allow devices without a camera to download your application. It's then your responsibility to check for the availability of the camera at runtime by calling hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY). If a camera is not available, you should then disable your camera features.

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

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

但是,这对我来说还不够,因为我的应用程序中的其他内容需要相机权限。所以对我有用的是将该权限标记为不需要,如下所示:

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

如果您需要保留

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

清单中的权限,只需确保在打开系统相机之前授予它。 在现代 android 中,您可以这样做:

   val cameraPermissionResult =
    registerForActivityResult(ActivityResultContracts.RequestPermission()) { permitted ->
        if (permitted) {
            openSystemCamera()
        }
    }

您可以按如下方式使用cameraPermissionResult:

cameraPermissionResult.launch(Manifest.permission.CAMERA)

如果您的应用已经获得该权限,它将只调用 openSystemCamera() 而无需任何用户操作。 在其他情况下,将显示权限对话框并根据用户选择的权限打开系统相机。

我来晚了,但请检查一下,因为总是有一些更新

根据官方开发者页面 - https://developer.android.com/training/camera/photobasics,您不需要在 Manifest.xml 中使用 uses-permission 而是使用 uses-feature :

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

注意 - 是uses-feature,不是uses-permission

检查正确,如果你同时使用uses-permissionuses-feature,可能你会同样崩溃(这个注意最重要然后从官方页面更新了内容,因为我同时使用了两个参数并遇到了这个崩溃,而且当我开始在我的应用程序中处理相机模块时,我不知道为什么我没有遇到这个问题但是现在应用程序突然开始崩溃)

来自开发者页面的关于 android:required 的更多信息:

If your application uses, but does not require a camera in order to function, instead set android:required to false. In doing so, Google Play will allow devices without a camera to download your application. It's then your responsibility to check for the availability of the camera at runtime by calling hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY). If a camera is not available, you should then disable your camera features.