Skip to content

Commit

Permalink
Port Environment.isExternalStorageManager (#1218)
Browse files Browse the repository at this point in the history
  • Loading branch information
JeroenWeener authored Nov 15, 2023
1 parent 05f587a commit 40e41a2
Show file tree
Hide file tree
Showing 9 changed files with 263 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.baseflow.permissionhandler;

import android.os.Build;
import android.os.Environment;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

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

import io.flutter.plugin.common.BinaryMessenger;

/**
* Host API implementation for `Environment`.
*
* <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 EnvironmentHostApiImpl implements EnvironmentHostApi {
// To ease adding additional methods, this value is added prematurely.
@SuppressWarnings({"unused", "FieldCanBeLocal"})
private final BinaryMessenger binaryMessenger;

// To ease adding additional methods, this value is added prematurely.
@SuppressWarnings({"unused", "FieldCanBeLocal"})
private final InstanceManager instanceManager;

/**
* Constructs an {@link EnvironmentHostApiImpl}.
*
* @param binaryMessenger used to communicate with Dart over asynchronous messages
* @param instanceManager maintains instances stored to communicate with attached Dart objects
*/
public EnvironmentHostApiImpl(
@NonNull BinaryMessenger binaryMessenger,
@NonNull InstanceManager instanceManager
) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
}

