Lots of changes and code cleanup

- Remove binaries because I was lied to
- Stuff
- Other stuff
- Jeez why did I wait two days to commit, I can't remember anything I did

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/242/head
androidacy-user 1 year ago
parent a1cc1a29c9
commit 71e11600ef

@ -99,7 +99,7 @@ android {
// Get the androidacy client ID from the androidacy.properties // Get the androidacy client ID from the androidacy.properties
Properties properties = new Properties() Properties properties = new Properties()
// If androidacy.properties doesn't exist, use the default client ID which is limited // If androidacy.properties doesn't exist, use the fdroid client ID which is limited
// to 50 requests per minute // to 50 requests per minute
if (project.rootProject.file('androidacy.properties').exists()) { if (project.rootProject.file('androidacy.properties').exists()) {
properties.load(project.rootProject.file('androidacy.properties').newDataInputStream()) properties.load(project.rootProject.file('androidacy.properties').newDataInputStream())
@ -212,7 +212,7 @@ dependencies {
implementation "dev.rikka.rikkax.insets:insets:1.3.0" implementation "dev.rikka.rikkax.insets:insets:1.3.0"
implementation 'com.github.Dimezis:BlurView:version-2.0.2' implementation 'com.github.Dimezis:BlurView:version-2.0.2'
implementation 'com.github.KieronQuinn:MonetCompat:0.4.1' implementation 'com.github.KieronQuinn:MonetCompat:0.4.1'
implementation 'com.github.Fox2Code:FoxCompat:0.1.5' implementation 'com.github.Fox2Code:FoxCompat:0.1.6'
// Update the version code in the root build.gradle // Update the version code in the root build.gradle
implementation "com.mikepenz:aboutlibraries:${latestAboutLibsRelease}" implementation "com.mikepenz:aboutlibraries:${latestAboutLibsRelease}"
@ -220,8 +220,9 @@ dependencies {
implementation 'androidx.work:work-runtime:2.7.1' implementation 'androidx.work:work-runtime:2.7.1'
implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:5.0.0-alpha.10' implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:5.0.0-alpha.10'
implementation 'com.squareup.okhttp3:okhttp-brotli:5.0.0-alpha.10' implementation 'com.squareup.okhttp3:okhttp-brotli:5.0.0-alpha.10'
// Chromium cronet from microG // Chromium cronet from androidacy
implementation fileTree(dir: 'libs', include: '*.jar') implementation 'com.androidacy:cronet-common:108.0.5359.95'
implementation 'com.androidacy:cronet-native:108.0.5359.95'
// Force prefer our own version of Cronet // Force prefer our own version of Cronet
implementation 'com.github.topjohnwu.libsu:io:5.0.1' implementation 'com.github.topjohnwu.libsu:io:5.0.1'
implementation 'com.github.Fox2Code:RosettaX:1.0.9' implementation 'com.github.Fox2Code:RosettaX:1.0.9'

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -21,26 +21,19 @@ import java.util.HashMap;
// See https://docs.github.com/en/rest/reference/repos#releases // See https://docs.github.com/en/rest/reference/repos#releases
public class AppUpdateManager { public class AppUpdateManager {
public static final int FLAG_COMPAT_LOW_QUALITY = 0x0001; public static final int FLAG_COMPAT_LOW_QUALITY = 0x0001;
public static final int FLAG_COMPAT_NO_EXT = 0x0002; public static final int FLAG_COMPAT_NO_EXT = 0x0002;
public static final int FLAG_COMPAT_MAGISK_CMD = 0x0004; public static final int FLAG_COMPAT_MAGISK_CMD = 0x0004;
public static final int FLAG_COMPAT_NEED_32BIT = 0x0008; public static final int FLAG_COMPAT_NEED_32BIT = 0x0008;
public static final int FLAG_COMPAT_MALWARE = 0x0010; public static final int FLAG_COMPAT_MALWARE = 0x0010;
public static final int FLAG_COMPAT_NO_ANSI = 0x0020; public static final int FLAG_COMPAT_NO_ANSI = 0x0020;
public static final int FLAG_COMPAT_FORCE_ANSI = 0x0040; public static final int FLAG_COMPAT_FORCE_ANSI = 0x0040;
public static final int FLAG_COMPAT_FORCE_HIDE = 0x0080; public static final int FLAG_COMPAT_FORCE_HIDE = 0x0080;
public static final int FLAG_COMPAT_MMT_REBORN = 0x0100; public static final int FLAG_COMPAT_MMT_REBORN = 0x0100;
public static final int FLAG_COMPAT_ZIP_WRAPPER = 0x0200; public static final int FLAG_COMPAT_ZIP_WRAPPER = 0x0200;
private static final String TAG = "AppUpdateManager"; private static final String TAG = "AppUpdateManager";
private static final AppUpdateManager INSTANCE = new AppUpdateManager(); private static final AppUpdateManager INSTANCE = new AppUpdateManager();
private static final String RELEASES_API_URL = private static final String RELEASES_API_URL = "https://api.github.com/repos/Fox2Code/FoxMagiskModuleManager/releases";
"https://api.github.com/repos/Fox2Code/FoxMagiskModuleManager/releases"; private static final String COMPAT_API_URL = "https://api.github.com/repos/Fox2Code/FoxMagiskModuleManager/issues/4";
private static final String COMPAT_API_URL =
"https://api.github.com/repos/Fox2Code/FoxMagiskModuleManager/issues/4";
public static AppUpdateManager getAppUpdateManager() {
return INSTANCE;
}
private final HashMap<String, Integer> compatDataId = new HashMap<>(); private final HashMap<String, Integer> compatDataId = new HashMap<>();
private final Object updateLock = new Object(); private final Object updateLock = new Object();
private final File compatFile; private final File compatFile;
@ -49,13 +42,10 @@ public class AppUpdateManager {
private long lastChecked; private long lastChecked;
private boolean preReleaseNewer; private boolean preReleaseNewer;
private boolean lastCheckSuccess; private boolean lastCheckSuccess;
private AppUpdateManager() { private AppUpdateManager() {
this.compatFile = new File(MainApplication.getINSTANCE().getFilesDir(), "compat.txt"); this.compatFile = new File(MainApplication.getINSTANCE().getFilesDir(), "compat.txt");
this.latestRelease = MainApplication.getBootSharedPreferences() this.latestRelease = MainApplication.getBootSharedPreferences().getString("updater_latest_release", BuildConfig.VERSION_NAME);
.getString("updater_latest_release", BuildConfig.VERSION_NAME); this.latestPreRelease = MainApplication.getBootSharedPreferences().getString("updater_latest_pre_release", BuildConfig.VERSION_NAME);
this.latestPreRelease = MainApplication.getBootSharedPreferences()
.getString("updater_latest_pre_release", BuildConfig.VERSION_NAME);
this.lastChecked = 0; this.lastChecked = 0;
this.preReleaseNewer = true; this.preReleaseNewer = true;
if (this.compatFile.isFile()) { if (this.compatFile.isFile()) {
@ -67,24 +57,34 @@ public class AppUpdateManager {
} }
} }
public static AppUpdateManager getAppUpdateManager() {
return INSTANCE;
}
public static int getFlagsForModule(String moduleId) {
return INSTANCE.getCompatibilityFlags(moduleId);
}
public static boolean shouldForceHide(String repoId) {
if (BuildConfig.DEBUG || repoId.startsWith("repo_") || repoId.equals("magisk_alt_repo"))
return false;
return !repoId.startsWith("repo_") && (INSTANCE.getCompatibilityFlags(repoId) & FLAG_COMPAT_FORCE_HIDE) != 0;
}
// Return true if should show a notification // Return true if should show a notification
public boolean checkUpdate(boolean force) { public boolean checkUpdate(boolean force) {
if (!BuildConfig.ENABLE_AUTO_UPDATER) if (!BuildConfig.ENABLE_AUTO_UPDATER) return false;
return false; if (!force && this.peekShouldUpdate()) return true;
if (!force && this.peekShouldUpdate())
return true;
long lastChecked = this.lastChecked; long lastChecked = this.lastChecked;
if (lastChecked != 0 && if (lastChecked != 0 &&
// Avoid spam calls by putting a 60 seconds timer // Avoid spam calls by putting a 60 seconds timer
lastChecked < System.currentTimeMillis() - 60000L) lastChecked < System.currentTimeMillis() - 60000L)
return force && this.peekShouldUpdate(); return force && this.peekShouldUpdate();
synchronized (this.updateLock) { synchronized (this.updateLock) {
if (lastChecked != this.lastChecked) if (lastChecked != this.lastChecked) return this.peekShouldUpdate();
return this.peekShouldUpdate();
boolean preReleaseNewer = true; boolean preReleaseNewer = true;
try { try {
JSONArray releases = new JSONArray(new String(Http.doHttpGet( JSONArray releases = new JSONArray(new String(Http.doHttpGet(RELEASES_API_URL, false), StandardCharsets.UTF_8));
RELEASES_API_URL, false), StandardCharsets.UTF_8));
String latestRelease = null, latestPreRelease = null; String latestRelease = null, latestPreRelease = null;
for (int i = 0; i < releases.length(); i++) { for (int i = 0; i < releases.length(); i++) {
JSONObject release = releases.getJSONObject(i); JSONObject release = releases.getJSONObject(i);
@ -92,22 +92,18 @@ public class AppUpdateManager {
if (release.getBoolean("draft")) continue; if (release.getBoolean("draft")) continue;
boolean preRelease = release.getBoolean("prerelease"); boolean preRelease = release.getBoolean("prerelease");
String version = release.getString("tag_name"); String version = release.getString("tag_name");
if (version.startsWith("v")) if (version.startsWith("v")) version = version.substring(1);
version = version.substring(1);
if (preRelease) { if (preRelease) {
if (latestPreRelease == null) if (latestPreRelease == null) latestPreRelease = version;
latestPreRelease = version;
} else if (latestRelease == null) { } else if (latestRelease == null) {
latestRelease = version; latestRelease = version;
if (latestPreRelease == null) if (latestPreRelease == null) preReleaseNewer = false;
preReleaseNewer = false;
} }
if (latestRelease != null && latestPreRelease != null) { if (latestRelease != null && latestPreRelease != null) {
break; // We read everything we needed to read. break; // We read everything we needed to read.
} }
} }
if (latestRelease != null) if (latestRelease != null) this.latestRelease = latestRelease;
this.latestRelease = latestRelease;
if (latestPreRelease != null) { if (latestPreRelease != null) {
this.latestPreRelease = latestPreRelease; this.latestPreRelease = latestPreRelease;
this.preReleaseNewer = preReleaseNewer; this.preReleaseNewer = preReleaseNewer;
@ -131,45 +127,42 @@ public class AppUpdateManager {
public void checkUpdateCompat() { public void checkUpdateCompat() {
if (this.compatFile.exists()) { if (this.compatFile.exists()) {
long lastUpdate = this.compatFile.lastModified(); long lastUpdate = this.compatFile.lastModified();
if (lastUpdate <= System.currentTimeMillis() && if (lastUpdate <= System.currentTimeMillis() && lastUpdate + 600_000L > System.currentTimeMillis()) {
lastUpdate + 600_000L > System.currentTimeMillis()) {
return; // Skip update return; // Skip update
} }
} }
try { try {
JSONObject object = new JSONObject(new String(Http.doHttpGet( JSONObject object = new JSONObject(new String(Http.doHttpGet(COMPAT_API_URL, false), StandardCharsets.UTF_8));
COMPAT_API_URL, false), StandardCharsets.UTF_8));
if (object.isNull("body")) { if (object.isNull("body")) {
compatDataId.clear(); compatDataId.clear();
Files.write(compatFile, new byte[0]); Files.write(compatFile, new byte[0]);
return; return;
} }
byte[] rawData = object.getString("body") byte[] rawData = object.getString("body").getBytes(StandardCharsets.UTF_8);
.getBytes(StandardCharsets.UTF_8);
this.parseCompatibilityFlags(new ByteArrayInputStream(rawData)); this.parseCompatibilityFlags(new ByteArrayInputStream(rawData));
Files.write(compatFile, rawData); Files.write(compatFile, rawData);
if (!BuildConfig.ENABLE_AUTO_UPDATER) if (!BuildConfig.ENABLE_AUTO_UPDATER) this.lastCheckSuccess = true;
this.lastCheckSuccess = true;
} catch (Exception e) { } catch (Exception e) {
if (!BuildConfig.ENABLE_AUTO_UPDATER) if (!BuildConfig.ENABLE_AUTO_UPDATER) this.lastCheckSuccess = false;
this.lastCheckSuccess = false;
Log.e("AppUpdateManager", "Failed to update compat list", e); Log.e("AppUpdateManager", "Failed to update compat list", e);
} }
} }
public boolean peekShouldUpdate() { public boolean peekShouldUpdate() {
if (!BuildConfig.ENABLE_AUTO_UPDATER) if (!BuildConfig.ENABLE_AUTO_UPDATER) return false;
return false; // Convert both BuildConfig.VERSION_NAME and latestRelease to int
return !(BuildConfig.VERSION_NAME.equals(this.latestRelease) || int currentVersion = 0, latestVersion = 0;
(this.preReleaseNewer && try {
BuildConfig.VERSION_NAME.equals(this.latestPreRelease))); currentVersion = Integer.parseInt(BuildConfig.VERSION_NAME.replace(".", ""));
latestVersion = Integer.parseInt(this.latestRelease.replace(".", ""));
} catch (NumberFormatException ignored) {
}
return currentVersion < latestVersion || (this.preReleaseNewer && currentVersion < Integer.parseInt(this.latestPreRelease.replace(".", "")));
} }
public boolean peekHasUpdate() { public boolean peekHasUpdate() {
if (!BuildConfig.ENABLE_AUTO_UPDATER) if (!BuildConfig.ENABLE_AUTO_UPDATER) return false;
return false; return !BuildConfig.VERSION_NAME.equals(this.preReleaseNewer ? this.latestPreRelease : this.latestRelease);
return !BuildConfig.VERSION_NAME.equals(this.preReleaseNewer ?
this.latestPreRelease : this.latestRelease);
} }
public boolean isLastCheckSuccess() { public boolean isLastCheckSuccess() {
@ -178,8 +171,7 @@ public class AppUpdateManager {
private void parseCompatibilityFlags(InputStream inputStream) throws IOException { private void parseCompatibilityFlags(InputStream inputStream) throws IOException {
compatDataId.clear(); compatDataId.clear();
BufferedReader bufferedReader = new BufferedReader( BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line; String line;
while ((line = bufferedReader.readLine()) != null) { while ((line = bufferedReader.readLine()) != null) {
line = line.trim(); line = line.trim();
@ -231,16 +223,4 @@ public class AppUpdateManager {
Integer compatFlags = compatDataId.get(moduleId); Integer compatFlags = compatDataId.get(moduleId);
return compatFlags == null ? 0 : compatFlags; return compatFlags == null ? 0 : compatFlags;
} }
public static int getFlagsForModule(String moduleId) {
return INSTANCE.getCompatibilityFlags(moduleId);
}
public static boolean shouldForceHide(String repoId) {
if (BuildConfig.DEBUG || repoId.startsWith("repo_") ||
repoId.equals("magisk_alt_repo")) return false;
return !repoId.startsWith("repo_") &&
(INSTANCE.getCompatibilityFlags(repoId) &
FLAG_COMPAT_FORCE_HIDE) != 0;
}
} }

@ -158,11 +158,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
moduleViewListBuilder.addNotification(NotificationType.MAGISK_OUTDATED); moduleViewListBuilder.addNotification(NotificationType.MAGISK_OUTDATED);
if (!MainApplication.isShowcaseMode()) if (!MainApplication.isShowcaseMode())
moduleViewListBuilder.addNotification(NotificationType.INSTALL_FROM_STORAGE); moduleViewListBuilder.addNotification(NotificationType.INSTALL_FROM_STORAGE);
noodleDebug.setEnabled(noodleDebugState);
noodleDebug.bind();
noodleDebug.push("Ensure Permissions");
ensurePermissions(); ensurePermissions();
noodleDebug.pop();
ModuleManager.getINSTANCE().scan(); ModuleManager.getINSTANCE().scan();
ModuleManager.getINSTANCE().runAfterScan(moduleViewListBuilder::appendInstalledModules); ModuleManager.getINSTANCE().runAfterScan(moduleViewListBuilder::appendInstalledModules);
this.commonNext(); this.commonNext();
@ -171,21 +167,17 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
@Override @Override
public void onFailure(int error) { public void onFailure(int error) {
Log.i(TAG, "Failed to get magisk path!"); Log.i(TAG, "Failed to get magisk path!");
noodleDebug.setEnabled(noodleDebugState);
noodleDebug.bind();
moduleViewListBuilder.addNotification(InstallerInitializer.getErrorNotification()); moduleViewListBuilder.addNotification(InstallerInitializer.getErrorNotification());
this.commonNext(); this.commonNext();
} }
public void commonNext() { public void commonNext() {
NoodleDebug noodleDebug = NoodleDebug.getNoodleDebug();
swipeRefreshBlocker = System.currentTimeMillis() + 5_000L; swipeRefreshBlocker = System.currentTimeMillis() + 5_000L;
updateScreenInsets(); // Fix an edge case updateScreenInsets(); // Fix an edge case
if (MainApplication.isShowcaseMode()) if (MainApplication.isShowcaseMode())
moduleViewListBuilder.addNotification(NotificationType.SHOWCASE_MODE); moduleViewListBuilder.addNotification(NotificationType.SHOWCASE_MODE);
if (!Http.hasWebView()) // Check Http for WebView availability if (!Http.hasWebView()) // Check Http for WebView availability
moduleViewListBuilder.addNotification(NotificationType.NO_WEB_VIEW); moduleViewListBuilder.addNotification(NotificationType.NO_WEB_VIEW);
noodleDebug.push("Apply");
moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter); moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
runOnUiThread(() -> { runOnUiThread(() -> {
progressIndicator.setIndeterminate(false); progressIndicator.setIndeterminate(false);
@ -194,14 +186,14 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
updateScreenInsets(getResources().getConfiguration()); updateScreenInsets(getResources().getConfiguration());
}); });
Log.i(TAG, "Scanning for modules!"); Log.i(TAG, "Scanning for modules!");
noodleDebug.replace("Initialize Update"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Initialize Update");
final int max = ModuleManager.getINSTANCE().getUpdatableModuleCount(); final int max = ModuleManager.getINSTANCE().getUpdatableModuleCount();
if (RepoManager.getINSTANCE().getCustomRepoManager().needUpdate()) { if (RepoManager.getINSTANCE().getCustomRepoManager().needUpdate()) {
Log.w(TAG, "Need update on create?"); Log.w(TAG, "Need update on create?");
} }
noodleDebug.replace("Check Update Compat"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check Update Compat");
AppUpdateManager.getAppUpdateManager().checkUpdateCompat(); AppUpdateManager.getAppUpdateManager().checkUpdateCompat();
noodleDebug.replace("Check Update"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check Update");
RepoManager.getINSTANCE().update(value -> runOnUiThread(max == 0 ? () -> progressIndicator.setProgressCompat((int) (value * PRECISION), true) : () -> progressIndicator.setProgressCompat((int) (value * PRECISION * 0.75F), true))); RepoManager.getINSTANCE().update(value -> runOnUiThread(max == 0 ? () -> progressIndicator.setProgressCompat((int) (value * PRECISION), true) : () -> progressIndicator.setProgressCompat((int) (value * PRECISION * 0.75F), true)));
NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder); NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder);
if (!NotificationType.NO_INTERNET.shouldRemove()) { if (!NotificationType.NO_INTERNET.shouldRemove()) {
@ -211,16 +203,16 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
} else { } else {
// Compatibility data still needs to be updated // Compatibility data still needs to be updated
AppUpdateManager appUpdateManager = AppUpdateManager.getAppUpdateManager(); AppUpdateManager appUpdateManager = AppUpdateManager.getAppUpdateManager();
noodleDebug.replace("Check App Update"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check App Update");
if (BuildConfig.ENABLE_AUTO_UPDATER && appUpdateManager.checkUpdate(true)) if (BuildConfig.ENABLE_AUTO_UPDATER && appUpdateManager.checkUpdate(true))
moduleViewListBuilder.addNotification(NotificationType.UPDATE_AVAILABLE); moduleViewListBuilder.addNotification(NotificationType.UPDATE_AVAILABLE);
noodleDebug.replace("Check Json Update"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check Json Update");
if (max != 0) { if (max != 0) {
int current = 0; int current = 0;
noodleDebug.push(""); // noodleDebug.push("");
for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) { for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) {
if (localModuleInfo.updateJson != null) { if (localModuleInfo.updateJson != null) {
noodleDebug.replace(localModuleInfo.id); if (BuildConfig.DEBUG) Log.d("NoodleDebug", localModuleInfo.id);
try { try {
localModuleInfo.checkModuleUpdate(); localModuleInfo.checkModuleUpdate();
} catch (Exception e) { } catch (Exception e) {
@ -231,7 +223,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
runOnUiThread(() -> progressIndicator.setProgressCompat((int) ((1F * currentTmp / max) * PRECISION * 0.25F + (PRECISION * 0.75F)), true)); runOnUiThread(() -> progressIndicator.setProgressCompat((int) ((1F * currentTmp / max) * PRECISION * 0.25F + (PRECISION * 0.75F)), true));
} }
} }
noodleDebug.pop();
} }
} }
runOnUiThread(() -> { runOnUiThread(() -> {
@ -241,12 +232,11 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
setActionBarBackground(null); setActionBarBackground(null);
updateScreenInsets(getResources().getConfiguration()); updateScreenInsets(getResources().getConfiguration());
}); });
noodleDebug.replace("Apply"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Apply");
RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendRemoteModules); RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendRemoteModules);
moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter); moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
noodleDebug.pop();
Log.i(TAG, "Finished app opening state!"); Log.i(TAG, "Finished app opening state!");
noodleDebug.unbind(); // noodleDebug.unbind();
} }
}, true); }, true);
ExternalHelper.INSTANCE.refreshHelper(this); ExternalHelper.INSTANCE.refreshHelper(this);
@ -328,8 +318,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
moduleViewListBuilder.addNotification(NotificationType.MAGISK_OUTDATED); moduleViewListBuilder.addNotification(NotificationType.MAGISK_OUTDATED);
if (!MainApplication.isShowcaseMode()) if (!MainApplication.isShowcaseMode())
moduleViewListBuilder.addNotification(NotificationType.INSTALL_FROM_STORAGE); moduleViewListBuilder.addNotification(NotificationType.INSTALL_FROM_STORAGE);
noodleDebug.setEnabled(noodleDebugState);
noodleDebug.bind();
ModuleManager.getINSTANCE().scan(); ModuleManager.getINSTANCE().scan();
ModuleManager.getINSTANCE().runAfterScan(moduleViewListBuilder::appendInstalledModules); ModuleManager.getINSTANCE().runAfterScan(moduleViewListBuilder::appendInstalledModules);
this.commonNext(); this.commonNext();
@ -345,7 +333,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
public void commonNext() { public void commonNext() {
Log.i(TAG, "Common Before"); Log.i(TAG, "Common Before");
NoodleDebug noodleDebug = NoodleDebug.getNoodleDebug();
if (MainApplication.isShowcaseMode()) if (MainApplication.isShowcaseMode())
moduleViewListBuilder.addNotification(NotificationType.SHOWCASE_MODE); moduleViewListBuilder.addNotification(NotificationType.SHOWCASE_MODE);
NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder); NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder);
@ -354,26 +341,23 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
else if (AppUpdateManager.getAppUpdateManager().checkUpdate(false)) else if (AppUpdateManager.getAppUpdateManager().checkUpdate(false))
moduleViewListBuilder.addNotification(NotificationType.UPDATE_AVAILABLE); moduleViewListBuilder.addNotification(NotificationType.UPDATE_AVAILABLE);
RepoManager.getINSTANCE().updateEnabledStates(); RepoManager.getINSTANCE().updateEnabledStates();
noodleDebug.push("");
if (RepoManager.getINSTANCE().getCustomRepoManager().needUpdate()) { if (RepoManager.getINSTANCE().getCustomRepoManager().needUpdate()) {
runOnUiThread(() -> { runOnUiThread(() -> {
progressIndicator.setIndeterminate(false); progressIndicator.setIndeterminate(false);
progressIndicator.setMax(PRECISION); progressIndicator.setMax(PRECISION);
}); });
noodleDebug.replace("Check Update"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check Update");
RepoManager.getINSTANCE().update(value -> runOnUiThread(() -> progressIndicator.setProgressCompat((int) (value * PRECISION), true))); RepoManager.getINSTANCE().update(value -> runOnUiThread(() -> progressIndicator.setProgressCompat((int) (value * PRECISION), true)));
runOnUiThread(() -> { runOnUiThread(() -> {
progressIndicator.setProgressCompat(PRECISION, true); progressIndicator.setProgressCompat(PRECISION, true);
progressIndicator.setVisibility(View.GONE); progressIndicator.setVisibility(View.GONE);
}); });
} }
noodleDebug.replace("Apply"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Apply");
RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendRemoteModules); RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendRemoteModules);
Log.i(TAG, "Common Before applyTo"); Log.i(TAG, "Common Before applyTo");
moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter); moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
noodleDebug.pop();
Log.i(TAG, "Common After"); Log.i(TAG, "Common After");
noodleDebug.unbind();
} }
}); });
this.initMode = false; this.initMode = false;
@ -390,33 +374,33 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
this.swipeRefreshLayout.setRefreshing(false); this.swipeRefreshLayout.setRefreshing(false);
return; // Do not double scan return; // Do not double scan
} }
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Refresh");
this.progressIndicator.setVisibility(View.VISIBLE); this.progressIndicator.setVisibility(View.VISIBLE);
this.progressIndicator.setProgressCompat(0, false); this.progressIndicator.setProgressCompat(0, false);
this.swipeRefreshBlocker = System.currentTimeMillis() + 5_000L; this.swipeRefreshBlocker = System.currentTimeMillis() + 5_000L;
// this.swipeRefreshLayout.setRefreshing(true); ?? // this.swipeRefreshLayout.setRefreshing(true); ??
new Thread(() -> { new Thread(() -> {
noodleDebug.setEnabled(noodleDebugState);
NoodleDebug noodleDebug = this.noodleDebug.bind();
Http.cleanDnsCache(); // Allow DNS reload from network Http.cleanDnsCache(); // Allow DNS reload from network
noodleDebug.push("Check Update"); // noodleDebug.push("Check Update");
final int max = ModuleManager.getINSTANCE().getUpdatableModuleCount(); final int max = ModuleManager.getINSTANCE().getUpdatableModuleCount();
RepoManager.getINSTANCE().update(value -> runOnUiThread(max == 0 ? () -> progressIndicator.setProgressCompat((int) (value * PRECISION), true) : () -> progressIndicator.setProgressCompat((int) (value * PRECISION * 0.75F), true))); RepoManager.getINSTANCE().update(value -> runOnUiThread(max == 0 ? () -> progressIndicator.setProgressCompat((int) (value * PRECISION), true) : () -> progressIndicator.setProgressCompat((int) (value * PRECISION * 0.75F), true)));
NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder); NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder);
if (!NotificationType.NO_INTERNET.shouldRemove()) { if (!NotificationType.NO_INTERNET.shouldRemove()) {
moduleViewListBuilder.addNotification(NotificationType.NO_INTERNET); moduleViewListBuilder.addNotification(NotificationType.NO_INTERNET);
} else if (!NotificationType.REPO_UPDATE_FAILED.shouldRemove()) {
moduleViewListBuilder.addNotification(NotificationType.REPO_UPDATE_FAILED);
} else { } else {
// Compatibility data still needs to be updated // Compatibility data still needs to be updated
AppUpdateManager appUpdateManager = AppUpdateManager.getAppUpdateManager(); AppUpdateManager appUpdateManager = AppUpdateManager.getAppUpdateManager();
// noodleDebug.replace("Check App Update"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check App Update");
if (BuildConfig.ENABLE_AUTO_UPDATER && appUpdateManager.checkUpdate(true)) if (BuildConfig.ENABLE_AUTO_UPDATER && appUpdateManager.checkUpdate(true))
moduleViewListBuilder.addNotification(NotificationType.UPDATE_AVAILABLE); moduleViewListBuilder.addNotification(NotificationType.UPDATE_AVAILABLE);
// noodleDebug.replace("Check Json Update"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check Json Update");
if (max != 0) { if (max != 0) {
int current = 0; int current = 0;
noodleDebug.push("");
for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) { for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) {
if (localModuleInfo.updateJson != null) { if (localModuleInfo.updateJson != null) {
noodleDebug.replace(localModuleInfo.id); if (BuildConfig.DEBUG) Log.d("NoodleDebug", localModuleInfo.id);
try { try {
localModuleInfo.checkModuleUpdate(); localModuleInfo.checkModuleUpdate();
} catch (Exception e) { } catch (Exception e) {
@ -427,23 +411,20 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
runOnUiThread(() -> progressIndicator.setProgressCompat((int) ((1F * currentTmp / max) * PRECISION * 0.25F + (PRECISION * 0.75F)), true)); runOnUiThread(() -> progressIndicator.setProgressCompat((int) ((1F * currentTmp / max) * PRECISION * 0.25F + (PRECISION * 0.75F)), true));
} }
} }
noodleDebug.pop();
} }
} }
// noodleDebug.replace("Apply"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Apply");
runOnUiThread(() -> { runOnUiThread(() -> {
this.progressIndicator.setVisibility(View.GONE); this.progressIndicator.setVisibility(View.GONE);
this.swipeRefreshLayout.setRefreshing(false); this.swipeRefreshLayout.setRefreshing(false);
}); });
NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder); NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder);
if (!NotificationType.NO_INTERNET.shouldRemove()) {
this.moduleViewListBuilder.addNotification(NotificationType.NO_INTERNET);
}
RepoManager.getINSTANCE().updateEnabledStates(); RepoManager.getINSTANCE().updateEnabledStates();
RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendRemoteModules); RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendRemoteModules);
this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter); this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
// noodleDebug.pop(); /*
// noodleDebug.unbind(); noodleDebug.unbind();
*/
}, "Repo update thread").start(); }, "Repo update thread").start();
} }

@ -60,6 +60,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
private static SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString, timeFormatLocale); private static SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString, timeFormatLocale);
private static SharedPreferences bootSharedPreferences; private static SharedPreferences bootSharedPreferences;
private static String relPackageName = BuildConfig.APPLICATION_ID; private static String relPackageName = BuildConfig.APPLICATION_ID;
@SuppressLint("StaticFieldLeak")
private static MainApplication INSTANCE; private static MainApplication INSTANCE;
private static boolean firstBoot; private static boolean firstBoot;

@ -191,6 +191,7 @@ public enum NotificationType implements NotificationTypeCst {
} }
public boolean shouldRemove() { public boolean shouldRemove() {
// By default, remove the notification`
return false; return false;
} }

@ -184,7 +184,8 @@ public final class AndroidacyRepoData extends RepoData {
} }
String deviceId = generateDeviceId(); String deviceId = generateDeviceId();
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
if (this.androidacyBlockade > time) return false; if (this.androidacyBlockade > time) return true; // fake it till you make it. Basically,
// don'e fail just becaue we're rate limited. API and web rate limits are different.
this.androidacyBlockade = time + 30_000L; this.androidacyBlockade = time + 30_000L;
try { try {
if (this.token == null) { if (this.token == null) {
@ -249,6 +250,9 @@ public final class AndroidacyRepoData extends RepoData {
@Override @Override
protected List<RepoModule> populate(JSONObject jsonObject) throws JSONException, NoSuchAlgorithmException { protected List<RepoModule> populate(JSONObject jsonObject) throws JSONException, NoSuchAlgorithmException {
if (BuildConfig.DEBUG) {
Log.d(TAG, "AndroidacyRepoData populate start");
}
if (!jsonObject.getString("status").equals("success")) if (!jsonObject.getString("status").equals("success"))
throw new JSONException("Response is not a success!"); throw new JSONException("Response is not a success!");
String name = jsonObject.optString("name", "Androidacy Modules Repo"); String name = jsonObject.optString("name", "Androidacy Modules Repo");
@ -326,7 +330,9 @@ public final class AndroidacyRepoData extends RepoData {
String config = jsonObject.optString("config", ""); String config = jsonObject.optString("config", "");
moduleInfo.config = config.isEmpty() ? null : config; moduleInfo.config = config.isEmpty() ? null : config;
PropUtils.applyFallbacks(moduleInfo); // Apply fallbacks PropUtils.applyFallbacks(moduleInfo); // Apply fallbacks
Log.d(TAG, "Module " + moduleInfo.name + " " + moduleInfo.id + " " + moduleInfo.version + " " + moduleInfo.versionCode); // Log.d(TAG,
// "Module " + moduleInfo.name + " " + moduleInfo.id + " " + moduleInfo
// .version + " " + moduleInfo.versionCode);
} }
Iterator<RepoModule> moduleInfoIterator = this.moduleHashMap.values().iterator(); Iterator<RepoModule> moduleInfoIterator = this.moduleHashMap.values().iterator();
while (moduleInfoIterator.hasNext()) { while (moduleInfoIterator.hasNext()) {

@ -29,7 +29,6 @@ import com.fox2code.mmm.utils.ExternalHelper;
import com.fox2code.mmm.utils.Files; import com.fox2code.mmm.utils.Files;
import com.fox2code.mmm.utils.Hashes; import com.fox2code.mmm.utils.Hashes;
import com.fox2code.mmm.utils.IntentHelper; import com.fox2code.mmm.utils.IntentHelper;
import com.fox2code.mmm.utils.PropUtils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.File; import java.io.File;
@ -44,11 +43,11 @@ public class AndroidacyWebAPI {
private static final int MAX_COMPAT_MODE = 1; private static final int MAX_COMPAT_MODE = 1;
private final AndroidacyActivity activity; private final AndroidacyActivity activity;
private final boolean allowInstall; private final boolean allowInstall;
private boolean allowHideNote = true;
boolean consumedAction; boolean consumedAction;
boolean downloadMode; boolean downloadMode;
int effectiveCompatMode; int effectiveCompatMode;
int notifiedCompatMode; int notifiedCompatMode;
private boolean allowHideNote = true;
public AndroidacyWebAPI(AndroidacyActivity activity, boolean allowInstall) { public AndroidacyWebAPI(AndroidacyActivity activity, boolean allowInstall) {
this.activity = activity; this.activity = activity;
@ -113,7 +112,7 @@ public class AndroidacyWebAPI {
final boolean fMMTReborn = mmtReborn; final boolean fMMTReborn = mmtReborn;
builder.setPositiveButton(hasUpdate ? builder.setPositiveButton(hasUpdate ?
R.string.update_module : R.string.install_module, (x, y) -> IntentHelper.openInstaller(this.activity, R.string.update_module : R.string.install_module, (x, y) -> IntentHelper.openInstaller(this.activity,
fModuleUrl, fTitle, fConfig, fChecksum, fMMTReborn)); fModuleUrl, fTitle, fConfig, fChecksum, fMMTReborn));
} }
builder.setOnCancelListener(dialogInterface -> { builder.setOnCancelListener(dialogInterface -> {
if (!this.activity.backOnResume) if (!this.activity.backOnResume)
@ -299,7 +298,7 @@ public class AndroidacyWebAPI {
return; return;
} }
// Get moduleTitle from url // Get moduleTitle from url
String moduleTitle = AndroidacyUtil.getModuleTitle(moduleUrl); String moduleTitle = AndroidacyUtil.getModuleTitle(moduleUrl);
this.openNativeModuleDialogRaw(moduleUrl, moduleId, moduleTitle, checksum, this.canInstall()); this.openNativeModuleDialogRaw(moduleUrl, moduleId, moduleTitle, checksum, this.canInstall());
} }

@ -4,6 +4,7 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.StrictMode;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.NotificationChannelCompat; import androidx.core.app.NotificationChannelCompat;
@ -53,6 +54,9 @@ public class BackgroundUpdateChecker extends Worker {
} }
static void doCheck(Context context) { static void doCheck(Context context) {
// This is actually not recommended but it's the only way to do it
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Thread.currentThread().setPriority(Thread.MIN_PRIORITY); Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
ModuleManager.getINSTANCE().scanAsync(); ModuleManager.getINSTANCE().scanAsync();
RepoManager.getINSTANCE().update(null); RepoManager.getINSTANCE().update(null);

@ -5,6 +5,7 @@ import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.fox2code.mmm.BuildConfig;
import com.fox2code.mmm.MainApplication; import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.installer.InstallerInitializer; import com.fox2code.mmm.installer.InstallerInitializer;
import com.fox2code.mmm.utils.Http; import com.fox2code.mmm.utils.Http;
@ -70,13 +71,13 @@ public final class ModuleManager extends SyncManager {
if (!FORCE_NEED_FALLBACK && needFallback) { if (!FORCE_NEED_FALLBACK && needFallback) {
Log.e(TAG, "Failed to detect modules folder, using fallback instead."); Log.e(TAG, "Failed to detect modules folder, using fallback instead.");
} }
noodleDebug.replace("Scan"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Scan");
if (modules != null) { if (modules != null) {
noodleDebug.push(""); noodleDebug.push("");
for (String module : modules) { for (String module : modules) {
if (!new SuFile("/data/adb/modules/" + module).isDirectory()) if (!new SuFile("/data/adb/modules/" + module).isDirectory())
continue; // Ignore non directory files inside modules folder continue; // Ignore non directory files inside modules folder
noodleDebug.replace(module); if (BuildConfig.DEBUG) Log.d("NoodleDebug", module);
LocalModuleInfo moduleInfo = moduleInfos.get(module); LocalModuleInfo moduleInfo = moduleInfos.get(module);
if (moduleInfo == null) { if (moduleInfo == null) {
moduleInfo = new LocalModuleInfo(module); moduleInfo = new LocalModuleInfo(module);
@ -118,16 +119,15 @@ public final class ModuleManager extends SyncManager {
moduleInfo.flags |= FLAG_MM_INVALID; moduleInfo.flags |= FLAG_MM_INVALID;
} }
} }
noodleDebug.pop();
} }
noodleDebug.replace("Scan update"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Scan update");
String[] modules_update = new SuFile("/data/adb/modules_update").list(); String[] modules_update = new SuFile("/data/adb/modules_update").list();
if (modules_update != null) { if (modules_update != null) {
noodleDebug.push(""); noodleDebug.push("");
for (String module : modules_update) { for (String module : modules_update) {
if (!new SuFile("/data/adb/modules_update/" + module).isDirectory()) if (!new SuFile("/data/adb/modules_update/" + module).isDirectory())
continue; // Ignore non directory files inside modules folder continue; // Ignore non directory files inside modules folder
noodleDebug.replace(module); if (BuildConfig.DEBUG) Log.d("NoodleDebug", module);
LocalModuleInfo moduleInfo = moduleInfos.get(module); LocalModuleInfo moduleInfo = moduleInfos.get(module);
if (moduleInfo == null) { if (moduleInfo == null) {
moduleInfo = new LocalModuleInfo(module); moduleInfo = new LocalModuleInfo(module);
@ -143,16 +143,15 @@ public final class ModuleManager extends SyncManager {
moduleInfo.flags |= FLAG_MM_INVALID; moduleInfo.flags |= FLAG_MM_INVALID;
} }
} }
noodleDebug.pop();
} }
noodleDebug.replace("Finalize scan"); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Finalize scan");
this.updatableModuleCount = 0; this.updatableModuleCount = 0;
Iterator<LocalModuleInfo> moduleInfoIterator = Iterator<LocalModuleInfo> moduleInfoIterator =
this.moduleInfos.values().iterator(); this.moduleInfos.values().iterator();
noodleDebug.push(""); noodleDebug.push("");
while (moduleInfoIterator.hasNext()) { while (moduleInfoIterator.hasNext()) {
LocalModuleInfo moduleInfo = moduleInfoIterator.next(); LocalModuleInfo moduleInfo = moduleInfoIterator.next();
noodleDebug.replace(moduleInfo.id); if (BuildConfig.DEBUG) Log.d("NoodleDebug", moduleInfo.id);
if ((moduleInfo.flags & FLAG_MM_UNPROCESSED) != 0) { if ((moduleInfo.flags & FLAG_MM_UNPROCESSED) != 0) {
moduleInfoIterator.remove(); moduleInfoIterator.remove();
continue; // Don't process fallbacks if unreferenced continue; // Don't process fallbacks if unreferenced
@ -174,12 +173,10 @@ public final class ModuleManager extends SyncManager {
} }
moduleInfo.verify(); moduleInfo.verify();
} }
noodleDebug.pop();
if (firstScan) { if (firstScan) {
editor.putBoolean("mm_first_scan", false); editor.putBoolean("mm_first_scan", false);
editor.apply(); editor.apply();
} }
noodleDebug.pop();
} }
public HashMap<String, LocalModuleInfo> getModules() { public HashMap<String, LocalModuleInfo> getModules() {

@ -1,12 +1,18 @@
package com.fox2code.mmm.repo; package com.fox2code.mmm.repo;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.fox2code.mmm.BuildConfig;
import com.fox2code.mmm.MainApplication; import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
import com.fox2code.mmm.XHooks; import com.fox2code.mmm.XHooks;
import com.fox2code.mmm.XRepo; import com.fox2code.mmm.XRepo;
import com.fox2code.mmm.androidacy.AndroidacyRepoData; import com.fox2code.mmm.androidacy.AndroidacyRepoData;
@ -14,9 +20,9 @@ import com.fox2code.mmm.manager.ModuleInfo;
import com.fox2code.mmm.utils.Files; import com.fox2code.mmm.utils.Files;
import com.fox2code.mmm.utils.Hashes; import com.fox2code.mmm.utils.Hashes;
import com.fox2code.mmm.utils.Http; import com.fox2code.mmm.utils.Http;
import com.fox2code.mmm.utils.NoodleDebug;
import com.fox2code.mmm.utils.PropUtils; import com.fox2code.mmm.utils.PropUtils;
import com.fox2code.mmm.utils.SyncManager; import com.fox2code.mmm.utils.SyncManager;
import com.google.android.material.snackbar.Snackbar;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -28,6 +34,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Objects;
public final class RepoManager extends SyncManager { public final class RepoManager extends SyncManager {
public static final String MAGISK_REPO = public static final String MAGISK_REPO =
@ -64,10 +71,10 @@ public final class RepoManager extends SyncManager {
private final HashMap<String, RepoModule> modules; private final HashMap<String, RepoModule> modules;
private final AndroidacyRepoData androidacyRepoData; private final AndroidacyRepoData androidacyRepoData;
private final CustomRepoManager customRepoManager; private final CustomRepoManager customRepoManager;
public String repoLastErrorName = null;
private boolean hasInternet; private boolean hasInternet;
private boolean repoLastError = false;
private boolean initialized; private boolean initialized;
public String repoLastErrorName = null; private boolean repoLastSuccess;
private RepoManager(MainApplication mainApplication) { private RepoManager(MainApplication mainApplication) {
INSTANCE = this; // Set early fox XHooks INSTANCE = this; // Set early fox XHooks
@ -227,10 +234,8 @@ public final class RepoManager extends SyncManager {
return repoData; return repoData;
} }
@SuppressLint("StringFormatInvalid")
protected void scanInternal(@NonNull UpdateListener updateListener) { protected void scanInternal(@NonNull UpdateListener updateListener) {
NoodleDebug noodleDebug = NoodleDebug.getNoodleDebug();
// First, check if we have internet connection
noodleDebug.push("Downloading indexes");
this.modules.clear(); this.modules.clear();
updateListener.update(0D); updateListener.update(0D);
// Using LinkedHashSet to deduplicate Androidacy entry. // Using LinkedHashSet to deduplicate Androidacy entry.
@ -238,26 +243,27 @@ public final class RepoManager extends SyncManager {
this.repoData.values()).toArray(new RepoData[0]); this.repoData.values()).toArray(new RepoData[0]);
RepoUpdater[] repoUpdaters = new RepoUpdater[repoDatas.length]; RepoUpdater[] repoUpdaters = new RepoUpdater[repoDatas.length];
int moduleToUpdate = 0; int moduleToUpdate = 0;
noodleDebug.push("");
for (int i = 0; i < repoDatas.length; i++) { for (int i = 0; i < repoDatas.length; i++) {
noodleDebug.replace(repoDatas[i].getName()); if (BuildConfig.DEBUG) Log.d("NoodleDebug", repoDatas[i].getName());
moduleToUpdate += (repoUpdaters[i] = moduleToUpdate += (repoUpdaters[i] =
new RepoUpdater(repoDatas[i])).fetchIndex(); new RepoUpdater(repoDatas[i])).fetchIndex();
updateListener.update(STEP1 / repoDatas.length * (i + 1)); updateListener.update(STEP1 / repoDatas.length * (i + 1));
} }
noodleDebug.pop(); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Updating meta-data");
noodleDebug.replace("Updating meta-data");
int updatedModules = 0; int updatedModules = 0;
boolean allowLowQualityModules = MainApplication.isDisableLowQualityModuleFilter(); boolean allowLowQualityModules = MainApplication.isDisableLowQualityModuleFilter();
noodleDebug.push("");
for (int i = 0; i < repoUpdaters.length; i++) { for (int i = 0; i < repoUpdaters.length; i++) {
// Check if the repo is enabled
if (!repoUpdaters[i].repoData.isEnabled()) {
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Skipping disabled repo: " + repoUpdaters[i].repoData.getName());
continue;
}
List<RepoModule> repoModules = repoUpdaters[i].toUpdate(); List<RepoModule> repoModules = repoUpdaters[i].toUpdate();
RepoData repoData = repoDatas[i]; RepoData repoData = repoDatas[i];
noodleDebug.replace(repoData.getName()); if (BuildConfig.DEBUG) Log.d("NoodleDebug", repoData.getName());
Log.d(TAG, "Registering " + repoData.getName()); if (BuildConfig.DEBUG) Log.d(TAG, "Registering " + repoData.getName());
noodleDebug.push("");
for (RepoModule repoModule : repoModules) { for (RepoModule repoModule : repoModules) {
noodleDebug.replace(repoModule.id); if (BuildConfig.DEBUG) Log.d("NoodleDebug", repoModule.id);
try { try {
if (repoModule.propUrl != null && if (repoModule.propUrl != null &&
!repoModule.propUrl.isEmpty()) { !repoModule.propUrl.isEmpty()) {
@ -283,7 +289,6 @@ public final class RepoManager extends SyncManager {
updatedModules++; updatedModules++;
updateListener.update(STEP1 + (STEP2 / moduleToUpdate * updatedModules)); updateListener.update(STEP1 + (STEP2 / moduleToUpdate * updatedModules));
} }
noodleDebug.pop();
for (RepoModule repoModule : repoUpdaters[i].toApply()) { for (RepoModule repoModule : repoUpdaters[i].toApply()) {
if ((repoModule.moduleInfo.flags & ModuleInfo.FLAG_METADATA_INVALID) == 0) { if ((repoModule.moduleInfo.flags & ModuleInfo.FLAG_METADATA_INVALID) == 0) {
RepoModule registeredRepoModule = this.modules.get(repoModule.id); RepoModule registeredRepoModule = this.modules.get(repoModule.id);
@ -296,9 +301,7 @@ public final class RepoManager extends SyncManager {
} }
} }
} }
noodleDebug.pop(); if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Finishing update");
noodleDebug.replace("Finishing update");
noodleDebug.push("");
this.hasInternet = false; this.hasInternet = false;
// Check if we have internet connection // Check if we have internet connection
// Attempt to contact connectivitycheck.gstatic.com/generate_204 // Attempt to contact connectivitycheck.gstatic.com/generate_204
@ -318,22 +321,36 @@ public final class RepoManager extends SyncManager {
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "Failed to check internet connection", e); Log.e(TAG, "Failed to check internet connection", e);
} }
noodleDebug.pop();
if (hasInternet) { if (hasInternet) {
for (int i = 0; i < repoDatas.length; i++) { for (int i = 0; i < repoDatas.length; i++) {
noodleDebug.replace(repoUpdaters[i].repoData.getName()); // If repo is not enabled, skip
this.repoLastError = !repoUpdaters[i].finish(); if (!repoDatas[i].isEnabled()) {
if (this.repoLastError) { if (BuildConfig.DEBUG) Log.d("NoodleDebug",
"Skipping " + repoDatas[i].getName() + " because it's disabled");
continue;
}
if (BuildConfig.DEBUG) Log.d("NoodleDebug", repoUpdaters[i].repoData.getName());
this.repoLastSuccess = repoUpdaters[i].finish();
if (!this.repoLastSuccess) {
Log.e(TAG, "Failed to update " + repoUpdaters[i].repoData.getName()); Log.e(TAG, "Failed to update " + repoUpdaters[i].repoData.getName());
// Show snackbar on main looper and add some bottom padding
int finalI = i;
Activity context = MainApplication.getINSTANCE().getLastCompatActivity();
new Handler(Looper.getMainLooper()).post(() -> {
if (context != null) {
Snackbar.make(context.findViewById(android.R.id.content),
context.getString(R.string.repo_update_failed_extended,
repoUpdaters[finalI].repoData.getName()),
Snackbar.LENGTH_LONG).show();
}
});
this.repoLastErrorName = repoUpdaters[i].repoData.getName(); this.repoLastErrorName = repoUpdaters[i].repoData.getName();
} }
updateListener.update(STEP1 + STEP2 + (STEP3 / repoDatas.length * (i + 1))); updateListener.update(STEP1 + STEP2 + (STEP3 / repoDatas.length * (i + 1)));
} }
} }
noodleDebug.pop();
Log.i(TAG, "Got " + this.modules.size() + " modules!"); Log.i(TAG, "Got " + this.modules.size() + " modules!");
updateListener.update(1D); updateListener.update(1D);
noodleDebug.pop(); // pop "Finishing update"
} }
public void updateEnabledStates() { public void updateEnabledStates() {
@ -408,6 +425,6 @@ public final class RepoManager extends SyncManager {
} }
public boolean isLastUpdateSuccess() { public boolean isLastUpdateSuccess() {
return this.repoLastError; return this.repoLastSuccess;
} }
} }

@ -1,20 +1,11 @@
package com.fox2code.mmm.repo; package com.fox2code.mmm.repo;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Toast;
import androidx.annotation.Nullable; import com.fox2code.mmm.BuildConfig;
import com.fox2code.mmm.MainActivity;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.utils.Files; import com.fox2code.mmm.utils.Files;
import com.fox2code.mmm.utils.Http; import com.fox2code.mmm.utils.Http;
import com.fox2code.mmm.utils.HttpException;
import com.google.android.material.snackbar.Snackbar;
import org.jetbrains.annotations.Contract;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
@ -52,12 +43,12 @@ public class RepoUpdater {
} }
this.indexRaw = Http.doHttpGet(this.repoData.getUrl(), false); this.indexRaw = Http.doHttpGet(this.repoData.getUrl(), false);
// Ensure it's a valid json and response code is 200 // Ensure it's a valid json and response code is 200
if (Arrays.hashCode(this.indexRaw) == 0) { /*if (Arrays.hashCode(this.indexRaw) == 0) {
this.indexRaw = null; this.indexRaw = null;
this.toUpdate = Collections.emptyList(); this.toUpdate = Collections.emptyList();
this.toApply = this.repoData.moduleHashMap.values(); this.toApply = this.repoData.moduleHashMap.values();
return 0; return 0;
} }*/
this.toUpdate = this.repoData.populate(new JSONObject( this.toUpdate = this.repoData.populate(new JSONObject(
new String(this.indexRaw, StandardCharsets.UTF_8))); new String(this.indexRaw, StandardCharsets.UTF_8)));
// Since we reuse instances this should work // Since we reuse instances this should work
@ -83,7 +74,7 @@ public class RepoUpdater {
} }
public boolean finish() { public boolean finish() {
final boolean success = this.indexRaw != null; boolean success = this.indexRaw != null;
// If repo is not enabled we don't need to do anything, just return true // If repo is not enabled we don't need to do anything, just return true
if (!this.repoData.isEnabled()) { if (!this.repoData.isEnabled()) {
return true; return true;
@ -91,6 +82,9 @@ public class RepoUpdater {
if (this.indexRaw != null) { if (this.indexRaw != null) {
try { try {
Files.write(this.repoData.metaDataCache, this.indexRaw); Files.write(this.repoData.metaDataCache, this.indexRaw);
if (BuildConfig.DEBUG) {
Log.d(TAG, "Wrote index of " + this.repoData.id);
}
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

@ -24,6 +24,7 @@ public class Hashes {
} }
public static String hashMd5(byte[] input) { public static String hashMd5(byte[] input) {
Log.w(TAG, "hashMd5: This method is insecure, use hashSha256 instead");
try { try {
MessageDigest md = MessageDigest.getInstance("MD5"); MessageDigest md = MessageDigest.getInstance("MD5");

@ -238,6 +238,7 @@ public class Http {
(allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(new Request.Builder().url(url).get().build()).execute(); (allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(new Request.Builder().url(url).get().build()).execute();
// 200/204 == success, 304 == cache valid // 200/204 == success, 304 == cache valid
if (response.code() != 200 && response.code() != 204 && (response.code() != 304 || !allowCache)) { if (response.code() != 200 && response.code() != 204 && (response.code() != 304 || !allowCache)) {
Log.e(TAG, "Failed to fetch " + url + ", code: " + response.code());
checkNeedCaptchaAndroidacy(url, response.code()); checkNeedCaptchaAndroidacy(url, response.code());
// If it's a 401, and an androidacy link, it's probably an invalid token // If it's a 401, and an androidacy link, it's probably an invalid token
if (response.code() == 401 && AndroidacyUtil.isAndroidacyLink(url)) { if (response.code() == 401 && AndroidacyUtil.isAndroidacyLink(url)) {
@ -260,6 +261,7 @@ public class Http {
@SuppressWarnings("resource") @SuppressWarnings("resource")
private static Object doHttpPostRaw(String url, String data, boolean allowCache) throws IOException { private static Object doHttpPostRaw(String url, String data, boolean allowCache) throws IOException {
if (BuildConfig.DEBUG) Log.d(TAG, "POST " + url + " " + data);
checkNeedBlockAndroidacyRequest(url); checkNeedBlockAndroidacyRequest(url);
Response response = (allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(new Request.Builder().url(url).post(JsonRequestBody.from(data)).header("Content-Type", "application/json").build()).execute(); Response response = (allowCache ? getHttpClientWithCache() : getHttpClient()).newCall(new Request.Builder().url(url).post(JsonRequestBody.from(data)).header("Content-Type", "application/json").build()).execute();
if (response.isRedirect()) { if (response.isRedirect()) {
@ -280,10 +282,11 @@ public class Http {
} }
public static byte[] doHttpGet(String url, ProgressListener progressListener) throws IOException { public static byte[] doHttpGet(String url, ProgressListener progressListener) throws IOException {
Log.d("Http", "Progress URL: " + url); if (BuildConfig.DEBUG) Log.d("Http", "Progress URL: " + url);
checkNeedBlockAndroidacyRequest(url); checkNeedBlockAndroidacyRequest(url);
Response response = getHttpClient().newCall(new Request.Builder().url(url).get().build()).execute(); Response response = getHttpClient().newCall(new Request.Builder().url(url).get().build()).execute();
if (response.code() != 200 && response.code() != 204) { if (response.code() != 200 && response.code() != 204) {
Log.e(TAG, "Failed to fetch " + url + ", code: " + response.code());
checkNeedCaptchaAndroidacy(url, response.code()); checkNeedCaptchaAndroidacy(url, response.code());
throw new HttpException(response.code()); throw new HttpException(response.code());
} }

@ -16,7 +16,7 @@
android:id="@+id/card_view" android:id="@+id/card_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="?attr/materialCardViewFilledStyle"> style="?attr/materialCardViewElevatedStyle">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"

@ -26,13 +26,22 @@
<style name="Theme.MagiskModuleManager.Monet.Black" parent="Theme.MagiskModuleManager.Monet.Dark"> <style name="Theme.MagiskModuleManager.Monet.Black" parent="Theme.MagiskModuleManager.Monet.Dark">
<item name="colorBackgroundFloating">@color/black</item> <item name="colorBackgroundFloating">@color/black</item>
<item name="android:windowBackground">@color/black</item> <item name="android:windowBackground">@color/black</item>
<item name="boxBackgroundColor">@color/black</item> <item name="boxBackgroundColor">@color/dark_backgroundColor</item>
<item name="cardBackgroundColor">@color/black</item> <item name="cardBackgroundColor">@color/cardview_dark_background</item>
<item name="backgroundColor">@color/black</item> <item name="backgroundColor">@color/black</item>
<item name="colorSurface">@color/black</item> <item name="colorSurface">@color/black</item>
<!-- Darker variants of the colors --> <!-- Darker variants of the monet colors -->
<item name="colorPrimaryVariant">@color/system_accent2_900</item> <item name="colorPrimary">@color/system_accent2_300</item>
<item name="colorSecondaryVariant">@color/system_accent2_900</item> <item name="colorPrimaryVariant">@color/system_accent2_700</item>
<item name="colorSecondary">@color/system_accent2_400</item>
<item name="colorSecondaryVariant">@color/system_accent2_600</item>
<!-- Override chip style -->
<item name="chipBackgroundColor">@color/system_accent2_700</item>
<item name="chipSurfaceColor">@color/system_accent2_700</item>
<!-- <item name="colorOnPrimary">@color/system_accent2_100</item>
<item name="colorOnSecondary">@color/system_accent2_100</item>
<item name="colorOnBackground">@color/system_accent2_100</item>
<item name="colorOnSurface">@color/system_accent2_100</item> -->
</style> </style>
<style name="Widget.Material3.Chip.Choice.Dark" parent="Widget.Material3.Chip.Assist"> <style name="Widget.Material3.Chip.Choice.Dark" parent="Widget.Material3.Chip.Assist">

@ -7,6 +7,7 @@
<color name="teal_700">#FF018786</color> <color name="teal_700">#FF018786</color>
<color name="orange_700">#EF6C00</color> <color name="orange_700">#EF6C00</color>
<color name="orange_200">#FFA726</color> <color name="orange_200">#FFA726</color>
<color name="orange_500">#FF9800</color>
<color name="black_transparent">#70000000</color> <color name="black_transparent">#70000000</color>
<color name="white_transparent">#70FFFFFF</color> <color name="white_transparent">#70FFFFFF</color>
<color name="transparent">#00000000</color> <color name="transparent">#00000000</color>

@ -198,4 +198,5 @@
download the GitHub release if you\'d like to benefit from features like module reviews, automatic security checks, and more.</string> download the GitHub release if you\'d like to benefit from features like module reviews, automatic security checks, and more.</string>
<string name="download_full_app">Download full version</string> <string name="download_full_app">Download full version</string>
<string name="repo_update_failed">Some repos have failed to update</string> <string name="repo_update_failed">Some repos have failed to update</string>
<string name="repo_update_failed_extended">Update of %1$s failed. Please try again later.</string>
</resources> </resources>

@ -92,8 +92,10 @@
<item name="backgroundColor">@color/black</item> <item name="backgroundColor">@color/black</item>
<item name="colorSurface">@color/black</item> <item name="colorSurface">@color/black</item>
<!-- Darker variants of the colors --> <!-- Darker variants of the colors -->
<item name="colorPrimaryVariant">@color/system_accent2_900</item> <item name="colorPrimary">@color/orange_500</item>
<item name="colorSecondaryVariant">@color/system_accent2_900</item> <item name="colorPrimaryVariant">@color/orange_700</item>
<item name="colorSecondary">@color/orange_500</item>
<item name="colorSecondaryVariant">@color/orange_700</item>
</style> </style>
<style name="Widget.Material.Chip.Choice.Dark" parent="Widget.MaterialComponents.Chip.Action"> <style name="Widget.Material.Chip.Choice.Dark" parent="Widget.MaterialComponents.Chip.Action">

@ -6,7 +6,7 @@ buildscript {
gradlePluginPortal() gradlePluginPortal()
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
} }
project.ext.latestAboutLibsRelease = "10.5.0" project.ext.latestAboutLibsRelease = "10.5.2"
project.ext.sentryConfigFile = new File(rootDir, "sentry.properties").getAbsoluteFile() project.ext.sentryConfigFile = new File(rootDir, "sentry.properties").getAbsoluteFile()
project.ext.hasSentryConfig = sentryConfigFile.exists() project.ext.hasSentryConfig = sentryConfigFile.exists()
project.ext.sentryCli = [ project.ext.sentryCli = [

Loading…
Cancel
Save