Skip to content

Commit

Permalink
feat(android): implements Activity Result API changes for permissions…
Browse files Browse the repository at this point in the history
… and activity results (#222)

Co-authored-by: jcesarmobile <[email protected]>
  • Loading branch information
carlpoole and jcesarmobile authored Feb 9, 2021
1 parent 8eaca1b commit f671b9f
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 105 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.capacitorjs.plugins.camera;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
Expand All @@ -10,6 +9,7 @@
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Base64;
import androidx.activity.result.ActivityResult;
import androidx.core.content.FileProvider;
import com.getcapacitor.FileUtils;
import com.getcapacitor.JSArray;
Expand All @@ -19,9 +19,10 @@
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.PluginRequestCodes;
import com.getcapacitor.annotation.ActivityCallback;
import com.getcapacitor.annotation.CapacitorPlugin;
import com.getcapacitor.annotation.Permission;
import com.getcapacitor.annotation.PermissionCallback;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
Expand All @@ -45,17 +46,19 @@
@CapacitorPlugin(
name = "Camera",
permissions = {
@Permission(strings = { Manifest.permission.CAMERA }, alias = "camera"),
@Permission(strings = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }, alias = "photos")
},
requestCodes = { CameraPlugin.REQUEST_IMAGE_CAPTURE, CameraPlugin.REQUEST_IMAGE_PICK, CameraPlugin.REQUEST_IMAGE_EDIT }
@Permission(strings = { Manifest.permission.CAMERA }, alias = CameraPlugin.CAMERA),
@Permission(
strings = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE },
alias = CameraPlugin.PHOTOS
)
}
)
public class CameraPlugin extends Plugin {

// Request codes
static final int REQUEST_IMAGE_CAPTURE = PluginRequestCodes.CAMERA_IMAGE_CAPTURE;
static final int REQUEST_IMAGE_PICK = PluginRequestCodes.CAMERA_IMAGE_PICK;
static final int REQUEST_IMAGE_EDIT = PluginRequestCodes.CAMERA_IMAGE_EDIT;
// Permission alias constants
static final String CAMERA = "camera";
static final String PHOTOS = "photos";

// Message constants
private static final String INVALID_RESULT_TYPE_ERROR = "Invalid resultType option";
private static final String PERMISSION_DENIED_ERROR = "Unable to access camera, user denied permission request";
Expand All @@ -74,7 +77,7 @@ public class CameraPlugin extends Plugin {

private CameraSettings settings = new CameraSettings();

@PluginMethod(permissionCallback = "cameraPermissionsCallback")
@PluginMethod
public void getPhoto(PluginCall call) {
isEdited = false;

Expand Down Expand Up @@ -138,31 +141,31 @@ private void showPhotos(final PluginCall call) {
private boolean checkCameraPermissions(PluginCall call) {
// if the manifest does not contain the camera permissions key, we don't need to ask the user
boolean needCameraPerms = hasDefinedPermissions(new String[] { Manifest.permission.CAMERA });
boolean hasCameraPerms = !needCameraPerms || getPermissionState("camera") == PermissionState.GRANTED;
boolean hasPhotoPerms = getPermissionState("photos") == PermissionState.GRANTED;
boolean hasCameraPerms = !needCameraPerms || getPermissionState(CAMERA) == PermissionState.GRANTED;
boolean hasPhotoPerms = getPermissionState(PHOTOS) == PermissionState.GRANTED;

// If we want to save to the gallery, we need two permissions
if (settings.isSaveToGallery() && !(hasCameraPerms && hasPhotoPerms)) {
String[] aliases;
if (needCameraPerms) {
aliases = new String[] { "camera", "photos" };
aliases = new String[] { CAMERA, PHOTOS };
} else {
aliases = new String[] { "photos" };
aliases = new String[] { PHOTOS };
}
requestPermissionForAliases(aliases, call);
requestPermissionForAliases(aliases, call, "cameraPermissionsCallback");
return false;
}
// If we don't need to save to the gallery, we can just ask for camera permissions
else if (!hasCameraPerms) {
requestPermissionForAlias("camera", call);
requestPermissionForAlias(CAMERA, call, "cameraPermissionsCallback");
return false;
}
return true;
}

private boolean checkPhotosPermissions(PluginCall call) {
if (getPermissionState("photos") != PermissionState.GRANTED) {
requestPermissionForAlias("photos", call);
if (getPermissionState(PHOTOS) != PermissionState.GRANTED) {
requestPermissionForAlias(PHOTOS, call, "cameraPermissionsCallback");
return false;
}
return true;
Expand All @@ -174,13 +177,14 @@ private boolean checkPhotosPermissions(PluginCall call) {
* @see #getPhoto(PluginCall)
* @param call the plugin call
*/
@PermissionCallback
private void cameraPermissionsCallback(PluginCall call) {
if (settings.getSource() == CameraSource.CAMERA && getPermissionState("camera") != PermissionState.GRANTED) {
Logger.debug(getLogTag(), "User denied camera permission: " + getPermissionState("camera").toString());
if (settings.getSource() == CameraSource.CAMERA && getPermissionState(CAMERA) != PermissionState.GRANTED) {
Logger.debug(getLogTag(), "User denied camera permission: " + getPermissionState(CAMERA).toString());
call.reject(PERMISSION_DENIED_ERROR);
return;
} else if (settings.getSource() == CameraSource.PHOTOS && getPermissionState("photos") != PermissionState.GRANTED) {
Logger.debug(getLogTag(), "User denied photos permission: " + getPermissionState("photos").toString());
} else if (settings.getSource() == CameraSource.PHOTOS && getPermissionState(PHOTOS) != PermissionState.GRANTED) {
Logger.debug(getLogTag(), "User denied photos permission: " + getPermissionState(PHOTOS).toString());
call.reject(PERMISSION_DENIED_ERROR);
return;
}
Expand Down Expand Up @@ -235,7 +239,7 @@ public void openCamera(final PluginCall call) {
return;
}

startActivityForResult(call, takePictureIntent, REQUEST_IMAGE_CAPTURE);
startActivityForResult(call, takePictureIntent, "processCameraImage");
} else {
call.reject(NO_CAMERA_ACTIVITY_ERROR);
}
Expand All @@ -246,11 +250,12 @@ public void openPhotos(final PluginCall call) {
if (checkPhotosPermissions(call)) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(call, intent, REQUEST_IMAGE_PICK);
startActivityForResult(call, intent, "processPickedImage");
}
}

public void processCameraImage(PluginCall call) {
@ActivityCallback
public void processCameraImage(PluginCall call, ActivityResult result) {
if (imageFileSavePath == null) {
call.reject(IMAGE_PROCESS_NO_FILE_ERROR);
return;
Expand All @@ -269,7 +274,9 @@ public void processCameraImage(PluginCall call) {
returnResult(call, bitmap, contentUri);
}

public void processPickedImage(PluginCall call, Intent data) {
@ActivityCallback
public void processPickedImage(PluginCall call, ActivityResult result) {
Intent data = result.getData();
if (data == null) {
call.reject("No image picked");
return;
Expand Down Expand Up @@ -304,6 +311,12 @@ public void processPickedImage(PluginCall call, Intent data) {
}
}

@ActivityCallback
private void processEditedImage(PluginCall call, ActivityResult result) {
isEdited = true;
processPickedImage(call, result);
}

/**
* Save the modified image we've created to a temporary location, so we can
* return a URI to it later
Expand Down Expand Up @@ -483,12 +496,12 @@ public void requestPermissions(PluginCall call) {
permsList = providedPerms.toList();
} catch (JSONException e) {}

if (permsList != null && permsList.size() == 1 && permsList.contains("camera")) {
if (permsList != null && permsList.size() == 1 && permsList.contains(CAMERA)) {
// the only thing being asked for was the camera so we can just return the current state
checkPermissions(call);
} else {
// we need to ask about photos so request storage permissions
requestPermissionForAlias("photos", call);
requestPermissionForAlias(PHOTOS, call, "checkPermissions");
}
}
}
Expand All @@ -499,47 +512,25 @@ public Map<String, PermissionState> getPermissionStates() {

// If Camera is not in the manifest and therefore not required, say the permission is granted
if (!hasDefinedPermissions(new String[] { Manifest.permission.CAMERA })) {
permissionStates.put("camera", PermissionState.GRANTED);
permissionStates.put(CAMERA, PermissionState.GRANTED);
}

return permissionStates;
}

@Override
protected void handleOnActivityResult(PluginCall savedCall, int requestCode, int resultCode, Intent data) {
if (savedCall == null) {
return;
}

settings = getSettings(savedCall);

if (requestCode == REQUEST_IMAGE_CAPTURE) {
processCameraImage(savedCall);
} else if (requestCode == REQUEST_IMAGE_PICK) {
processPickedImage(savedCall, data);
} else if (requestCode == REQUEST_IMAGE_EDIT && resultCode == Activity.RESULT_OK) {
isEdited = true;
processPickedImage(savedCall, data);
} else if (resultCode == Activity.RESULT_CANCELED && imageFileSavePath != null) {
imageEditedFileSavePath = null;
isEdited = true;
processCameraImage(savedCall);
}
}

private void editImage(PluginCall call, Bitmap bitmap, Uri uri, ByteArrayOutputStream bitmapOutputStream) {
Uri origPhotoUri = uri;
if (imageFileUri != null) {
origPhotoUri = imageFileUri;
}
try {
Intent editIntent = createEditIntent(origPhotoUri, false);
startActivityForResult(call, editIntent, REQUEST_IMAGE_EDIT);
startActivityForResult(call, editIntent, "processEditedImage");
} catch (SecurityException ex) {
Uri tempImage = getTempImage(bitmap, uri, bitmapOutputStream);
Intent editIntent = createEditIntent(tempImage, true);
if (editIntent != null) {
startActivityForResult(call, editIntent, REQUEST_IMAGE_EDIT);
startActivityForResult(call, editIntent, "processEditedImage");
} else {
call.reject(IMAGE_EDIT_ERROR);
}
Expand Down
Loading

0 comments on commit f671b9f

Please sign in to comment.