Skip to content

Commit

Permalink
Refactor: Port startActivityForResult (Android) (#1209)
Browse files Browse the repository at this point in the history
* Port Android `Manifest.permission` and `Manifest.permission_group` (#1196)

* Port `Manifest.permission` and `Manifest.permission_group`

* Use Dart conventions for `Manifest` variables

* Implement `checkPermissionStatus`

* Change entry point of getting an `Activity`, implement `requestPermission`

* Expose `requestCode`

* Update tests

* Update main.dart

* Update CHANGELOG.md

* Elaborate on concern

* Replace `AndroidActivity` with `ActivityAware`

* Delete test

* Apply small fixes

* Elaborate on missing Android activity

* Regenerate pigeon files

* Make small adjustments based on review

* Update documentation

* Update documentation

* Implement `Settings` mirror

* Implement `Uri` mirror

* Add `Intent` constructor and update `Uri` implementation

* Implement `Intent` methods

* Implement `startActivity`, `getPackageName` for `Context`

* Copy new `Context` methods to `Activity`

* Implement `openAppSettings` in `PermissionHandlerAndroid`

* Follow-up changes

* Run `dart format .`

* Add `startActivityForResult`

* Add actions to `Settings`

* Update TODOs

* Run `dart format .`

* Remove duplicate methods

* Expose optional `requestCode` for permission requests
  • Loading branch information
JeroenWeener authored Nov 9, 2023
1 parent ee07c08 commit 8e4488b
Show file tree
Hide file tree
Showing 11 changed files with 598 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package com.baseflow.permissionhandler;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;

import com.baseflow.instancemanager.InstanceManager;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import io.flutter.plugin.common.BinaryMessenger;
Expand All @@ -24,14 +26,26 @@
* <p>This class may handle instantiating and adding native object instances that are attached to a
* Dart instance or handle method calls on the associated native class or an instance of the class.
*/
public class ActivityHostApiImpl implements ActivityHostApi, PluginRegistry.RequestPermissionsResultListener {
public class ActivityHostApiImpl implements
ActivityHostApi,
PluginRegistry.RequestPermissionsResultListener,
PluginRegistry.ActivityResultListener {

/**
* The request code used when requesting permissions.
* The default request code used when requesting permissions.
*
* <p>This code has been randomly generated once, in the hope of avoiding collisions with other
* request codes that are used on the native side, such as by other plugins.
*/
static final int REQUEST_CODE = 702764314;
static final int DEFAULT_REQUEST_CODE_PERMISSIONS = 702764314;

/**
* The default request code used when requesting special permissions.
*
* <p>This code has been randomly generated once, in the hope of avoiding collisions with other
* request codes that are used on the native side, such as by other plugins.
*/
static final int DEFAULT_REQUEST_CODE_ACTIVITY_FOR_RESULT = 834370754;

// To ease adding additional methods, this value is added prematurely.
@SuppressWarnings({"unused", "FieldCanBeLocal"})
Expand All @@ -40,12 +54,20 @@ public class ActivityHostApiImpl implements ActivityHostApi, PluginRegistry.Requ
private final InstanceManager instanceManager;

/**
* A callback to complete a pending permission request.
* Callbacks to complete a pending permission request.
* <p>
* These callbacks are set in {@link this#requestPermissions(String, List, Long, Result)}, and
* are completed in {@link this#onRequestPermissionsResult(int, String[], int[])}.
*/
private final Map<Integer, Result<PermissionRequestResult>> pendingPermissionsRequestMap = new HashMap<>();

/**
* Callback to complete a pending activity-for-result request.
* <p>
* This callback is set in {@link this#requestPermissions(String, List, Result)}, and completed
* in {@link this#onRequestPermissionsResult(int, String[], int[])}.
* These callbacks are set in {@link this#startActivityForResult(String, String, Long, Result)},
* and are completed in {@link this#onActivityResult(int, int, Intent)}.
*/
private Result<PermissionRequestResult> pendingRequest;
private final Map<Integer, Result<ActivityResultPigeon>> pendingActivityResultRequestMap = new HashMap<>();

/**
* Constructs an {@link ActivityHostApiImpl}.
Expand All @@ -68,9 +90,7 @@ public ActivityHostApiImpl(
) {
final UUID activityInstanceUuid = UUID.fromString(activityInstanceId);
final Activity activity = instanceManager.getInstance(activityInstanceUuid);
if (activity == null) {
throw new ActivityNotFoundException();
}

return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}

Expand All @@ -81,33 +101,35 @@ public ActivityHostApiImpl(
) {
final UUID activityInstanceUuid = UUID.fromString(activityInstanceId);
final Activity activity = instanceManager.getInstance(activityInstanceUuid);
if (activity == null) {
throw new ActivityNotFoundException();
}

return (long) ActivityCompat.checkSelfPermission(activity, permission);
}

@Override
public void requestPermissions(
@NonNull String activityInstanceId,
@NonNull List<String> permissions,
@Nullable Long requestCode,
@NonNull Result<PermissionRequestResult> result
) {
final UUID activityInstanceUuid = UUID.fromString(activityInstanceId);
final Activity activity = instanceManager.getInstance(activityInstanceUuid);
if (activity == null) {
throw new ActivityNotFoundException();
}

pendingRequest = result;
int requestCodeInt = requestCode == null ? DEFAULT_REQUEST_CODE_PERMISSIONS : requestCode.intValue();
pendingPermissionsRequestMap.put(requestCodeInt, result);

String[] permissionsArray = permissions.toArray(new String[0]);
ActivityCompat.requestPermissions(activity, permissionsArray, REQUEST_CODE);
ActivityCompat.requestPermissions(activity, permissionsArray, requestCodeInt);
}

@Override
public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode != REQUEST_CODE) {
public boolean onRequestPermissionsResult(
int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults
) {
@Nullable final Result<PermissionRequestResult> pendingPermissionsRequest = pendingPermissionsRequestMap.get(requestCode);
if (pendingPermissionsRequest == null) {
return false;
}

Expand All @@ -118,11 +140,13 @@ public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] per
}
final PermissionRequestResult result = new PermissionRequestResult
.Builder()
.setRequestCode((long) requestCode)
.setPermissions(permissionsList)
.setGrantResults(grantResultsList)
.build();

pendingRequest.success(result);
pendingPermissionsRequest.success(result);
pendingPermissionsRequestMap.remove(requestCode);

return true;
}
Expand Down Expand Up @@ -150,4 +174,49 @@ public void startActivity(

return activity.getPackageName();
}

@Override
public void startActivityForResult(
@NonNull String instanceId,
@NonNull String intentInstanceId,
@Nullable Long requestCode,
@NonNull Result<ActivityResultPigeon> result
) {
final UUID instanceUuid = UUID.fromString(instanceId);
final UUID intentInstanceUuid = UUID.fromString(intentInstanceId);

final Activity activity = instanceManager.getInstance(instanceUuid);
final Intent intent = instanceManager.getInstance(intentInstanceUuid);

int requestCodeInt = requestCode == null ? DEFAULT_REQUEST_CODE_ACTIVITY_FOR_RESULT : requestCode.intValue();
pendingActivityResultRequestMap.put(requestCodeInt, result);

activity.startActivityForResult(intent, requestCodeInt);
}

@Override
public boolean onActivityResult(
int requestCode,
int resultCode,
@Nullable Intent data
) {
@Nullable final Result<ActivityResultPigeon> pendingActivityResultRequest = pendingActivityResultRequestMap.get(requestCode);
if (pendingActivityResultRequest == null) {
return false;
}

final ActivityResultPigeon.Builder activityResultBuilder = new ActivityResultPigeon.Builder()
.setRequestCode((long) requestCode)
.setResultCode((long) resultCode);

if (data != null) {
final UUID intentInstanceId = instanceManager.addHostCreatedInstance(data);
activityResultBuilder.setDataInstanceId(intentInstanceId.toString());
}

pendingActivityResultRequest.success(activityResultBuilder.build());
pendingActivityResultRequestMap.remove(requestCode);

return true;
}
}
Loading

0 comments on commit 8e4488b

Please sign in to comment.