Skip to content

Commit

Permalink
Refactor: Port canScheduleExactAlarms (Android) (#1214)
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 .`

* Implement `getSystemService`

* Add `Build`

* Implement `PowerManager`

* Fix bug with `PowerManager`, update `PermissionHandlerAndroid`

* Run `dart format .`

* Add sdk check to `isIgnoringBatteryOptimizations`

* Implement `AlarmManager`
  • Loading branch information
JeroenWeener authored Nov 9, 2023
1 parent b1bf5fc commit 84ac0f9
Show file tree
Hide file tree
Showing 14 changed files with 872 additions and 180 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.baseflow.permissionhandler;

import android.app.Activity;
import android.app.AlarmManager;
import android.content.Intent;
import android.os.PowerManager;

Expand Down Expand Up @@ -56,6 +57,8 @@ public class ActivityHostApiImpl implements

private final PowerManagerFlutterApiImpl powerManagerFlutterApi;

private final AlarmManagerFlutterApiImpl alarmManagerFlutterApi;

/**
* Callbacks to complete a pending permission request.
* <p>
Expand All @@ -80,9 +83,11 @@ public class ActivityHostApiImpl implements
*/
public ActivityHostApiImpl(
@NonNull PowerManagerFlutterApiImpl powerManagerFlutterApi,
@NonNull AlarmManagerFlutterApiImpl alarmManagerFlutterApi,
@NonNull BinaryMessenger binaryMessenger,
@NonNull InstanceManager instanceManager
) {
this.alarmManagerFlutterApi = alarmManagerFlutterApi;
this.powerManagerFlutterApi = powerManagerFlutterApi;
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
Expand Down Expand Up @@ -237,6 +242,8 @@ public boolean onActivityResult(

if (systemService instanceof PowerManager) {
powerManagerFlutterApi.create((PowerManager) systemService);
} else if (systemService instanceof AlarmManager) {
alarmManagerFlutterApi.create((AlarmManager) systemService);
}

final UUID systemServiceUuid = instanceManager.getIdentifierForStrongReference(systemService);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.baseflow.permissionhandler;

import android.app.AlarmManager;

import androidx.annotation.NonNull;

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

import java.util.UUID;

import io.flutter.plugin.common.BinaryMessenger;

/**
* Flutter API implementation for `AlarmManager`.
*
* <p>This class may handle adding native instances that are attached to a Dart instance or passing
* arguments of callbacks methods to a Dart instance.
*/
public class AlarmManagerFlutterApiImpl {
// To ease adding additional methods, this value is added prematurely.
@SuppressWarnings({"unused", "FieldCanBeLocal"})
private final BinaryMessenger binaryMessenger;

private final InstanceManager instanceManager;

private final AlarmManagerFlutterApi api;

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

/**
* Stores the `AlarmManager` instance and notifies Dart to create and store a new `AlarmManager`
* instance that is attached to this one. If `instance` has already been added, this method does
* nothing.
*/
public void create(@NonNull AlarmManager instance) {
if (!instanceManager.containsInstance(instance)) {
final UUID alarmManagerInstanceUuid = instanceManager.addHostCreatedInstance(instance);
api.create(alarmManagerInstanceUuid.toString(), reply -> {});
}
}

/**
* Disposes of the `AlarmManager` instance in the instance manager and notifies Dart to do the
* same. If `instance` was already disposed, this method does nothing.
*/
public void dispose(AlarmManager instance) {
final UUID alarmManagerInstanceUuid = instanceManager.getIdentifierForStrongReference(instance);
if (alarmManagerInstanceUuid != null) {
api.dispose(alarmManagerInstanceUuid.toString(), reply -> {});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.baseflow.permissionhandler;

import android.os.Build;
import android.app.AlarmManager;

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

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

import java.util.UUID;

import io.flutter.plugin.common.BinaryMessenger;

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

private final InstanceManager instanceManager;

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

@RequiresApi(api = Build.VERSION_CODES.S)
@NonNull
@Override
public Boolean canScheduleExactAlarms(@NonNull String instanceId) {
final UUID instanceUuid = UUID.fromString(instanceId);
final AlarmManager alarmManager = instanceManager.getInstance(instanceUuid);

return alarmManager.canScheduleExactAlarms();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.baseflow.permissionhandler;

import android.app.AlarmManager;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
Expand Down Expand Up @@ -29,6 +30,8 @@ public class ContextHostApiImpl implements ContextHostApi {

private final PowerManagerFlutterApiImpl powerManagerFlutterApi;

private final AlarmManagerFlutterApiImpl alarmManagerFlutterApi;

/**
* Constructs an {@link ContextHostApiImpl}.
*
Expand All @@ -37,10 +40,12 @@ public class ContextHostApiImpl implements ContextHostApi {
*/
public ContextHostApiImpl(
@NonNull PowerManagerFlutterApiImpl powerManagerFlutterApi,
@NonNull AlarmManagerFlutterApiImpl alarmManagerFlutterApi,
@NonNull BinaryMessenger binaryMessenger,
@NonNull InstanceManager instanceManager
) {
this.powerManagerFlutterApi = powerManagerFlutterApi;
this.alarmManagerFlutterApi = alarmManagerFlutterApi;
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
}
Expand Down Expand Up @@ -92,6 +97,8 @@ public void startActivity(

if (systemService instanceof PowerManager) {
powerManagerFlutterApi.create((PowerManager) systemService);
} else if (systemService instanceof AlarmManager) {
alarmManagerFlutterApi.create((AlarmManager) systemService);
}

final UUID systemServiceUuid = instanceManager.getIdentifierForStrongReference(systemService);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1225,4 +1225,102 @@ static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable BuildVersi
}
}
}
/**
* Host API for `AlarmManager`.
*
* 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/app/AlarmManager.
*
* Generated interface from Pigeon that represents a handler of messages from Flutter.
*/
public interface AlarmManagerHostApi {
/**
* Called to check if the application can schedule exact alarms.
*
* See https://developer.android.com/reference/android/app/AlarmManager#canScheduleExactAlarms().
*/
@NonNull
Boolean canScheduleExactAlarms(@NonNull String instanceId);

/** The codec used by AlarmManagerHostApi. */
static @NonNull MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
}
/**Sets up an instance of `AlarmManagerHostApi` to handle messages through the `binaryMessenger`. */
static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable AlarmManagerHostApi api) {
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.permission_handler_android.AlarmManagerHostApi.canScheduleExactAlarms", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
ArrayList<Object> args = (ArrayList<Object>) message;
String instanceIdArg = (String) args.get(0);
try {
Boolean output = api.canScheduleExactAlarms(instanceIdArg);
wrapped.add(0, output);
}
catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
}
}
/**
* Flutter API for `AlarmManager`.
*
* This class may handle instantiating and adding Dart instances that are
* attached to a native instance or receiving callback methods from an
* overridden native class.
*
* See https://developer.android.com/reference/android/app/AlarmManager.
*
* Generated class from Pigeon that represents Flutter messages that can be called from Java.
*/
public static class AlarmManagerFlutterApi {
private final @NonNull BinaryMessenger binaryMessenger;

public AlarmManagerFlutterApi(@NonNull BinaryMessenger argBinaryMessenger) {
this.binaryMessenger = argBinaryMessenger;
}

/** Public interface for sending reply. */
@SuppressWarnings("UnknownNullness")
public interface Reply<T> {
void reply(T reply);
}
/** The codec used by AlarmManagerFlutterApi. */
static @NonNull MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
}
/** Create a new Dart instance and add it to the `InstanceManager`. */
public void create(@NonNull String instanceIdArg, @NonNull Reply<Void> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.permission_handler_android.AlarmManagerFlutterApi.create", getCodec());
channel.send(
new ArrayList<Object>(Collections.singletonList(instanceIdArg)),
channelReply -> callback.reply(null));
}
/** Dispose of the Dart instance and remove it from the `InstanceManager`. */
public void dispose(@NonNull String instanceIdArg, @NonNull Reply<Void> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.permission_handler_android.AlarmManagerFlutterApi.dispose", getCodec());
channel.send(
new ArrayList<Object>(Collections.singletonList(instanceIdArg)),
channelReply -> callback.reply(null));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.baseflow.instancemanager.InstanceManagerPigeon.InstanceManagerHostApi;
import com.baseflow.instancemanager.JavaObjectHostApiImpl;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.ActivityHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.AlarmManagerHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.BuildVersionHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.ContextHostApi;
import com.baseflow.permissionhandler.PermissionHandlerPigeon.IntentHostApi;
Expand Down Expand Up @@ -62,9 +63,14 @@ private void setUp(
final PowerManagerHostApi powerManagerHostApi = new PowerManagerHostApiImpl(binaryMessenger, instanceManager);
PowerManagerHostApi.setup(binaryMessenger, powerManagerHostApi);

final AlarmManagerFlutterApiImpl alarmManagerFlutterApi = new AlarmManagerFlutterApiImpl(binaryMessenger, instanceManager);
final AlarmManagerHostApi alarmManagerHostApi = new AlarmManagerHostApiImpl(binaryMessenger, instanceManager);
AlarmManagerHostApi.setup(binaryMessenger, alarmManagerHostApi);

activityFlutterApi = new ActivityFlutterApiImpl(binaryMessenger, instanceManager);
activityHostApi = new ActivityHostApiImpl(
powerManagerFlutterApi,
alarmManagerFlutterApi,
binaryMessenger,
instanceManager
);
Expand All @@ -73,6 +79,7 @@ private void setUp(
contextFlutterApi = new ContextFlutterApiImpl(binaryMessenger, instanceManager);
final ContextHostApiImpl contextHostApi = new ContextHostApiImpl(
powerManagerFlutterApi,
alarmManagerFlutterApi,
binaryMessenger,
instanceManager
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
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/intent.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ class Activity extends JavaObject {

final ActivityHostApiImpl _hostApi;

/// Use with [Context.getSystemService] to retrieve a [PowerManager] for
/// controlling power management, including "wake locks," which let you keep
/// the device on while you're running long tasks.
static const String powerService = 'power';

/// Use with [Context.getSystemService] to retrieve an [AlarmManager] for
/// receiving intents at a time of your choosing.
static const String alarmService = 'alarm';

/// Standard activity result: operation succeeded.
///
/// Constant Value: -1 (0xffffffff).
Expand Down
Loading

0 comments on commit 84ac0f9

Please sign in to comment.