45

我正在尝试启动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);
                }
            }
        }
    });
4

11 回答 11

76

移除此权限

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

于 2017-09-21T16:48:30.177 回答
24

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

<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)。

于 2016-03-13T17:24:46.027 回答
15

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

要解决此问题:

1-转到模拟器的设置。

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

3- 单击添加权限。

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

4- 选择列表中的相机。

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

6-启用相机。

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

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

于 2017-11-01T19:02:19.220 回答
11

这是我解决我的方法:

首先,我认为当您尝试在没有完全权限的情况下使用设备相机(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:requiredfalse. 这样一来,Google Play 将允许没有摄像头的设备下载您的应用程序。然后,您有责任通过调用在运行时检查相机的可用性hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)。如果相机不可用,则应禁用相机功能。

于 2020-07-14T08:02:34.740 回答
9
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);
}
于 2018-08-31T06:22:25.583 回答
2

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

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

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

于 2020-06-27T16:40:51.977 回答
2

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

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

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

<uses-permission android:name="android.permission.CAMERA" android:required="false" />
于 2020-09-15T23:35:21.817 回答
0

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

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

于 2018-09-12T05:28:52.527 回答
0

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

于 2019-07-16T11:25:11.777 回答
0

如果您需要保留

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

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

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

您可以使用 cameraPermissionResult 如下:

cameraPermissionResult.launch(Manifest.permission.CAMERA)

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

于 2022-01-20T12:51:31.523 回答
-9

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

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

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

于 2016-03-13T17:24:40.097 回答