Switch to AlarmManager plugin from WorkManager for more reliable update checking (for #87) (#97)

This commit is contained in:
Imran Remtulla
2022-11-05 23:25:19 -04:00
committed by GitHub
parent bd5f21984e
commit ed4a26d348
6 changed files with 53 additions and 57 deletions

View File

@@ -30,7 +30,25 @@
<meta-data <meta-data
android:name="flutterEmbedding" android:name="flutterEmbedding"
android:value="2" /> android:value="2" />
<service
android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<receiver
android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmBroadcastReceiver"
android:exported="false"/>
<receiver
android:name="dev.fluttercommunity.plus.androidalarmmanager.RebootBroadcastReceiver"
android:enabled="false"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application> </application>
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
</manifest> </manifest>

View File

@@ -1,4 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@@ -10,18 +11,21 @@ import 'package:obtainium/providers/settings_provider.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:workmanager/workmanager.dart';
import 'package:dynamic_color/dynamic_color.dart'; import 'package:dynamic_color/dynamic_color.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart';
const String currentVersion = '0.6.6'; const String currentVersion = '0.6.7';
const String currentReleaseTag = const String currentReleaseTag =
'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
const String bgUpdateCheckTaskName = 'bg-update-check'; const int bgUpdateCheckAlarmId = 666;
bgUpdateCheck(int? ignoreAfterMicroseconds) async { @pragma('vm:entry-point')
Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
int? ignoreAfterMicroseconds = params?['ignoreAfterMicroseconds'];
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await AndroidAlarmManager.initialize();
DateTime? ignoreAfter = ignoreAfterMicroseconds != null DateTime? ignoreAfter = ignoreAfterMicroseconds != null
? DateTime.fromMicrosecondsSinceEpoch(ignoreAfterMicroseconds) ? DateTime.fromMicrosecondsSinceEpoch(ignoreAfterMicroseconds)
: null; : null;
@@ -43,13 +47,13 @@ bgUpdateCheck(int? ignoreAfterMicroseconds) async {
shouldCorrectInstallStatus: false); shouldCorrectInstallStatus: false);
} catch (e) { } catch (e) {
if (e is RateLimitError || e is SocketException) { if (e is RateLimitError || e is SocketException) {
String nextTaskName = AndroidAlarmManager.oneShot(
'$bgUpdateCheckTaskName-${nextIgnoreAfter.microsecondsSinceEpoch.toString()}'; Duration(minutes: e is RateLimitError ? e.remainingMinutes : 15),
Workmanager().registerOneOffTask(nextTaskName, nextTaskName, Random().nextInt(pow(2, 31) as int),
constraints: Constraints(networkType: NetworkType.connected), bgUpdateCheck,
initialDelay: Duration( params: {
minutes: e is RateLimitError ? e.remainingMinutes : 15), 'ignoreAfterMicroseconds': nextIgnoreAfter.microsecondsSinceEpoch
inputData: {'ignoreAfter': nextIgnoreAfter.microsecondsSinceEpoch}); });
} else { } else {
err = e.toString(); err = e.toString();
} }
@@ -80,24 +84,14 @@ bgUpdateCheck(int? ignoreAfterMicroseconds) async {
if (err != null) { if (err != null) {
throw err; throw err;
} }
return Future.value(true);
} catch (e) { } catch (e) {
notificationsProvider notificationsProvider
.notify(ErrorCheckingUpdatesNotification(e.toString())); .notify(ErrorCheckingUpdatesNotification(e.toString()));
return Future.error(false);
} finally { } finally {
await notificationsProvider.cancel(checkingUpdatesNotification.id); await notificationsProvider.cancel(checkingUpdatesNotification.id);
} }
} }
@pragma('vm:entry-point')
void bgTaskCallback() {
// Background process callback
Workmanager().executeTask((task, inputData) async {
return await bgUpdateCheck(inputData?['ignoreAfter']);
});
}
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
if ((await DeviceInfoPlugin().androidInfo).version.sdkInt >= 29) { if ((await DeviceInfoPlugin().androidInfo).version.sdkInt >= 29) {
@@ -106,9 +100,7 @@ void main() async {
); );
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
} }
Workmanager().initialize( await AndroidAlarmManager.initialize();
bgTaskCallback,
);
runApp(MultiProvider( runApp(MultiProvider(
providers: [ providers: [
ChangeNotifierProvider( ChangeNotifierProvider(
@@ -165,17 +157,14 @@ class _ObtainiumState extends State<Obtainium> {
if (existingUpdateInterval != settingsProvider.updateInterval) { if (existingUpdateInterval != settingsProvider.updateInterval) {
existingUpdateInterval = settingsProvider.updateInterval; existingUpdateInterval = settingsProvider.updateInterval;
if (existingUpdateInterval == 0) { if (existingUpdateInterval == 0) {
Workmanager().cancelByUniqueName(bgUpdateCheckTaskName); AndroidAlarmManager.cancel(bgUpdateCheckAlarmId);
} else { } else {
Workmanager().registerPeriodicTask( AndroidAlarmManager.periodic(
bgUpdateCheckTaskName, bgUpdateCheckTaskName, Duration(minutes: existingUpdateInterval),
frequency: Duration(minutes: existingUpdateInterval), bgUpdateCheckAlarmId,
initialDelay: Duration(minutes: existingUpdateInterval), bgUpdateCheck,
constraints: Constraints(networkType: NetworkType.connected), rescheduleOnReboot: true,
existingWorkPolicy: ExistingWorkPolicy.replace, wakeup: true);
backoffPolicy: BackoffPolicy.linear,
backoffPolicyDelay:
const Duration(minutes: minUpdateIntervalMinutes));
} }
} }
} }

View File

@@ -209,17 +209,6 @@ class _SettingsPageState extends State<SettingsPage> {
settingsProvider.updateInterval = value; settingsProvider.updateInterval = value;
} }
}), }),
const SizedBox(
height: 8,
),
Text(
'Longer intervals may result in less reliable behaviour',
style: Theme.of(context)
.textTheme
.labelMedium!
.merge(const TextStyle(
fontStyle: FontStyle.italic)),
),
const Divider( const Divider(
height: 48, height: 48,
), ),

View File

@@ -55,7 +55,7 @@ class SettingsProvider with ChangeNotifier {
} }
int get updateInterval { int get updateInterval {
var min = prefs?.getInt('updateInterval') ?? 60; var min = prefs?.getInt('updateInterval') ?? 360;
if (!updateIntervals.contains(min)) { if (!updateIntervals.contains(min)) {
var temp = updateIntervals[0]; var temp = updateIntervals[0];
for (var i in updateIntervals) { for (var i in updateIntervals) {

View File

@@ -1,6 +1,13 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
android_alarm_manager_plus:
dependency: "direct main"
description:
name: android_alarm_manager_plus
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
animations: animations:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -358,7 +365,7 @@ packages:
name: path_provider_android name: path_provider_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.20" version: "2.0.21"
path_provider_ios: path_provider_ios:
dependency: transitive dependency: transitive
description: description:
@@ -470,7 +477,7 @@ packages:
name: share_plus name: share_plus
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.0" version: "6.2.0"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -700,13 +707,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
workmanager:
dependency: "direct main"
description:
name: workmanager
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:

View File

@@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 0.6.6+50 # When changing this, update the tag in main() accordingly version: 0.6.7+51 # When changing this, update the tag in main() accordingly
environment: environment:
sdk: '>=2.18.2 <3.0.0' sdk: '>=2.18.2 <3.0.0'
@@ -42,7 +42,6 @@ dependencies:
provider: ^6.0.3 provider: ^6.0.3
http: ^0.13.5 http: ^0.13.5
webview_flutter: ^3.0.4 webview_flutter: ^3.0.4
workmanager: ^0.5.0
dynamic_color: ^1.5.4 dynamic_color: ^1.5.4
html: ^0.15.0 html: ^0.15.0
shared_preferences: ^2.0.15 shared_preferences: ^2.0.15
@@ -56,6 +55,7 @@ dependencies:
share_plus: ^6.0.1 share_plus: ^6.0.1
installed_apps: ^1.3.1 installed_apps: ^1.3.1
package_archive_info: ^0.1.0 package_archive_info: ^0.1.0
android_alarm_manager_plus: ^2.1.0
dev_dependencies: dev_dependencies: