Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit 58a29f0

Browse files
committed
Implement background module update check & improve translator utils. (New strings)
1 parent 5487921 commit 58a29f0

File tree

12 files changed

+317
-33
lines changed

12 files changed

+317
-33
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ dependencies {
9797
implementation 'com.github.Fox2Code:FoxCompat:0.0.2'
9898

9999
// Utils
100+
implementation 'androidx.work:work-runtime:2.7.1'
100101
implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.3'
101102
implementation 'com.squareup.okhttp3:okhttp-brotli:4.9.3'
102103
implementation 'com.github.topjohnwu.libsu:io:5.0.1'

app/src/main/AndroidManifest.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
<uses-permission android:name="android.permission.INTERNET" />
1212
<!-- WebView offline webpage support -->
1313
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
14+
<!-- Check if there is modules updates on boot -->
15+
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
1416
<!-- Open config apps for applications -->
1517
<uses-permission-sdk-23 android:name="android.permission.QUERY_ALL_PACKAGES" />
1618
<!-- Supposed to fix bugs with old firmware, only requested on pre Marshmallow -->
@@ -31,7 +33,14 @@
3133
android:networkSecurityConfig="@xml/network_security_config"
3234
android:usesCleartextTraffic="false"
3335
tools:targetApi="s"
34-
tools:replace="android:supportsRtl">
36+
tools:replace="android:supportsRtl"
37+
tools:ignore="ManifestResource">
38+
<receiver android:name="com.fox2code.mmm.background.BackgroundBootListener"
39+
android:exported="true">
40+
<intent-filter>
41+
<action android:name="android.intent.action.BOOT_COMPLETED" />
42+
</intent-filter>
43+
</receiver>
3544
<activity
3645
android:name=".settings.SettingsActivity"
3746
android:parentActivityName=".MainActivity"

app/src/main/java/com/fox2code/mmm/MainActivity.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
import androidx.annotation.NonNull;
1717
import androidx.appcompat.widget.SearchView;
1818
import androidx.cardview.widget.CardView;
19+
import androidx.core.app.NotificationManagerCompat;
1920
import androidx.core.graphics.ColorUtils;
2021
import androidx.recyclerview.widget.LinearLayoutManager;
2122
import androidx.recyclerview.widget.RecyclerView;
2223
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
2324

2425
import com.fox2code.foxcompat.FoxActivity;
2526
import com.fox2code.foxcompat.FoxDisplay;
27+
import com.fox2code.mmm.background.BackgroundUpdateChecker;
2628
import com.fox2code.mmm.installer.InstallerInitializer;
2729
import com.fox2code.mmm.manager.LocalModuleInfo;
2830
import com.fox2code.mmm.manager.ModuleManager;
@@ -64,9 +66,16 @@ public MainActivity() {
6466
this.moduleViewListBuilder.addNotification(NotificationType.INSTALL_FROM_STORAGE);
6567
}
6668

69+
@Override
70+
protected void onResume() {
71+
BackgroundUpdateChecker.onMainActivityResume(this);
72+
super.onResume();
73+
}
74+
6775
@Override
6876
protected void onCreate(Bundle savedInstanceState) {
6977
this.initMode = true;
78+
BackgroundUpdateChecker.onMainActivityCreate(this);
7079
super.onCreate(savedInstanceState);
7180
this.setActionBarExtraMenuButton(R.drawable.ic_baseline_settings_24, v -> {
7281
IntentHelper.startActivity(this, SettingsActivity.class);
@@ -395,7 +404,8 @@ public boolean onQueryTextSubmit(final String query) {
395404
this.searchView.clearFocus();
396405
if (this.initMode) return false;
397406
if (this.moduleViewListBuilder.setQueryChange(query)) {
398-
new Thread(() -> this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter), "Query update thread").start();
407+
new Thread(() -> this.moduleViewListBuilder.applyTo(
408+
moduleList, moduleViewAdapter), "Query update thread").start();
399409
}
400410
return true;
401411
}
@@ -404,7 +414,8 @@ public boolean onQueryTextSubmit(final String query) {
404414
public boolean onQueryTextChange(String query) {
405415
if (this.initMode) return false;
406416
if (this.moduleViewListBuilder.setQueryChange(query)) {
407-
new Thread(() -> this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter), "Query update thread").start();
417+
new Thread(() -> this.moduleViewListBuilder.applyTo(
418+
moduleList, moduleViewAdapter), "Query update thread").start();
408419
}
409420
return false;
410421
}
@@ -413,7 +424,8 @@ public boolean onQueryTextChange(String query) {
413424
public boolean onClose() {
414425
if (this.initMode) return false;
415426
if (this.moduleViewListBuilder.setQueryChange(null)) {
416-
new Thread(() -> this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter), "Query update thread").start();
427+
new Thread(() -> this.moduleViewListBuilder.applyTo(
428+
moduleList, moduleViewAdapter), "Query update thread").start();
417429
}
418430
return false;
419431
}

app/src/main/java/com/fox2code/mmm/MainApplication.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@
1717
import androidx.emoji2.text.DefaultEmojiCompatConfig;
1818
import androidx.emoji2.text.EmojiCompat;
1919
import androidx.emoji2.text.FontRequestEmojiCompatConfig;
20+
import androidx.work.Constraints;
21+
import androidx.work.ExistingPeriodicWorkPolicy;
22+
import androidx.work.NetworkType;
23+
import androidx.work.PeriodicWorkRequest;
24+
import androidx.work.WorkManager;
2025

2126
import com.fox2code.foxcompat.FoxActivity;
2227
import com.fox2code.foxcompat.FoxApplication;
2328
import com.fox2code.foxcompat.FoxThemeWrapper;
29+
import com.fox2code.mmm.background.BackgroundUpdateChecker;
2430
import com.fox2code.mmm.installer.InstallerInitializer;
2531
import com.fox2code.mmm.utils.GMSProviderInstaller;
2632
import com.fox2code.mmm.utils.Http;
@@ -31,6 +37,7 @@
3137
import java.util.Date;
3238
import java.util.Locale;
3339
import java.util.Random;
40+
import java.util.concurrent.TimeUnit;
3441

3542
import io.noties.markwon.Markwon;
3643
import io.noties.markwon.html.HtmlPlugin;
@@ -47,7 +54,8 @@
4754
includeAll = true,
4855
grammarLocatorClassName = ".Prism4jGrammarLocator"
4956
)
50-
public class MainApplication extends FoxApplication {
57+
public class MainApplication extends FoxApplication
58+
implements androidx.work.Configuration.Provider {
5159
private static final String timeFormatString = "dd MMM yyyy"; // Example: 13 july 2001
5260
private static Locale timeFormatLocale =
5361
Resources.getSystem().getConfiguration().locale;
@@ -146,6 +154,10 @@ && getSharedPreferences().getBoolean("pref_use_magisk_install_command", false)
146154
&& isDeveloper();
147155
}
148156

157+
public static boolean isBackgroundUpdateCheckEnabled() {
158+
return getSharedPreferences().getBoolean("pref_background_update_check", true);
159+
}
160+
149161
public static boolean isFirstBoot() {
150162
return firstBoot;
151163
}
@@ -196,6 +208,12 @@ public FoxThemeWrapper getMarkwonThemeContext() {
196208
return this.markwonThemeContext;
197209
}
198210

211+
@NonNull
212+
@Override
213+
public androidx.work.Configuration getWorkManagerConfiguration() {
214+
return new androidx.work.Configuration.Builder().build();
215+
}
216+
199217
private class Prism4jSwitchTheme implements Prism4jTheme {
200218
private final Prism4jTheme light = new Prism4jThemeDefault(Color.TRANSPARENT);
201219
private final Prism4jTheme dark = new Prism4jThemeDarkula(Color.TRANSPARENT);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.fox2code.mmm.background;
2+
3+
import android.content.BroadcastReceiver;
4+
import android.content.Context;
5+
import android.content.Intent;
6+
7+
import com.fox2code.mmm.MainApplication;
8+
9+
public class BackgroundBootListener extends BroadcastReceiver {
10+
private static final String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
11+
12+
@Override
13+
public void onReceive(Context context, Intent intent) {
14+
if (!BOOT_COMPLETED.equals(intent.getAction())) return;
15+
if (!MainApplication.isBackgroundUpdateCheckEnabled()) return;
16+
BackgroundUpdateChecker.onMainActivityCreate(context);
17+
BackgroundUpdateChecker.doCheck(context);
18+
}
19+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package com.fox2code.mmm.background;
2+
3+
import android.app.PendingIntent;
4+
import android.content.Context;
5+
import android.content.Intent;
6+
import android.os.Build;
7+
8+
import androidx.annotation.NonNull;
9+
import androidx.core.app.NotificationChannelCompat;
10+
import androidx.core.app.NotificationCompat;
11+
import androidx.core.app.NotificationManagerCompat;
12+
import androidx.work.Constraints;
13+
import androidx.work.ExistingPeriodicWorkPolicy;
14+
import androidx.work.NetworkType;
15+
import androidx.work.PeriodicWorkRequest;
16+
import androidx.work.WorkManager;
17+
import androidx.work.Worker;
18+
import androidx.work.WorkerParameters;
19+
20+
import com.fox2code.mmm.MainActivity;
21+
import com.fox2code.mmm.MainApplication;
22+
import com.fox2code.mmm.R;
23+
import com.fox2code.mmm.manager.LocalModuleInfo;
24+
import com.fox2code.mmm.manager.ModuleManager;
25+
import com.fox2code.mmm.repo.RepoManager;
26+
import com.fox2code.mmm.repo.RepoModule;
27+
28+
import java.util.Random;
29+
import java.util.concurrent.TimeUnit;
30+
31+
public class BackgroundUpdateChecker extends Worker {
32+
private static boolean easterEggActive = false;
33+
public static final String NOTIFICATION_CHANNEL_ID = "background_update";
34+
public static final int NOTIFICATION_ID = 1;
35+
36+
public BackgroundUpdateChecker(@NonNull Context context,
37+
@NonNull WorkerParameters workerParams) {
38+
super(context, workerParams);
39+
}
40+
41+
@NonNull
42+
@Override
43+
public Result doWork() {
44+
if (!NotificationManagerCompat.from(this.getApplicationContext()).areNotificationsEnabled()
45+
|| !MainApplication.isBackgroundUpdateCheckEnabled()) return Result.success();
46+
47+
doCheck(this.getApplicationContext());
48+
49+
return Result.success();
50+
}
51+
52+
static void doCheck(Context context) {
53+
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
54+
RepoManager.getINSTANCE().update(null);
55+
ModuleManager.getINSTANCE().scan();
56+
ModuleManager.getINSTANCE().scan();
57+
int moduleUpdateCount = 0;
58+
for (LocalModuleInfo localModuleInfo :
59+
ModuleManager.getINSTANCE().getModules().values()) {
60+
RepoModule repoModule = RepoManager.getINSTANCE()
61+
.getModules().get(localModuleInfo.id);
62+
localModuleInfo.checkModuleUpdate();
63+
if (localModuleInfo.updateVersionCode > localModuleInfo.versionCode) {
64+
moduleUpdateCount++;
65+
} else if (repoModule != null &&
66+
repoModule.moduleInfo.versionCode > localModuleInfo.versionCode) {
67+
moduleUpdateCount++;
68+
}
69+
}
70+
if (moduleUpdateCount != 0) {
71+
postNotification(context, moduleUpdateCount);
72+
}
73+
}
74+
75+
public static void postNotification(Context context, int updateCount) {
76+
if (!easterEggActive) easterEggActive = new Random().nextInt(100) <= updateCount;
77+
NotificationCompat.Builder builder = new NotificationCompat.Builder(
78+
context, NOTIFICATION_CHANNEL_ID)
79+
.setContentTitle(context.getString(easterEggActive ?
80+
R.string.notification_update_title_easter_egg :
81+
R.string.notification_update_title)
82+
.replace("%i", String.valueOf(updateCount)))
83+
.setContentText(context.getString(R.string.notification_update_subtitle))
84+
.setSmallIcon(R.drawable.ic_baseline_extension_24)
85+
.setPriority(NotificationCompat.PRIORITY_HIGH)
86+
.setContentIntent(PendingIntent.getActivity(context, 0,
87+
new Intent(context, MainActivity.class).setFlags(
88+
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK),
89+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ?
90+
PendingIntent.FLAG_IMMUTABLE : 0)).setAutoCancel(true);
91+
NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, builder.build());
92+
}
93+
94+
public static void onMainActivityCreate(Context context) {
95+
NotificationManagerCompat notificationManagerCompat =
96+
NotificationManagerCompat.from(context);
97+
notificationManagerCompat.createNotificationChannel(
98+
new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID,
99+
NotificationManagerCompat.IMPORTANCE_HIGH).setShowBadge(true)
100+
.setName(context.getString(R.string.notification_update_pref)).build());
101+
notificationManagerCompat.cancel(BackgroundUpdateChecker.NOTIFICATION_ID);
102+
BackgroundUpdateChecker.easterEggActive = false;
103+
WorkManager.getInstance(context).enqueueUniquePeriodicWork("background_checker",
104+
ExistingPeriodicWorkPolicy.REPLACE, new PeriodicWorkRequest.Builder(
105+
BackgroundUpdateChecker.class, 6, TimeUnit.HOURS)
106+
.setConstraints(new Constraints.Builder().setRequiresBatteryNotLow(true)
107+
.setRequiredNetworkType(NetworkType.UNMETERED).build()).build());
108+
}
109+
110+
public static void onMainActivityResume(Context context) {
111+
NotificationManagerCompat.from(context).cancel(
112+
BackgroundUpdateChecker.NOTIFICATION_ID);
113+
BackgroundUpdateChecker.easterEggActive = false;
114+
}
115+
}

app/src/main/java/com/fox2code/mmm/module/ActionButtonType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ public static int donateIconForUrl(String url) {
253253
if (url.startsWith("https://www.paypal.me/") ||
254254
url.startsWith("https://www.paypal.com/paypalme/")) {
255255
icon = R.drawable.ic_baseline_paypal_24;
256-
} else if (url.startsWith("https://www.patreon.com/")) {
256+
} else if (url.startsWith("https://patreon.com/") ||
257+
url.startsWith("https://www.patreon.com/")) {
257258
icon = R.drawable.ic_patreon;
258259
}
259260
return icon;

app/src/main/java/com/fox2code/mmm/repo/RepoData.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,14 @@ public String getPreferenceId() {
212212
return this.id;
213213
}
214214

215+
private static boolean isNonNull(String str) {
216+
return str != null && !str.isEmpty() && !"null".equals(str);
217+
}
218+
215219
// Repo data info getters
216220
@NonNull
217221
public String getName() {
218-
if (this.name != null &&
219-
!this.name.isEmpty())
222+
if (isNonNull(this.name))
220223
return this.name;
221224
if (this.defaultName != null)
222225
return this.defaultName;
@@ -225,31 +228,27 @@ public String getName() {
225228

226229
@NonNull
227230
public String getWebsite() {
228-
if (this.website != null &&
229-
!this.website.isEmpty())
231+
if (isNonNull(this.website))
230232
return this.website;
231233
if (this.defaultWebsite != null)
232234
return this.defaultWebsite;
233235
return this.url;
234236
}
235237

236238
public String getSupport() {
237-
if (this.support != null &&
238-
!this.support.isEmpty())
239+
if (isNonNull(this.support))
239240
return this.support;
240241
return this.defaultSupport;
241242
}
242243

243244
public String getDonate() {
244-
if (this.donate != null &&
245-
!this.donate.isEmpty())
245+
if (isNonNull(this.donate))
246246
return this.donate;
247247
return this.defaultDonate;
248248
}
249249

250250
public String getSubmitModule() {
251-
if (this.submitModule != null &&
252-
!this.submitModule.isEmpty())
251+
if (isNonNull(this.submitModule))
253252
return this.submitModule;
254253
return this.defaultSubmitModule;
255254
}

0 commit comments

Comments
 (0)