(fix) try to fix update showing in UI

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/300/head
androidacy-user 1 year ago
parent 39bb0c119f
commit 7effbaac2f

@ -321,7 +321,7 @@ dependencies {
implementation 'com.github.KieronQuinn:MonetCompat:0.4.1'
implementation 'com.github.Fox2Code:FoxCompat:0.2.0'
// Update the version code in the root build.gradle
implementation 'com.mikepenz:aboutlibraries:10.6.1'
implementation 'com.mikepenz:aboutlibraries:10.6.2'
// Utils
implementation 'androidx.work:work-runtime:2.8.1'
@ -402,7 +402,7 @@ android {
jvmTarget = JavaVersion.VERSION_17
}
//noinspection GrDeprecatedAPIUsage
buildToolsVersion '34.0.0 rc2'
buildToolsVersion '34.0.0 rc3'
}

@ -191,11 +191,6 @@
android:resource="@xml/shared_file_paths" />
</provider>
<service
android:name=".background.BackgroundUpdateCheckerService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
<meta-data
android:name="io.sentry.auto-init"
android:value="false" />

@ -15,6 +15,8 @@ import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.TypedValue;
import android.view.View;
@ -221,6 +223,8 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
rootContainer.setLayoutParams(params);
rootContainer.setY(0F);
});
// reset update module and update module Count in mainapplication
MainApplication.getINSTANCE().resetUpdateModule();
InstallerInitializer.tryGetMagiskPathAsync(new InstallerInitializer.Callback() {
@Override
public void onPathReceived(String path) {
@ -344,17 +348,18 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
});
if (BuildConfig.DEBUG) Timber.i("Apply");
RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilderOnline::appendRemoteModules);
moduleViewListBuilderOnline.applyTo(moduleListOnline, moduleViewAdapterOnline);
// logic to handle updateable modules
moduleViewListBuilder.applyTo(moduleListOnline, moduleViewAdapterOnline);
moduleViewListBuilderOnline.applyTo(moduleListOnline, moduleViewAdapterOnline);
// if moduleViewListBuilderOnline has the upgradeable notification, show a badge on the online repo nav item
if (MainApplication.getINSTANCE().modulesHaveUpdates) {
runOnUiThread(() -> {
final var badge = bottomNavigationView.getOrCreateBadge(1);
Timber.i("Applying badge");
new Handler(Looper.getMainLooper()).post(() -> {
final var badge = bottomNavigationView.getOrCreateBadge(R.id.online_menu_item);
badge.setVisible(true);
badge.setNumber(MainApplication.getINSTANCE().updateModuleCount);
bottomNavigationView.setSelectedItemId(R.id.installed_menu_item);
badge.applyTheme(MainApplication.getInitialApplication().getTheme());
Timber.i("Badge applied");
});
}
Timber.i("Finished app opening state!");
@ -546,6 +551,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
RepoManager.getINSTANCE().updateEnabledStates();
RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilderOnline::appendRemoteModules);
this.moduleViewListBuilderOnline.applyTo(moduleListOnline, moduleViewAdapterOnline);
this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
}, "Repo update thread").start();
}

@ -112,6 +112,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
}
public int updateModuleCount = 0;
public List<String> updateModules = new ArrayList<>();
@StyleRes
private int managerThemeResId = R.style.Theme_MagiskModuleManager;
@ -699,6 +700,12 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
return decryptedKey; // pass to a realm configuration via encryptionKey()
}
public void resetUpdateModule() {
modulesHaveUpdates = false;
updateModuleCount = 0;
updateModules = new ArrayList<>();
}
private static class ReleaseTree extends Timber.Tree {
@Override
protected void log(int priority, String tag, @NonNull String message, Throwable t) {

@ -36,18 +36,16 @@ public enum AndroidacyUtil {
// Avoid logging token
public static String hideToken(@NonNull String url) {
int i = url.lastIndexOf("token=");
if (i == -1)
return url;
int i2 = url.indexOf('&', i);
int i3 = url.indexOf(' ', i);
if (i3 != -1 && i3 < i2)
i2 = i3;
if (i2 == -1) {
return url.substring(0, i + 6) + "<token>";
} else {
return url.substring(0, i + 6) + "<token>" + url.substring(i2);
}
// for token, device_id, and client_id, replace with <hidden> by using replaceAll to match until the next non-alphanumeric character or end
// Also, URL decode
url = Uri.decode(url);
url = url + "&";
url = url.replaceAll("token=[^&]*", "token=<hidden>");
url = url.replaceAll("device_id=[^&]*", "device_id=<hidden>");
url = url.replaceAll("client_id=[^&]*", "client_id=<hidden>");
// remove last & added at the end
url = url.substring(0, url.length() - 1);
return url;
}
public static String getModuleId(String moduleUrl) {

@ -1,6 +1,7 @@
package com.fox2code.mmm.background;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -24,9 +25,16 @@ import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import com.fox2code.mmm.AppUpdateManager;
import com.fox2code.mmm.MainActivity;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
import com.fox2code.mmm.UpdateActivity;
import com.fox2code.mmm.manager.LocalModuleInfo;
import com.fox2code.mmm.manager.ModuleManager;
import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.repo.RepoModule;
import com.fox2code.mmm.utils.io.PropUtils;
import java.util.HashMap;
import java.util.Map;
@ -40,7 +48,39 @@ public class BackgroundUpdateChecker extends Worker {
public static final String NOTIFICATION_CHANNEL_ID = "background_update";
public static final int NOTIFICATION_ID = 1;
public static final String NOTFIICATION_GROUP = "updates";
static final Object lock = new Object(); // Avoid concurrency issues
static final Object lock = new Object(); // Avoid concurrency issuespublic static final String NOTIFICATION_CHANNEL_ID = "background_update";
public static final String NOTIFICATION_CHANNEL_ID_APP = "background_update_app";
private static final int NOTIFICATION_ID_ONGOING = 2;
private static final String NOTIFICATION_CHANNEL_ID_ONGOING = "mmm_background_update";
private static final int NOTIFICATION_ID_APP = 3;
@SuppressLint("RestrictedApi")
private static void postNotificationForAppUpdate(Context context) {
// create the notification channel if not already created
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID_APP, NotificationManagerCompat.IMPORTANCE_HIGH).setName(context.getString(R.string.notification_channel_category_app_update)).setDescription(context.getString(R.string.notification_channel_category_app_update_description)).setGroup(NOTFIICATION_GROUP).build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID_APP);
builder.setSmallIcon(R.drawable.baseline_system_update_24);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setCategory(NotificationCompat.CATEGORY_RECOMMENDATION);
builder.setShowWhen(false);
builder.setOnlyAlertOnce(true);
builder.setOngoing(false);
builder.setAutoCancel(true);
builder.setGroup(NOTFIICATION_GROUP);
// open app on click
Intent intent = new Intent(context, UpdateActivity.class);
// set action to ACTIONS.DOWNLOAD
intent.setAction(String.valueOf(UpdateActivity.ACTIONS.DOWNLOAD));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
builder.setContentIntent(android.app.PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE));
// set summary to Found X
builder.setContentTitle(context.getString(R.string.notification_channel_background_update_app));
builder.setContentText(context.getString(R.string.notification_channel_background_update_app_description));
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(NOTIFICATION_ID_APP, builder.build());
}
}
public BackgroundUpdateChecker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
@ -65,10 +105,77 @@ public class BackgroundUpdateChecker extends Worker {
return;
}
}
// start foreground service
Intent intent = new Intent(context, BackgroundUpdateCheckerService.class);
intent.setAction(BackgroundUpdateCheckerService.ACTION_START_FOREGROUND_SERVICE);
context.startService(intent);
synchronized (lock) {
// post checking notification if notifications are enabled
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID_ONGOING, NotificationManagerCompat.IMPORTANCE_MIN).setName(context.getString(R.string.notification_channel_category_background_update)).setDescription(context.getString(R.string.notification_channel_category_background_update_description)).setGroup(NOTFIICATION_GROUP).build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_baseline_update_24);
builder.setPriority(NotificationCompat.PRIORITY_MIN);
builder.setCategory(NotificationCompat.CATEGORY_SERVICE);
builder.setShowWhen(false);
builder.setOnlyAlertOnce(true);
builder.setOngoing(true);
builder.setAutoCancel(false);
builder.setGroup("update_bg");
builder.setContentTitle(context.getString(R.string.notification_channel_background_update));
builder.setContentText(context.getString(R.string.notification_channel_background_update_description));
notificationManager.notify(NOTIFICATION_ID_ONGOING, builder.build());
} else {
Timber.d("Not posting notification because of missing permission");
}
ModuleManager.getINSTANCE().scanAsync();
RepoManager.getINSTANCE().update(null);
ModuleManager.getINSTANCE().runAfterScan(() -> {
int moduleUpdateCount = 0;
HashMap<String, RepoModule> repoModules = RepoManager.getINSTANCE().getModules();
// hashmap of updateable modules names
HashMap<String, String> updateableModules = new HashMap<>();
for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) {
if ("twrp-keep".equals(localModuleInfo.id)) continue;
// exclude all modules with id's stored in the pref pref_background_update_check_excludes
try {
if (MainApplication.getPreferences("mmm").getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id))
continue;
} catch (Exception ignored) {
}
RepoModule repoModule = repoModules.get(localModuleInfo.id);
localModuleInfo.checkModuleUpdate();
if (localModuleInfo.updateVersionCode > localModuleInfo.versionCode && !PropUtils.isNullString(localModuleInfo.updateVersion)) {
moduleUpdateCount++;
updateableModules.put(localModuleInfo.name, localModuleInfo.version);
} else if (repoModule != null && repoModule.moduleInfo.versionCode > localModuleInfo.versionCode && !PropUtils.isNullString(repoModule.moduleInfo.version)) {
moduleUpdateCount++;
updateableModules.put(localModuleInfo.name, localModuleInfo.version);
}
}
if (moduleUpdateCount != 0) {
Timber.d("Found %d updates", moduleUpdateCount);
postNotification(context, updateableModules, moduleUpdateCount, false);
}
});
// check for app updates
if (MainApplication.getPreferences("mmm").getBoolean("pref_background_update_check_app", false)) {
try {
boolean shouldUpdate = AppUpdateManager.getAppUpdateManager().checkUpdate(true);
if (shouldUpdate) {
Timber.d("Found app update");
postNotificationForAppUpdate(context);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// remove checking notification
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
Timber.d("Removing notification");
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(NOTIFICATION_ID_ONGOING);
}
}
// increment or create counter in shared preferences
MainApplication.getPreferences("mmm").edit().putInt("pref_background_update_counter", MainApplication.getPreferences("mmm").getInt("pref_background_update_counter", 0) + 1).apply();
}
public static void postNotification(Context context, HashMap<String, String> updateable, int updateCount, boolean test) {

@ -1,151 +0,0 @@
package com.fox2code.mmm.background;
import static com.fox2code.mmm.background.BackgroundUpdateChecker.NOTFIICATION_GROUP;
import static com.fox2code.mmm.background.BackgroundUpdateChecker.postNotification;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.IBinder;
import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import com.fox2code.mmm.AppUpdateManager;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
import com.fox2code.mmm.UpdateActivity;
import com.fox2code.mmm.manager.LocalModuleInfo;
import com.fox2code.mmm.manager.ModuleManager;
import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.repo.RepoModule;
import com.fox2code.mmm.utils.io.PropUtils;
import java.util.HashMap;
import timber.log.Timber;
@SuppressLint("RestrictedApi")
public class BackgroundUpdateCheckerService extends Service {
public static final String NOTIFICATION_CHANNEL_ID = "background_update";
public static final String NOTIFICATION_CHANNEL_ID_APP = "background_update_app";
public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE";
static final Object lock = new Object(); // Avoid concurrency issues
private static final int NOTIFICATION_ID_ONGOING = 2;
private static final String NOTIFICATION_CHANNEL_ID_ONGOING = "mmm_background_update";
private static final int NOTIFICATION_ID_APP = 3;
@SuppressLint("RestrictedApi")
private static void postNotificationForAppUpdate(Context context) {
// create the notification channel if not already created
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID_APP, NotificationManagerCompat.IMPORTANCE_HIGH).setName(context.getString(R.string.notification_channel_category_app_update)).setDescription(context.getString(R.string.notification_channel_category_app_update_description)).setGroup(NOTFIICATION_GROUP).build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID_APP);
builder.setSmallIcon(R.drawable.baseline_system_update_24);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setCategory(NotificationCompat.CATEGORY_RECOMMENDATION);
builder.setShowWhen(false);
builder.setOnlyAlertOnce(true);
builder.setOngoing(false);
builder.setAutoCancel(true);
builder.setGroup(NOTFIICATION_GROUP);
// open app on click
Intent intent = new Intent(context, UpdateActivity.class);
// set action to ACTIONS.DOWNLOAD
intent.setAction(String.valueOf(UpdateActivity.ACTIONS.DOWNLOAD));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
builder.setContentIntent(android.app.PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE));
// set summary to Found X
builder.setContentTitle(context.getString(R.string.notification_channel_background_update_app));
builder.setContentText(context.getString(R.string.notification_channel_background_update_app_description));
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(NOTIFICATION_ID_APP, builder.build());
}
}
@Override
public IBinder onBind(Intent intent) {
Context context = MainApplication.getINSTANCE().getApplicationContext();
// check if ACTION_START_FOREGROUND_SERVICE was called
if (intent.getAction() != null && intent.getAction().equals(ACTION_START_FOREGROUND_SERVICE)) {
synchronized (lock) {
// post checking notification if notifications are enabled
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID_ONGOING, NotificationManagerCompat.IMPORTANCE_MIN).setName(context.getString(R.string.notification_channel_category_background_update)).setDescription(context.getString(R.string.notification_channel_category_background_update_description)).setGroup(NOTFIICATION_GROUP).build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_baseline_update_24);
builder.setPriority(NotificationCompat.PRIORITY_MIN);
builder.setCategory(NotificationCompat.CATEGORY_SERVICE);
builder.setShowWhen(false);
builder.setOnlyAlertOnce(true);
builder.setOngoing(true);
builder.setAutoCancel(false);
builder.setGroup("update_bg");
builder.setContentTitle(context.getString(R.string.notification_channel_background_update));
builder.setContentText(context.getString(R.string.notification_channel_background_update_description));
notificationManager.notify(NOTIFICATION_ID_ONGOING, builder.build());
} else {
Timber.d("Not posting notification because of missing permission");
}
ModuleManager.getINSTANCE().scanAsync();
RepoManager.getINSTANCE().update(null);
ModuleManager.getINSTANCE().runAfterScan(() -> {
int moduleUpdateCount = 0;
HashMap<String, RepoModule> repoModules = RepoManager.getINSTANCE().getModules();
// hashmap of updateable modules names
HashMap<String, String> updateableModules = new HashMap<>();
for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) {
if ("twrp-keep".equals(localModuleInfo.id)) continue;
// exclude all modules with id's stored in the pref pref_background_update_check_excludes
try {
if (MainApplication.getPreferences("mmm").getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id))
continue;
} catch (Exception ignored) {
}
RepoModule repoModule = repoModules.get(localModuleInfo.id);
localModuleInfo.checkModuleUpdate();
if (localModuleInfo.updateVersionCode > localModuleInfo.versionCode && !PropUtils.isNullString(localModuleInfo.updateVersion)) {
moduleUpdateCount++;
updateableModules.put(localModuleInfo.name, localModuleInfo.version);
} else if (repoModule != null && repoModule.moduleInfo.versionCode > localModuleInfo.versionCode && !PropUtils.isNullString(repoModule.moduleInfo.version)) {
moduleUpdateCount++;
updateableModules.put(localModuleInfo.name, localModuleInfo.version);
}
}
if (moduleUpdateCount != 0) {
Timber.d("Found %d updates", moduleUpdateCount);
postNotification(context, updateableModules, moduleUpdateCount, false);
}
});
// check for app updates
if (MainApplication.getPreferences("mmm").getBoolean("pref_background_update_check_app", false)) {
try {
boolean shouldUpdate = AppUpdateManager.getAppUpdateManager().checkUpdate(true);
if (shouldUpdate) {
Timber.d("Found app update");
postNotificationForAppUpdate(context);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// remove checking notification
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
Timber.d("Removing notification");
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(NOTIFICATION_ID_ONGOING);
}
}
} else {
Timber.d("No action found");
}
return null;
}
}

@ -27,6 +27,7 @@ import com.fox2code.mmm.MainActivity;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
import com.fox2code.mmm.XHooks;
import com.fox2code.mmm.androidacy.AndroidacyUtil;
import com.fox2code.mmm.module.ActionButtonType;
import com.fox2code.mmm.utils.FastException;
import com.fox2code.mmm.utils.IntentHelper;
@ -168,7 +169,7 @@ public class InstallerActivity extends FoxActivity {
// Set this to the error message if it's a HTTP error
byte[] rawModule;
try {
Timber.i("%s%s", (urlMode ? "Downloading: " : "Loading: "), finalTarget);
Timber.i("%s%s", (urlMode ? "Downloading: " : "Loading: "), AndroidacyUtil.hideToken(finalTarget));
rawModule = urlMode ? Http.doHttpGet(finalTarget, (progress, max, done) -> {
if (max <= 0 && this.progressIndicator.isIndeterminate()) return;
this.runOnUiThread(() -> {

@ -147,7 +147,10 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
this.repoModule.moduleInfo.versionCode)) {
Timber.d("Module %s has update", this.moduleId);
MainApplication.getINSTANCE().modulesHaveUpdates = true;
MainApplication.getINSTANCE().updateModuleCount++;
if (!MainApplication.getINSTANCE().updateModules.contains(this.moduleId)) {
MainApplication.getINSTANCE().updateModules.add(this.moduleId);
MainApplication.getINSTANCE().updateModuleCount++;
}
Timber.d("modulesHaveUpdates = %s, updateModuleCount = %s", MainApplication.getINSTANCE().modulesHaveUpdates, MainApplication.getINSTANCE().updateModuleCount);
return Type.UPDATABLE;
} else {

@ -19,7 +19,7 @@ buildscript {
project.ext.sentry_version = "6.16.0"
dependencies {
//noinspection AndroidGradlePluginVersion
classpath 'com.android.tools.build:gradle:8.0.0-rc01'
classpath 'com.android.tools.build:gradle:8.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20"
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}"

Loading…
Cancel
Save