Skip to content

Commit

Permalink
Switched to package names as app ids (#69)
Browse files Browse the repository at this point in the history
* Fixes #14 (although detection is disabled in background processes due to the bug described in #60)
    * Added App icons and basic installed detection
    * Real Package Names Used as IDs + App Icons (INCONVENIENT FOR PREVIOUS VERSION USERS)
    * Switch to using extracted names (no custom names)

* Fixes #57

* Fixes #67

* Fixes #64

* Fixes #61

* Commented out APKMirror and added code to remove their Apps

* Updated README

* Switched to Flutter stable (causes some UI elements to switch back to the old material design style, but this will be fixed in later Flutter releases)

* BG task silently retries on network errors

* Updated screenshots
  • Loading branch information
ImranR98 authored Oct 29, 2022
1 parent a954a62 commit d1a3529
Show file tree
Hide file tree
Showing 16 changed files with 576 additions and 433 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ Currently supported App sources:
- [IzzyOnDroid](https://android.izzysoft.de/)
- [Mullvad](https://mullvad.net/en/)
- [Signal](https://signal.org/)
- [APKMirror](https://apkmirror.com/)

## Limitations
- App installs are assumed to have succeeded; failures and cancelled installs cannot be detected.
Expand Down
Binary file modified assets/screenshots/1.apps.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/screenshots/2.dark_theme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/screenshots/3.material_you.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/screenshots/4.app.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/screenshots/5.apk_picker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/screenshots/6.apk_install.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 18 additions & 12 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:obtainium/app_sources/github.dart';
import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/pages/home.dart';
import 'package:obtainium/providers/apps_provider.dart';
Expand All @@ -13,12 +14,14 @@ import 'package:workmanager/workmanager.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:device_info_plus/device_info_plus.dart';

const String currentVersion = '0.6.0';
const String currentReleaseTag =
'v0.5.10-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES

const String bgUpdateCheckTaskName = 'bg-update-check';

bgUpdateCheck(int? ignoreAfterMicroseconds) async {
WidgetsFlutterBinding.ensureInitialized();
DateTime? ignoreAfter = ignoreAfterMicroseconds != null
? DateTime.fromMicrosecondsSinceEpoch(ignoreAfterMicroseconds)
: null;
Expand All @@ -27,21 +30,25 @@ bgUpdateCheck(int? ignoreAfterMicroseconds) async {
try {
var appsProvider = AppsProvider();
await notificationsProvider.cancel(ErrorCheckingUpdatesNotification('').id);
await appsProvider.loadApps();
await appsProvider.loadApps(shouldCorrectInstallStatus: false);
List<String> existingUpdateIds =
appsProvider.getExistingUpdates(installedOnly: true);
DateTime nextIgnoreAfter = DateTime.now();
String? err;
try {
await appsProvider.checkUpdates(
ignoreAfter: ignoreAfter, immediatelyThrowRateLimitError: true);
ignoreAfter: ignoreAfter,
immediatelyThrowRateLimitError: true,
immediatelyThrowSocketError: true,
shouldCorrectInstallStatus: false);
} catch (e) {
if (e is RateLimitError) {
if (e is RateLimitError || e is SocketException) {
String nextTaskName =
'$bgUpdateCheckTaskName-${nextIgnoreAfter.microsecondsSinceEpoch.toString()}';
Workmanager().registerOneOffTask(nextTaskName, nextTaskName,
constraints: Constraints(networkType: NetworkType.connected),
initialDelay: Duration(minutes: e.remainingMinutes),
initialDelay: Duration(
minutes: e is RateLimitError ? e.remainingMinutes : 15),
inputData: {'ignoreAfter': nextIgnoreAfter.microsecondsSinceEpoch});
} else {
err = e.toString();
Expand All @@ -68,16 +75,15 @@ bgUpdateCheck(int? ignoreAfterMicroseconds) async {
// }

if (newUpdates.isNotEmpty) {
notificationsProvider.notify(UpdateNotification(newUpdates),
cancelExisting: true);
notificationsProvider.notify(UpdateNotification(newUpdates));
}
if (err != null) {
throw err;
}
return Future.value(true);
} catch (e) {
notificationsProvider.notify(ErrorCheckingUpdatesNotification(e.toString()),
cancelExisting: true);
notificationsProvider
.notify(ErrorCheckingUpdatesNotification(e.toString()));
return Future.error(false);
} finally {
await notificationsProvider.cancel(checkingUpdatesNotification.id);
Expand All @@ -94,7 +100,7 @@ void bgTaskCallback() {

void main() async {
WidgetsFlutterBinding.ensureInitialized();
if ((await DeviceInfoPlugin().androidInfo).version.sdkInt! >= 29) {
if ((await DeviceInfoPlugin().androidInfo).version.sdkInt >= 29) {
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(systemNavigationBarColor: Colors.transparent),
);
Expand Down Expand Up @@ -143,7 +149,7 @@ class _ObtainiumState extends State<Obtainium> {
Permission.notification.request();
appsProvider.saveApps([
App(
'imranr98_obtainium_${GitHub().host}',
'dev.imranr.obtainium',
'https://github.com/ImranR98/Obtainium',
'ImranR98',
'Obtainium',
Expand Down
121 changes: 59 additions & 62 deletions lib/pages/add_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class _AddAppPageState extends State<AddAppPage> {
String userInput = '';
AppSource? pickedSource;
List<String> additionalData = [];
String customName = '';
bool validAdditionalData = true;

@override
Expand Down Expand Up @@ -80,66 +79,79 @@ class _AddAppPageState extends State<AddAppPage> {
.doesSourceHaveRequiredAdditionalData(
source)
: true;
if (source == null) {
customName = '';
}
}
});
},
defaultValues: const [])),
const SizedBox(
width: 16,
),
ElevatedButton(
onPressed: gettingAppInfo ||
pickedSource == null ||
(pickedSource!.additionalDataFormItems
.isNotEmpty &&
!validAdditionalData)
? null
: () {
HapticFeedback.selectionClick();
setState(() {
gettingAppInfo = true;
});
sourceProvider
.getApp(pickedSource!, userInput,
additionalData,
customName: customName)
.then((app) {
var appsProvider =
context.read<AppsProvider>();
var settingsProvider =
context.read<SettingsProvider>();
if (appsProvider.apps
.containsKey(app.id)) {
throw 'App already added';
}
settingsProvider
.getInstallPermission()
.then((_) {
appsProvider
.saveApps([app]).then((_) {
gettingAppInfo
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: gettingAppInfo ||
pickedSource == null ||
(pickedSource!.additionalDataFormItems
.isNotEmpty &&
!validAdditionalData)
? null
: () async {
setState(() {
gettingAppInfo = true;
});
var appsProvider =
context.read<AppsProvider>();
var settingsProvider =
context.read<SettingsProvider>();
() async {
HapticFeedback.selectionClick();
App app =
await sourceProvider.getApp(
pickedSource!,
userInput,
additionalData);
await settingsProvider
.getInstallPermission();
// ignore: use_build_context_synchronously
var apkUrl = await appsProvider
.selectApkUrl(app, context);
if (apkUrl == null) {
throw 'Cancelled';
}
app.preferredApkIndex =
app.apkUrls.indexOf(apkUrl);
var downloadedApk =
await appsProvider
.downloadApp(app);
app.id = downloadedApk.appId;
if (appsProvider.apps
.containsKey(app.id)) {
throw 'App already added';
}
await appsProvider.saveApps([app]);

return app;
}()
.then((app) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
AppPage(
appId: app.id)));
}).catchError((e) {
ScaffoldMessenger.of(context)
.showSnackBar(
SnackBar(
content: Text(e.toString())),
);
}).whenComplete(() {
setState(() {
gettingAppInfo = false;
});
});
});
}).catchError((e) {
ScaffoldMessenger.of(context)
.showSnackBar(
SnackBar(content: Text(e.toString())),
);
}).whenComplete(() {
setState(() {
gettingAppInfo = false;
});
});
},
child: const Text('Add'))
},
child: const Text('Add'))
],
),
if (pickedSource != null)
Expand Down Expand Up @@ -174,21 +186,6 @@ class _AddAppPageState extends State<AddAppPage> {
const SizedBox(
height: 8,
),
if (pickedSource != null)
GeneratedForm(
items: [
[
GeneratedFormItem(
label: 'Custom App Name',
required: false)
]
],
onValueChanges: (values, valid) {
setState(() {
customName = values[0];
});
},
defaultValues: [customName])
],
)
else
Expand Down
Loading

0 comments on commit d1a3529

Please sign in to comment.