From c377a097480043f8cac8c4ddd658c9d71e2356fd Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Tue, 12 Apr 2022 18:06:48 -0700 Subject: [PATCH] add setting that reports / triggers android power optimization exemption --- .../kotlin/im/cwtch/flwtch/MainActivity.kt | 27 ++++++-- lib/cwtch/gomobile.dart | 12 ---- lib/l10n/intl_cy.arb | 4 +- lib/l10n/intl_da.arb | 4 +- lib/l10n/intl_de.arb | 4 +- lib/l10n/intl_el.arb | 4 +- lib/l10n/intl_en.arb | 4 +- lib/l10n/intl_es.arb | 4 +- lib/l10n/intl_fr.arb | 4 +- lib/l10n/intl_it.arb | 4 +- lib/l10n/intl_lb.arb | 4 +- lib/l10n/intl_no.arb | 4 +- lib/l10n/intl_pl.arb | 4 +- lib/l10n/intl_pt.arb | 4 +- lib/l10n/intl_ro.arb | 4 +- lib/l10n/intl_ru.arb | 3 +- lib/views/globalsettingsview.dart | 65 +++++++++++++++++++ 17 files changed, 129 insertions(+), 30 deletions(-) diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt index 2798ffef..dd39a06d 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt @@ -37,6 +37,9 @@ class MainActivity: FlutterActivity() { // Channel to get app info private val CHANNEL_APP_INFO = "test.flutter.dev/applicationInfo" private val CALL_APP_INFO = "getNativeLibDir" + private val ANDROID_SETTINGS_CHANNEL_NAME = "androidSettings" + private val ANDROID_SETTINGS_CHANGE_NAME= "androidSettingsChanged" + private var andoidSettingsChangeChannel: MethodChannel? = null private val CALL_ASK_BATTERY_EXEMPTION = "requestBatteryExemption" private val CALL_IS_BATTERY_EXEMPT = "isBatteryExempt" @@ -94,6 +97,14 @@ class MainActivity: FlutterActivity() { override fun onActivityResult(requestCode: Int, result: Int, intent: Intent?) { super.onActivityResult(requestCode, result, intent); + // has null intent and data + if (requestCode == REQUEST_DOZE_WHITELISTING_CODE) { + // 0 == "battery optimized" (still) + // -1 == "no battery optimization" (exempt!) + andoidSettingsChangeChannel!!.invokeMethod("powerExemptionChange", result == -1) + return; + } + if (intent == null || intent!!.getData() == null) { Log.i(TAG, "user canceled activity"); return; @@ -135,8 +146,6 @@ class MainActivity: FlutterActivity() { os?.close(); //Files.delete(sourcePath); } - } else if (requestCode == REQUEST_DOZE_WHITELISTING_CODE) { - checkIgnoreBatteryOpt() } } @@ -147,8 +156,10 @@ class MainActivity: FlutterActivity() { requestWindowFeature(Window.FEATURE_NO_TITLE) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_APP_INFO).setMethodCallHandler { call, result -> handleAppInfo(call, result) } MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_CWTCH).setMethodCallHandler { call, result -> handleCwtch(call, result) } + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, ANDROID_SETTINGS_CHANNEL_NAME).setMethodCallHandler { call, result -> handleAndroidSettings(call, result) } notificationClickChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_NOTIF_CLICK) shutdownClickChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_SHUTDOWN_CLICK) + andoidSettingsChangeChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, ANDROID_SETTINGS_CHANGE_NAME) } // MethodChannel CHANNEL_APP_INFO handler (Flutter Channel for requests for Android environment info) @@ -156,8 +167,16 @@ class MainActivity: FlutterActivity() { when (call.method) { CALL_APP_INFO -> result.success(getNativeLibDir()) ?: result.error("Unavailable", "nativeLibDir not available", null); - CALL_ASK_BATTERY_EXEMPTION -> result.success(checkIgnoreBatteryOpt()) ?: false; - CALL_IS_BATTERY_EXEMPT -> result.success(requestBatteryExemption()); + else -> result.notImplemented() + } + } + + // MethodChannel ANDROID_SETTINGS_CHANNEL_NAME handler (Flutter Channel for requests for Android settings) + // Called from lib/view/globalsettingsview.dart + private fun handleAndroidSettings(@NonNull call: MethodCall, @NonNull result: Result) { + when (call.method) { + CALL_IS_BATTERY_EXEMPT -> result.success(checkIgnoreBatteryOpt() ?: false); + CALL_ASK_BATTERY_EXEMPTION -> { requestBatteryExemption(); result.success(null); } else -> result.notImplemented() } } diff --git a/lib/cwtch/gomobile.dart b/lib/cwtch/gomobile.dart index fac90776..7bd4f888 100644 --- a/lib/cwtch/gomobile.dart +++ b/lib/cwtch/gomobile.dart @@ -57,18 +57,6 @@ class CwtchGomobile implements Cwtch { return cwtchPlatform.invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath}); } - //* Android Only Requests - - Future IsBatteryExempt() async { - return await appInfoPlatform?.invokeMethod('isBatteryExempt') ?? false; - } - - Future RequestBatteryExemption() async { - await appInfoPlatform?.invokeMethod('requestBatteryExemption'); - } - - //* End Android Only Requests - @override // ignore: non_constant_identifier_names Future ReconnectCwtchForeground() async { diff --git a/lib/l10n/intl_cy.arb b/lib/l10n/intl_cy.arb index 77e5a083..c86e8d76 100644 --- a/lib/l10n/intl_cy.arb +++ b/lib/l10n/intl_cy.arb @@ -1,6 +1,8 @@ { "@@locale": "cy", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_da.arb b/lib/l10n/intl_da.arb index a07fca58..6036f30a 100644 --- a/lib/l10n/intl_da.arb +++ b/lib/l10n/intl_da.arb @@ -1,6 +1,8 @@ { "@@locale": "da", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index 3deedbba..25789c91 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -1,6 +1,8 @@ { "@@locale": "de", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_el.arb b/lib/l10n/intl_el.arb index b6e196f6..99cf5bc4 100644 --- a/lib/l10n/intl_el.arb +++ b/lib/l10n/intl_el.arb @@ -1,6 +1,8 @@ { "@@locale": "el", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index a924c3b4..0693616b 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,6 +1,8 @@ { "@@locale": "en", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 075a16e9..8e37b1d3 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -1,6 +1,8 @@ { "@@locale": "es", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 4e134d74..b98cadee 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -1,6 +1,8 @@ { "@@locale": "fr", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Activer la mise en forme de texte enrichi dans les messages affichés, par exemple **gras** et *italique*", "formattingExperiment": "Mise en forme des messages", diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index 34fd3fa9..1bce64ea 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -1,6 +1,8 @@ { "@@locale": "it", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_lb.arb b/lib/l10n/intl_lb.arb index cf33de01..50ca5fe4 100644 --- a/lib/l10n/intl_lb.arb +++ b/lib/l10n/intl_lb.arb @@ -1,6 +1,8 @@ { "@@locale": "lb", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_no.arb b/lib/l10n/intl_no.arb index 295c2538..20614bb1 100644 --- a/lib/l10n/intl_no.arb +++ b/lib/l10n/intl_no.arb @@ -1,6 +1,8 @@ { "@@locale": "no", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_pl.arb b/lib/l10n/intl_pl.arb index ce83b136..9122f2e4 100644 --- a/lib/l10n/intl_pl.arb +++ b/lib/l10n/intl_pl.arb @@ -1,6 +1,8 @@ { "@@locale": "pl", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_pt.arb b/lib/l10n/intl_pt.arb index a48754a3..a03c616b 100644 --- a/lib/l10n/intl_pt.arb +++ b/lib/l10n/intl_pt.arb @@ -1,6 +1,8 @@ { "@@locale": "pt", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_ro.arb b/lib/l10n/intl_ro.arb index 051e69b8..7a135e5d 100644 --- a/lib/l10n/intl_ro.arb +++ b/lib/l10n/intl_ro.arb @@ -1,6 +1,8 @@ { "@@locale": "ro", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "@@last_modified": "2022-04-13T02:54:41+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/l10n/intl_ru.arb b/lib/l10n/intl_ru.arb index b7be29a1..bc7e8cd5 100644 --- a/lib/l10n/intl_ru.arb +++ b/lib/l10n/intl_ru.arb @@ -1,6 +1,7 @@ { "@@locale": "ru", - "@@last_modified": "2022-04-12T20:56:53+02:00", + "settingAndroidPowerExemptionDescription": "Android by default applies an \"optimized\" power management profile to apps which can result in them being stopped or killed. Request Android to exempt Cwtch from this for better stability but more power use.", + "settingAndroidPowerExemption": "Android Ignore Battery Optimizations", "thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings", "messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*", "formattingExperiment": "Message Formatting", diff --git a/lib/views/globalsettingsview.dart b/lib/views/globalsettingsview.dart index 806d9486..964db812 100644 --- a/lib/views/globalsettingsview.dart +++ b/lib/views/globalsettingsview.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:math'; import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:cwtch/models/servers.dart'; import 'package:cwtch/widgets/folderpicker.dart'; @@ -13,6 +14,7 @@ import 'package:cwtch/themes/opaque.dart'; import 'package:cwtch/themes/pumpkin.dart'; import 'package:cwtch/themes/vampire.dart'; import 'package:cwtch/themes/witch.dart'; +import 'package:flutter/services.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:flutter/material.dart'; import 'package:cwtch/settings.dart'; @@ -29,11 +31,52 @@ class GlobalSettingsView extends StatefulWidget { } class _GlobalSettingsViewState extends State { + static const androidSettingsChannel = const MethodChannel('androidSettings'); + static const androidSettingsChangeChannel = const MethodChannel('androidSettingsChanged'); + bool powerExempt = false; + @override void dispose() { super.dispose(); } + @override + void initState() { + super.initState(); + androidSettingsChangeChannel.setMethodCallHandler(handleSettingsChanged); + + if (Platform.isAndroid) { + isBatteryExempt().then((value) => setState(() { powerExempt = value; }) ); + } else { + powerExempt = false; + } + } + + // Handler on method channel for MainActivity/onActivityResult to report the user choice when we ask for power exemption + Future handleSettingsChanged(MethodCall call) async { + if (call.method == "powerExemptionChange") { + if (call.arguments) { + setState(() { + powerExempt = true; + }); + } + } + } + + //* Android Only Requests + + Future isBatteryExempt() async { + return await androidSettingsChannel.invokeMethod('isBatteryExempt', {}) ?? false; + } + + + Future requestBatteryExemption() async { + await androidSettingsChannel.invokeMethod('requestBatteryExemption', {}); + return Future.value(); + } + + //* End Android Only Requests + @override Widget build(BuildContext context) { return Scaffold( @@ -172,6 +215,28 @@ class _GlobalSettingsViewState extends State { height: 40, ), Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text(AppLocalizations.of(context)!.settingGroupBehaviour, style: TextStyle(fontWeight: FontWeight.bold))]), + Visibility( + visible: Platform.isAndroid, + child: SwitchListTile( + title: Text(AppLocalizations.of(context)!.settingAndroidPowerExemption, style: TextStyle(color: settings + .current() + .mainTextColor)), + subtitle: Text(AppLocalizations.of(context)!.settingAndroidPowerExemptionDescription), + value: powerExempt, + onChanged: (bool value) { + if (value) { + requestBatteryExemption(); + } else { + // We don't ask for it to be turned off, user has to manually in android settings, so this is a NOP + } + }, + activeTrackColor: settings.theme.defaultButtonColor, + inactiveTrackColor: settings.theme.defaultButtonDisabledColor, + secondary: Icon(Icons.power, color: settings + .current() + .mainTextColor), + ), + ), ListTile( title: Text(AppLocalizations.of(context)!.notificationPolicySettingLabel), subtitle: Text(AppLocalizations.of(context)!.notificationPolicySettingDescription),