繁体   English   中英

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

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

我正在尝试启动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 文件中:

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

移除此权限

  <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希望这会有所帮助。

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

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

现在我们有了非常有序的权限处理方式。 所以,这里是步骤。 我在这里添加了 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)。

就我而言,问题与我的模拟器权限有关,

要解决此问题:

1-转到模拟器的设置。

2- 寻找应用程序和通知。

3- 单击添加权限。

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

4- 选择列表中的相机。

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

6-启用相机。

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

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

这是我解决我的方法:

首先,我认为当您尝试在没有完全权限的情况下使用设备相机(SDK < 26)时会出现问题。

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

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

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

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

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

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

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

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

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

然而,这对我来说还不够,因为我需要相机权限才能在我的应用程序中使用其他东西。 所以对我有用的是将该权限标记为不需要,如下所示:

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

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

长答案.....给它权限写入方式以在所有版本的 Android 上工作。我正在循环获取权限存储和相机,以便它可以与 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(); 是我在获得存储和相机权限后调用意图(开始意图)的地方。

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

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

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

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

如果您需要保留

<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的更多信息来自开发者页面:

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM