Skip to content

Commit

Permalink
feat(android)!: Android 13 support (apache#844)
Browse files Browse the repository at this point in the history
* feat(android)!: Android 13 support
* refactor(android): simplify getPermissions logic
* feat(android)!: bump cordova-android requirement to >=12.0.0
* feat(android): update saveAlbumPermission to include Android 9 and below use case

---------

Co-authored-by: ochakov <[email protected]>
# Conflicts:
#	package-lock.json
#	package.json
#	plugin.xml
#	src/android/CameraLauncher.java
  • Loading branch information
Ricardo Petrére authored and ricardopetrere committed Sep 5, 2023
1 parent adf1579 commit d7b7693
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-camera",
"version": "4.2.0",
"version": "4.3.0",
"description": "Cordova Camera Plugin",
"types": "./types/index.d.ts",
"cordova": {
Expand Down
4 changes: 3 additions & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-camera"
version="4.2.0">
version="4.3.0">
<name>Camera</name>
<description>Cordova Camera Plugin</description>
<license>Apache 2.0</license>
Expand Down Expand Up @@ -55,6 +55,8 @@
</config-file>
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
</config-file>
<config-file target="AndroidManifest.xml" parent="application">
<provider
Expand Down
66 changes: 57 additions & 9 deletions src/android/CameraLauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Licensed to the Apache Software Foundation (ASF) under one
package org.apache.cordova.camera;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentValues;
Expand Down Expand Up @@ -58,6 +59,7 @@ Licensed to the Apache Software Foundation (ASF) under one
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
Expand Down Expand Up @@ -119,8 +121,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
private boolean orientationCorrected; // Has the picture's orientation been corrected
private boolean allowEdit; // Should we allow the user to crop the image.

protected final static String[] permissions = { Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE };

public CallbackContext callbackContext;
private int numPics;

Expand Down Expand Up @@ -191,8 +191,9 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
}
else if ((this.srcType == PHOTOLIBRARY) || (this.srcType == SAVEDPHOTOALBUM)) {
// FIXME: Stop always requesting the permission
if(!PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
PermissionHelper.requestPermission(this, SAVE_TO_ALBUM_SEC, Manifest.permission.READ_EXTERNAL_STORAGE);
String[] permissions = getPermissions(true, mediaType);
if(!hasPermissions(permissions)) {
PermissionHelper.requestPermissions(this, SAVE_TO_ALBUM_SEC, permissions);
} else {
this.getImage(this.srcType, destType, encodingType);
}
Expand All @@ -219,6 +220,38 @@ else if ((this.srcType == PHOTOLIBRARY) || (this.srcType == SAVEDPHOTOALBUM)) {
// LOCAL METHODS
//--------------------------------------------------------------------------

private String[] getPermissions(boolean storageOnly, int mediaType) {
ArrayList<String> permissions = new ArrayList<>();

if (android.os.Build.VERSION.SDK_INT >= 33) {
// if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// Android API 33 and higher
switch (mediaType) {
case PICTURE:
permissions.add("android.permission.READ_MEDIA_IMAGES");
break;
case VIDEO:
permissions.add("android.permission.READ_MEDIA_VIDEO");
break;
default:
permissions.add("android.permission.READ_MEDIA_IMAGES");
permissions.add("android.permission.READ_MEDIA_VIDEO");
break;
}
} else {
// Android API 32 or lower
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}

if (!storageOnly) {
// Add camera permission when not storage.
permissions.add(Manifest.permission.CAMERA);
}

return permissions.toArray(new String[0]);
}

private String getTempDirectoryPath() {
File cache = cordova.getActivity().getCacheDir();
// Create the cache directory if it doesn't exist
Expand All @@ -241,8 +274,14 @@ private String getTempDirectoryPath() {
* @param encodingType Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
*/
public void callTakePicture(int returnType, int encodingType) {
boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
&& PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
String[] storagePermissions = getPermissions(true, mediaType);
boolean saveAlbumPermission;
if (android.os.Build.VERSION.SDK_INT >= 29) {
// if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
saveAlbumPermission = this.saveToPhotoAlbum ? hasPermissions(storagePermissions) : true;
} else {
saveAlbumPermission = hasPermissions(storagePermissions);
}
boolean takePicturePermission = PermissionHelper.hasPermission(this, Manifest.permission.CAMERA);

// CB-10120: The CAMERA permission does not need to be requested unless it is declared
Expand Down Expand Up @@ -273,10 +312,9 @@ public void callTakePicture(int returnType, int encodingType) {
} else if (saveAlbumPermission && !takePicturePermission) {
PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.CAMERA);
} else if (!saveAlbumPermission && takePicturePermission) {
PermissionHelper.requestPermissions(this, TAKE_PIC_SEC,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, storagePermissions);
} else {
PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, permissions);
PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, getPermissions(false, mediaType));
}
}

Expand Down Expand Up @@ -1216,6 +1254,7 @@ private void checkForDuplicateImage(int type) {
// delete the duplicate file if the difference is 2 for file URI or 1 for Data URL
if ((currentNumOfImages - numPics) == diff) {
cursor.moveToLast();
@SuppressLint("Range")
int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID)));
if (diff == 2) {
id--;
Expand Down Expand Up @@ -1389,4 +1428,13 @@ private String getFileNameFromUri(Uri uri) {
String path = external_storage.getAbsolutePath() + partial_path;
return path;
}

private boolean hasPermissions(String[] permissions) {
for (String permission: permissions) {
if (!PermissionHelper.hasPermission(this, permission)) {
return false;
}
}
return true;
}
}
2 changes: 1 addition & 1 deletion tests/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-camera-tests",
"version": "4.2.0",
"version": "4.3.0",
"description": "",
"cordova": {
"id": "cordova-plugin-camera-tests",
Expand Down
2 changes: 1 addition & 1 deletion tests/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:rim="http://www.blackberry.com/ns/widgets"
id="cordova-plugin-camera-tests"
version="4.2.0">
version="4.3.0">
<name>Cordova Camera Plugin Tests</name>
<license>Apache 2.0</license>

Expand Down

0 comments on commit d7b7693

Please sign in to comment.