Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Port canScheduleExactAlarms (Android) #1214

Merged
merged 40 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
1c1b15f
Port Android `Manifest.permission` and `Manifest.permission_group` (#…
JeroenWeener Oct 19, 2023
4e920f1
Implement `checkPermissionStatus`
JeroenWeener Oct 20, 2023
19feb05
Change entry point of getting an `Activity`, implement `requestPermis…
JeroenWeener Oct 25, 2023
0b6355d
Expose `requestCode`
JeroenWeener Oct 25, 2023
8cbc4ca
Update tests
JeroenWeener Oct 26, 2023
ae7af45
Update main.dart
JeroenWeener Oct 26, 2023
1dfee64
Update CHANGELOG.md
JeroenWeener Oct 26, 2023
81ad104
Elaborate on concern
JeroenWeener Oct 26, 2023
96a88f4
Replace `AndroidActivity` with `ActivityAware`
JeroenWeener Oct 31, 2023
5c2c915
Delete test
JeroenWeener Nov 1, 2023
23846f2
Apply small fixes
JeroenWeener Nov 1, 2023
543e547
Elaborate on missing Android activity
JeroenWeener Nov 1, 2023
f8ee5e5
Regenerate pigeon files
JeroenWeener Nov 1, 2023
99bc174
Make small adjustments based on review
JeroenWeener Nov 3, 2023
1a4fe07
Update documentation
JeroenWeener Nov 3, 2023
56f0d43
Update documentation
JeroenWeener Nov 3, 2023
2eefb81
Implement `Settings` mirror
JeroenWeener Nov 1, 2023
2074f42
Implement `Uri` mirror
JeroenWeener Nov 2, 2023
272e092
Add `Intent` constructor and update `Uri` implementation
JeroenWeener Nov 2, 2023
9448940
Implement `Intent` methods
JeroenWeener Nov 2, 2023
508a0b6
Implement `startActivity`, `getPackageName` for `Context`
JeroenWeener Nov 3, 2023
d005fdd
Copy new `Context` methods to `Activity`
JeroenWeener Nov 3, 2023
9353a62
Implement `openAppSettings` in `PermissionHandlerAndroid`
JeroenWeener Nov 3, 2023
39f8fd2
Follow-up changes
JeroenWeener Nov 3, 2023
0e6f860
Run `dart format .`
JeroenWeener Nov 3, 2023
11163cc
Add `startActivityForResult`
JeroenWeener Nov 3, 2023
d218197
Add actions to `Settings`
JeroenWeener Nov 3, 2023
c234ddc
Update TODOs
JeroenWeener Nov 3, 2023
2810bcb
Run `dart format .`
JeroenWeener Nov 3, 2023
5fc9de2
Implement `getSystemService`
JeroenWeener Nov 3, 2023
c8044f0
Merge remote-tracking branch 'upstream/next' into feature/check-permi…
JeroenWeener Nov 6, 2023
4e7c5a3
Add `Build`
JeroenWeener Nov 6, 2023
62ebe6c
Implement `PowerManager`
JeroenWeener Nov 6, 2023
e0e8258
Merge remote-tracking branch 'upstream/next' into feature/check-permi…
JeroenWeener Nov 7, 2023
bcabe3b
Fix bug with `PowerManager`, update `PermissionHandlerAndroid`
JeroenWeener Nov 7, 2023
35f6d9a
Run `dart format .`
JeroenWeener Nov 7, 2023
782b09f
Add sdk check to `isIgnoringBatteryOptimizations`
JeroenWeener Nov 7, 2023
6004d9c
Merge remote-tracking branch 'upstream/next' into feature/schedule-ex…
JeroenWeener Nov 9, 2023
e3b6fd9
Implement `AlarmManager`
JeroenWeener Nov 9, 2023
787d966
Merge remote-tracking branch 'upstream/next' into feature/schedule-ex…
JeroenWeener Nov 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading