diff --git a/example/lib/main.dart b/example/lib/main.dart index 531b21e..f28738d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -271,6 +271,21 @@ class MyHomePageState extends State { }, child: const Text('Get cache directory'), ), + ElevatedButton( + onPressed: () async { + // ignore: avoid_print + print(await MoxplatformPlugin.platform + .isIgnoringBatteryOptimizations()); + }, + child: const Text('Is battery optimised?'), + ), + ElevatedButton( + onPressed: () async { + await MoxplatformPlugin.platform + .openBatteryOptimisationSettings(); + }, + child: const Text('Open battery optimisation page'), + ), ], ), ), diff --git a/packages/moxplatform_android/android/src/main/AndroidManifest.xml b/packages/moxplatform_android/android/src/main/AndroidManifest.xml index 4626f0e..e2b99f2 100644 --- a/packages/moxplatform_android/android/src/main/AndroidManifest.xml +++ b/packages/moxplatform_android/android/src/main/AndroidManifest.xml @@ -1,15 +1,16 @@ - + - - + + + wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.openBatteryOptimisationSettings", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + api.openBatteryOptimisationSettings(); + wrapped.add(0, null); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.isIgnoringBatteryOptimizations", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isIgnoringBatteryOptimizations(); + wrapped.add(0, output); + } catch (Throwable exception) { ArrayList wrappedError = wrapError(exception); wrapped = wrappedError; diff --git a/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Constants.kt b/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Constants.kt index edd0eef..8866fb0 100644 --- a/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Constants.kt +++ b/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Constants.kt @@ -25,7 +25,7 @@ const val NOTIFICATION_EXTRA_ID_KEY = "notification_id" const val NOTIFICATION_MESSAGE_EXTRA_MIME = "mime" const val NOTIFICATION_MESSAGE_EXTRA_PATH = "path" -const val MOXPLATFORM_FILEPROVIDER_ID = "me.polynom.moxplatform_android.fileprovider" +const val MOXPLATFORM_FILEPROVIDER_ID = "me.polynom.moxplatform_android.fileprovider2" // Shared preferences keys const val SHARED_PREFERENCES_KEY = "me.polynom.moxplatform_android" diff --git a/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/MoxplatformAndroidPlugin.java b/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/MoxplatformAndroidPlugin.java index 664b7ea..2bcdea0 100644 --- a/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/MoxplatformAndroidPlugin.java +++ b/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/MoxplatformAndroidPlugin.java @@ -1,6 +1,8 @@ package me.polynom.moxplatform_android; +import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS; import static androidx.core.content.ContextCompat.getSystemService; +import static androidx.core.content.ContextCompat.startActivity; import static me.polynom.moxplatform_android.ConstantsKt.SHARED_PREFERENCES_KEY; import static me.polynom.moxplatform_android.CryptoKt.*; import static me.polynom.moxplatform_android.RecordSentMessageKt.*; @@ -15,6 +17,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.net.Uri; +import android.os.PowerManager; import android.util.Log; import androidx.annotation.NonNull; @@ -257,6 +261,22 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt return context.getCacheDir().getPath(); } + @Override + public void openBatteryOptimisationSettings() { + final Uri packageUri = Uri.parse("package:" + context.getPackageName()); + Log.d(TAG, packageUri.toString()); + final Intent intent = new Intent(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, packageUri); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + @NonNull + @Override + public Boolean isIgnoringBatteryOptimizations() { + final PowerManager pm = context.getSystemService(PowerManager.class); + return pm.isIgnoringBatteryOptimizations(context.getPackageName()); + } + @Override public void recordSentMessage(@NonNull String name, @NonNull String jid, @Nullable String avatarPath, @NonNull FallbackIconType fallbackIcon) { systemRecordSentMessage(context, name, jid, avatarPath, fallbackIcon); diff --git a/packages/moxplatform_android/lib/src/platform_android.dart b/packages/moxplatform_android/lib/src/platform_android.dart index 7d3c28e..51e0cc2 100644 --- a/packages/moxplatform_android/lib/src/platform_android.dart +++ b/packages/moxplatform_android/lib/src/platform_android.dart @@ -10,4 +10,14 @@ class AndroidPlatformImplementation extends PlatformImplementation { Future getPersistentDataPath() { return MoxplatformInterface.api.getPersistentDataPath(); } + + @override + Future isIgnoringBatteryOptimizations() { + return MoxplatformInterface.api.isIgnoringBatteryOptimizations(); + } + + @override + Future openBatteryOptimisationSettings() { + return MoxplatformInterface.api.openBatteryOptimisationSettings(); + } } diff --git a/packages/moxplatform_platform_interface/lib/src/api.g.dart b/packages/moxplatform_platform_interface/lib/src/api.g.dart index 81ecb15..4ea730e 100644 --- a/packages/moxplatform_platform_interface/lib/src/api.g.dart +++ b/packages/moxplatform_platform_interface/lib/src/api.g.dart @@ -583,6 +583,55 @@ class MoxplatformApi { } } + Future openBatteryOptimisationSettings() async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.openBatteryOptimisationSettings', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; + 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 { + return; + } + } + + Future isIgnoringBatteryOptimizations() async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.isIgnoringBatteryOptimizations', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; + 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?)!; + } + } + /// Contacts APIs Future recordSentMessage(String arg_name, String arg_jid, String? arg_avatarPath, FallbackIconType arg_fallbackIcon) async { diff --git a/packages/moxplatform_platform_interface/lib/src/platform b/packages/moxplatform_platform_interface/lib/src/platform new file mode 100644 index 0000000..e69de29 diff --git a/packages/moxplatform_platform_interface/lib/src/platform.dart b/packages/moxplatform_platform_interface/lib/src/platform.dart index 8e15199..4874ad9 100644 --- a/packages/moxplatform_platform_interface/lib/src/platform.dart +++ b/packages/moxplatform_platform_interface/lib/src/platform.dart @@ -4,4 +4,12 @@ abstract class PlatformImplementation { /// Returns the path where cache data should be stored. Future getCacheDataPath(); + + /// Returns whether the app is battery-optimised (false) or + /// excluded from battery savings (true). + Future isIgnoringBatteryOptimizations(); + + /// Opens the page for battery optimisations. If not supported on the + /// platform, does nothing. + Future openBatteryOptimisationSettings(); } diff --git a/packages/moxplatform_platform_interface/lib/src/platform_stub.dart b/packages/moxplatform_platform_interface/lib/src/platform_stub.dart index eeb11ea..e67cf56 100644 --- a/packages/moxplatform_platform_interface/lib/src/platform_stub.dart +++ b/packages/moxplatform_platform_interface/lib/src/platform_stub.dart @@ -8,4 +8,10 @@ class StubPlatformImplementation extends PlatformImplementation { /// Returns the path where cache data should be stored. @override Future getCacheDataPath() async => ''; + + @override + Future isIgnoringBatteryOptimizations() async => false; + + @override + Future openBatteryOptimisationSettings() async {} } diff --git a/pigeons/api.dart b/pigeons/api.dart index a872b24..00e7288 100644 --- a/pigeons/api.dart +++ b/pigeons/api.dart @@ -181,6 +181,8 @@ abstract class MoxplatformApi { /// Platform APIs String getPersistentDataPath(); String getCacheDataPath(); + void openBatteryOptimisationSettings(); + bool isIgnoringBatteryOptimizations(); /// Contacts APIs void recordSentMessage(String name, String jid, String? avatarPath, FallbackIconType fallbackIcon);