diff --git a/camera/README.md b/camera/README.md
index ba1144ea0..6bebe3146 100644
--- a/camera/README.md
+++ b/camera/README.md
@@ -29,6 +29,14 @@ This API requires the following permissions be added to your `AndroidManifest.xm
```
+You can also specify those permissions only for the Android versions where they will be requested:
+
+```xml
+
+
+
+```
+
The storage permissions are for reading/saving photo files.
Read about [Setting Permissions](https://capacitorjs.com/docs/android/configuration#setting-permissions) in the [Android Guide](https://capacitorjs.com/docs/android) for more information on setting Android permissions.
diff --git a/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.java b/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.java
index 2fd96d87f..754e76720 100644
--- a/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.java
+++ b/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.java
@@ -62,12 +62,19 @@
name = "Camera",
permissions = {
@Permission(strings = { Manifest.permission.CAMERA }, alias = CameraPlugin.CAMERA),
- // SDK VERSIONS 32 AND BELOW
+ // SDK VERSIONS 29 AND BELOW
@Permission(
strings = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE },
alias = CameraPlugin.PHOTOS
),
/*
+ SDK VERSIONS 30-32
+ This alias is a placeholder and the PHOTOS alias will be updated to use this permission
+ so that the end user does not need to explicitly use separate aliases depending
+ on the SDK version.
+ */
+ @Permission(strings = { Manifest.permission.READ_EXTERNAL_STORAGE }, alias = CameraPlugin.READ_EXTERNAL_STORAGE),
+ /*
SDK VERSIONS 33 AND ABOVE
This alias is a placeholder and the PHOTOS alias will be updated to use these permissions
so that the end user does not need to explicitly use separate aliases depending
@@ -82,6 +89,7 @@ public class CameraPlugin extends Plugin {
static final String CAMERA = "camera";
static final String PHOTOS = "photos";
static final String MEDIA = "media";
+ static final String READ_EXTERNAL_STORAGE = "readExternalStorage";
// Message constants
private static final String INVALID_RESULT_TYPE_ERROR = "Invalid resultType option";
@@ -206,11 +214,16 @@ else if (!hasCameraPerms) {
}
private boolean checkPhotosPermissions(PluginCall call) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
if (getPermissionState(PHOTOS) != PermissionState.GRANTED) {
requestPermissionForAlias(PHOTOS, call, "cameraPermissionsCallback");
return false;
}
+ } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ if (getPermissionState(READ_EXTERNAL_STORAGE) != PermissionState.GRANTED) {
+ requestPermissionForAlias(READ_EXTERNAL_STORAGE, call, "cameraPermissionsCallback");
+ return false;
+ }
} else if (getPermissionState(MEDIA) != PermissionState.GRANTED) {
requestPermissionForAlias(MEDIA, call, "cameraPermissionsCallback");
return false;
@@ -235,9 +248,13 @@ private void cameraPermissionsCallback(PluginCall call) {
call.reject(PERMISSION_DENIED_ERROR_CAMERA);
return;
} else if (settings.getSource() == CameraSource.PHOTOS) {
- PermissionState permissionState = (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
- ? getPermissionState(PHOTOS)
- : getPermissionState(MEDIA);
+ String alias = MEDIA;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ alias = PHOTOS;
+ } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ alias = READ_EXTERNAL_STORAGE;
+ }
+ PermissionState permissionState = getPermissionState(alias);
if (permissionState != PermissionState.GRANTED) {
Logger.debug(getLogTag(), "User denied photos permission: " + permissionState.toString());
call.reject(PERMISSION_DENIED_ERROR_PHOTOS);
@@ -257,6 +274,12 @@ protected void requestPermissionForAliases(@NonNull String[] aliases, @NonNull P
aliases[i] = MEDIA;
}
}
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ for (int i = 0; i < aliases.length; i++) {
+ if (aliases[i].equals(PHOTOS)) {
+ aliases[i] = READ_EXTERNAL_STORAGE;
+ }
+ }
}
super.requestPermissionForAliases(aliases, call, callbackName);
}
@@ -817,9 +840,15 @@ public Map getPermissionStates() {
permissionStates.put(CAMERA, PermissionState.GRANTED);
}
- // If the SDK version is 33 or higher, update the PHOTOS state to match the MEDIA state.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && permissionStates.containsKey(MEDIA)) {
- permissionStates.put(PHOTOS, permissionStates.get(MEDIA));
+ // If the SDK version is 30 or higher, update the PHOTOS state to match the MEDIA or READ_EXTERNAL_STORAGE states.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ String alias = READ_EXTERNAL_STORAGE;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ alias = MEDIA;
+ }
+ if (permissionStates.containsKey(alias)) {
+ permissionStates.put(PHOTOS, permissionStates.get(alias));
+ }
}
return permissionStates;