@RequiresApi(api = Build.VERSION_CODES.R)
@NonNull
@Override
public Boolean isExternalStorageManager() {
return Environment.isExternalStorageManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1516,4 +1516,58 @@ public void dispose(@NonNull String instanceIdArg, @NonNull Reply<Void> callback
channelReply -> callback.reply(null));
}
}
/**
* Host API for `Environment`.
*
* 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.
*
* See https://developer.android.com/reference/android/os/Environment.
*
* Generated interface from Pigeon that represents a handler of messages from Flutter.
*/
public interface EnvironmentHostApi {
/**
* Returns whether the calling app has All Files Access on the primary shared/external storage media.
*
* Declaring the permission [Manifest.permission.manageExternalStorage] is
* not enough to gain the access. To request access, use
* [Settings.actionManageAppAllFilesAccessPermission].
*
* See https://developer.android.com/reference/android/os/Environment#isExternalStorageManager().
*/
@NonNull
Boolean isExternalStorageManager();

/** The codec used by EnvironmentHostApi. */
static @NonNull MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
}
/**Sets up an instance of `EnvironmentHostApi` to handle messages through the `binaryMessenger`. */
static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable EnvironmentHostApi api) {
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.permission_handler_android.EnvironmentHostApi.isExternalStorageManager", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
try {
Boolean output = api.isExternalStorageManager();
wrapped.add(0, output);
}
catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.baseflow.permissionhandler.PermissionHandlerPigeon.AlarmManagerHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.BuildVersionHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.ContextHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.EnvironmentHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.IntentHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.NotificationManagerHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.PackageManagerHostApi;
Expand Down Expand Up @@ -81,6 +82,9 @@ private void setUp(
final NotificationManagerHostApi notificationManagerHostApi = new NotificationManagerHostApiImpl(binaryMessenger, instanceManager);
NotificationManagerHostApi.setup(binaryMessenger, notificationManagerHostApi);

final EnvironmentHostApi environmentHostApi = new EnvironmentHostApiImpl(binaryMessenger, instanceManager);
EnvironmentHostApi.setup(binaryMessenger, environmentHostApi);

activityFlutterApi = new ActivityFlutterApiImpl(binaryMessenger, instanceManager);
activityHostApi = new ActivityHostApiImpl(
binaryMessenger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export 'src/android_object_mirrors/activity.dart';
export 'src/android_object_mirrors/alarm_manager.dart';
export 'src/android_object_mirrors/build.dart';
export 'src/android_object_mirrors/context.dart';
export 'src/android_object_mirrors/environment.dart';
export 'src/android_object_mirrors/intent.dart';
export 'src/android_object_mirrors/manifest.dart';
export 'src/android_object_mirrors/notification_manager.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import '../permission_handler.pigeon.dart';

/// Provides access to environment variables.
///
/// See https://developer.android.com/reference/android/os/Environment.
class Environment {
const Environment._();

static final EnvironmentHostApi _hostApi = EnvironmentHostApi();

/// Returns whether the calling app has All Files Access on the primary shared/external storage media.
///
/// Declaring the permission [Manifest.permission.manageExternalStorage] is
/// not enough to gain the access. To request access, use
/// [Settings.actionManageAppAllFilesAccessPermission].
///
/// See https://developer.android.com/reference/android/os/Environment#isExternalStorageManager().
static Future<bool> isExternalStorageManager() {
return _hostApi.isExternalStorageManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -730,3 +730,22 @@ class NotificationManagerFlutterApiImpl extends NotificationManagerFlutterApi {
_instanceManager.remove(instanceId);
}
}

/// Host API implementation of Environment.
class EnvironmentHostApiImpl extends EnvironmentHostApi {
/// Creates a new instance of [EnvironmentHostApiImpl].
EnvironmentHostApiImpl({
this.binaryMessenger,
InstanceManager? instanceManager,
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
super(binaryMessenger: binaryMessenger);

/// Sends binary data across the Flutter platform barrier.
///
/// If it is null, the default BinaryMessenger will be used which routes to
/// the host platform.
final BinaryMessenger? binaryMessenger;

/// Maintains instances stored to communicate with native language objects.
final InstanceManager instanceManager;
}
52 changes: 52 additions & 0 deletions permission_handler_android/lib/src/permission_handler.pigeon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1347,3 +1347,55 @@ abstract class NotificationManagerFlutterApi {
}
}
}

/// Host API for `Environment`.
///
/// 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.
///
/// See https://developer.android.com/reference/android/os/Environment.
class EnvironmentHostApi {
/// Constructor for [EnvironmentHostApi]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
EnvironmentHostApi({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;

static const MessageCodec<Object?> codec = StandardMessageCodec();

/// Returns whether the calling app has All Files Access on the primary shared/external storage media.
///
/// Declaring the permission [Manifest.permission.manageExternalStorage] is
/// not enough to gain the access. To request access, use
/// [Settings.actionManageAppAllFilesAccessPermission].
///
/// See https://developer.android.com/reference/android/os/Environment#isExternalStorageManager().
Future<bool> isExternalStorageManager() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.permission_handler_android.EnvironmentHostApi.isExternalStorageManager',
codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as bool?)!;
}
}
}
19 changes: 19 additions & 0 deletions permission_handler_android/pigeons/android_permission_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,22 @@ abstract class NotificationManagerFlutterApi {
/// Dispose of the Dart instance and remove it from the `InstanceManager`.
void dispose(String instanceId);
}

/// Host API for `Environment`.
///
/// 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.
///
/// See https://developer.android.com/reference/android/os/Environment.
@HostApi(dartHostTestHandler: 'EnvironmentTestHostApi')
abstract class EnvironmentHostApi {
/// Returns whether the calling app has All Files Access on the primary shared/external storage media.
///
/// Declaring the permission [Manifest.permission.manageExternalStorage] is
/// not enough to gain the access. To request access, use
/// [Settings.actionManageAppAllFilesAccessPermission].
///
/// See https://developer.android.com/reference/android/os/Environment#isExternalStorageManager().
bool isExternalStorageManager();
}
Original file line number Diff line number Diff line change
Expand Up @@ -909,3 +909,47 @@ abstract class NotificationManagerTestHostApi {
}
}
}

/// Host API for `Environment`.
///
/// 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.
///
/// See https://developer.android.com/reference/android/os/Environment.
abstract class EnvironmentTestHostApi {
static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
TestDefaultBinaryMessengerBinding.instance;
static const MessageCodec<Object?> codec = StandardMessageCodec();

/// Returns whether the calling app has All Files Access on the primary shared/external storage media.
///
/// Declaring the permission [Manifest.permission.manageExternalStorage] is
/// not enough to gain the access. To request access, use
/// [Settings.actionManageAppAllFilesAccessPermission].
///
/// See https://developer.android.com/reference/android/os/Environment#isExternalStorageManager().
bool isExternalStorageManager();

static void setup(EnvironmentTestHostApi? api,
{BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.permission_handler_android.EnvironmentHostApi.isExternalStorageManager',
codec,
binaryMessenger: binaryMessenger);
if (api == null) {
_testBinaryMessengerBinding!.defaultBinaryMessenger
.setMockDecodedMessageHandler<Object?>(channel, null);
} else {
_testBinaryMessengerBinding!.defaultBinaryMessenger
.setMockDecodedMessageHandler<Object?>(channel,
(Object? message) async {
// ignore message
final bool output = api.isExternalStorageManager();
return <Object?>[output];
});
}
}
}
}

0 comments on commit 40e41a2

Please sign in to comment.