code cleanup

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/267/head
androidacy-user 1 year ago
parent 5d941ae570
commit 2573313f3a

@ -41,7 +41,7 @@ public class AppUpdateManager {
private String latestPreRelease;
private long lastChecked;
private boolean preReleaseNewer;
private boolean lastCheckSuccess;
private AppUpdateManager() {
this.compatFile = new File(MainApplication.getINSTANCE().getFilesDir(), "compat.txt");
this.latestRelease = MainApplication.getBootSharedPreferences().getString("updater_latest_release", BuildConfig.VERSION_NAME);
@ -51,7 +51,8 @@ public class AppUpdateManager {
if (this.compatFile.isFile()) {
try {
this.parseCompatibilityFlags(new FileInputStream(this.compatFile));
} catch (IOException e) {
} catch (
IOException e) {
e.printStackTrace();
}
}
@ -73,15 +74,18 @@ public class AppUpdateManager {
// Return true if should show a notification
public boolean checkUpdate(boolean force) {
if (!BuildConfig.ENABLE_AUTO_UPDATER) return false;
if (!force && this.peekShouldUpdate()) return true;
if (!BuildConfig.ENABLE_AUTO_UPDATER)
return false;
if (!force && this.peekShouldUpdate())
return true;
long lastChecked = this.lastChecked;
if (lastChecked != 0 &&
// Avoid spam calls by putting a 60 seconds timer
lastChecked < System.currentTimeMillis() - 60000L)
return force && this.peekShouldUpdate();
synchronized (this.updateLock) {
if (lastChecked != this.lastChecked) return this.peekShouldUpdate();
if (lastChecked != this.lastChecked)
return this.peekShouldUpdate();
boolean preReleaseNewer = true;
try {
JSONArray releases = new JSONArray(new String(Http.doHttpGet(RELEASES_API_URL, false), StandardCharsets.UTF_8));
@ -89,21 +93,26 @@ public class AppUpdateManager {
for (int i = 0; i < releases.length(); i++) {
JSONObject release = releases.getJSONObject(i);
// Skip invalid entries
if (release.getBoolean("draft")) continue;
if (release.getBoolean("draft"))
continue;
boolean preRelease = release.getBoolean("prerelease");
String version = release.getString("tag_name");
if (version.startsWith("v")) version = version.substring(1);
if (version.startsWith("v"))
version = version.substring(1);
if (preRelease) {
if (latestPreRelease == null) latestPreRelease = version;
if (latestPreRelease == null)
latestPreRelease = version;
} else if (latestRelease == null) {
latestRelease = version;
if (latestPreRelease == null) preReleaseNewer = false;
if (latestPreRelease == null)
preReleaseNewer = false;
}
if (latestRelease != null && latestPreRelease != null) {
break; // We read everything we needed to read.
}
}
if (latestRelease != null) this.latestRelease = latestRelease;
if (latestRelease != null)
this.latestRelease = latestRelease;
if (latestPreRelease != null) {
this.latestPreRelease = latestPreRelease;
this.preReleaseNewer = preReleaseNewer;
@ -111,13 +120,15 @@ public class AppUpdateManager {
this.latestPreRelease = "";
this.preReleaseNewer = false;
}
if (BuildConfig.DEBUG) Log.i(TAG, "Latest release: " + latestRelease);
if (BuildConfig.DEBUG) Log.i(TAG, "Latest pre-release: " + latestPreRelease);
if (BuildConfig.DEBUG) Log.i(TAG, "Latest pre-release newer: " + preReleaseNewer);
if (BuildConfig.DEBUG)
Log.d(TAG, "Latest release: " + latestRelease);
if (BuildConfig.DEBUG)
Log.d(TAG, "Latest pre-release: " + latestPreRelease);
if (BuildConfig.DEBUG)
Log.d(TAG, "Latest pre-release newer: " + preReleaseNewer);
this.lastChecked = System.currentTimeMillis();
this.lastCheckSuccess = true;
} catch (Exception ioe) {
this.lastCheckSuccess = false;
} catch (
Exception ioe) {
Log.e("AppUpdateManager", "Failed to check releases", ioe);
}
}
@ -125,7 +136,8 @@ public class AppUpdateManager {
}
public void checkUpdateCompat() {
if (BuildConfig.DEBUG) Log.i(TAG, "Checking compatibility flags");
if (BuildConfig.DEBUG)
Log.d(TAG, "Checking compatibility flags");
if (this.compatFile.exists()) {
long lastUpdate = this.compatFile.lastModified();
if (lastUpdate <= System.currentTimeMillis() && lastUpdate + 600_000L > System.currentTimeMillis()) {
@ -133,58 +145,63 @@ public class AppUpdateManager {
}
}
try {
if (BuildConfig.DEBUG) Log.i(TAG, "Downloading compatibility flags");
if (BuildConfig.DEBUG)
Log.d(TAG, "Downloading compatibility flags");
JSONObject object = new JSONObject(new String(Http.doHttpGet(COMPAT_API_URL, false), StandardCharsets.UTF_8));
if (object.isNull("body")) {
if (BuildConfig.DEBUG) Log.i(TAG, "Compatibility flags not found");
if (BuildConfig.DEBUG)
Log.d(TAG, "Compatibility flags not found");
compatDataId.clear();
Files.write(compatFile, new byte[0]);
return;
}
if (BuildConfig.DEBUG) Log.i(TAG, "Parsing compatibility flags");
if (BuildConfig.DEBUG)
Log.d(TAG, "Parsing compatibility flags");
byte[] rawData = object.getString("body").getBytes(StandardCharsets.UTF_8);
this.parseCompatibilityFlags(new ByteArrayInputStream(rawData));
Files.write(compatFile, rawData);
if (!BuildConfig.ENABLE_AUTO_UPDATER) this.lastCheckSuccess = true;
if (BuildConfig.DEBUG) Log.i(TAG, "Compatibility flags update finishing");
if (BuildConfig.DEBUG)
Log.d(TAG, "Compatibility flags update finishing");
return;
} catch (Exception e) {
if (!BuildConfig.ENABLE_AUTO_UPDATER) this.lastCheckSuccess = false;
} catch (
Exception e) {
Log.e("AppUpdateManager", "Failed to update compat list", e);
}
if (BuildConfig.DEBUG) Log.i(TAG, "Compatibility flags updated");
if (BuildConfig.DEBUG)
Log.d(TAG, "Compatibility flags updated");
}
public boolean peekShouldUpdate() {
if (!BuildConfig.ENABLE_AUTO_UPDATER) return false;
if (!BuildConfig.ENABLE_AUTO_UPDATER)
return false;
// Convert both BuildConfig.VERSION_NAME and latestRelease to int
int currentVersion = 0, latestVersion = 0;
try {
currentVersion = Integer.parseInt(BuildConfig.VERSION_NAME.replace(".", ""));
latestVersion = Integer.parseInt(this.latestRelease.replace(".", ""));
} catch (NumberFormatException ignored) {
} catch (
NumberFormatException ignored) {
}
return currentVersion < latestVersion || (this.preReleaseNewer && currentVersion < Integer.parseInt(this.latestPreRelease.replace(".", "")));
}
public boolean peekHasUpdate() {
if (!BuildConfig.ENABLE_AUTO_UPDATER) return false;
if (!BuildConfig.ENABLE_AUTO_UPDATER)
return false;
return !BuildConfig.VERSION_NAME.equals(this.preReleaseNewer ? this.latestPreRelease : this.latestRelease);
}
public boolean isLastCheckSuccess() {
return lastCheckSuccess;
}
private void parseCompatibilityFlags(InputStream inputStream) throws IOException {
compatDataId.clear();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line;
while ((line = bufferedReader.readLine()) != null) {
line = line.trim();
if (line.isEmpty() || line.startsWith("#")) continue;
if (line.isEmpty() || line.startsWith("#"))
continue;
int i = line.indexOf('/');
if (i == -1) continue;
if (i == -1)
continue;
int value = 0;
for (String arg : line.substring(i + 1).split(",")) {
switch (arg) {

@ -214,13 +214,13 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
public void commonNext() {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Common next");
Log.d(TAG, "Common next");
moduleViewListBuilder.addNotification(NotificationType.DEBUG);
}
updateScreenInsets(); // Fix an edge case
if (waitInitialSetupFinished()) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Initial setup not finished, waiting...");
Log.d(TAG, "Initial setup not finished, waiting...");
}
return;
}
@ -239,7 +239,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
// On every preferences change, log the change if debug is enabled
if (BuildConfig.DEBUG) {
Log.i("PrefsListener", "onCreate: Preferences: " + MainApplication.getSharedPreferences().getAll());
Log.d("PrefsListener", "onCreate: Preferences: " + MainApplication.getSharedPreferences().getAll());
// Log all preferences changes
MainApplication.getSharedPreferences().registerOnSharedPreferenceChangeListener((prefs, key) -> Log.i("PrefsListener", "onSharedPreferenceChanged: " + key + " = " + prefs.getAll().get(key)));
}
@ -377,7 +377,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
connection.connect();
// For debug builds, log the response code and response body
if (BuildConfig.DEBUG) {
Log.i("NoodleDebug", "Response Code: " + connection.getResponseCode());
Log.d("NoodleDebug", "Response Code: " + connection.getResponseCode());
}
// Check if the request was successful
if (connection.getResponseCode() == 200) {
@ -767,7 +767,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_magisk_alt_repo))).setChecked(BuildConfig.ENABLED_REPOS.contains("magisk_alt_repo"));
// On debug builds, log when a switch is toggled
if (BuildConfig.DEBUG) {
((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_background_update_check))).setOnCheckedChangeListener((buttonView, isChecked) -> Log.i("SetupWizard", "Background Update Check: " + isChecked));
Log.d("SetupWizard", "Background Update Check: " + ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_background_update_check))).isChecked());
((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_crash_reporting))).setOnCheckedChangeListener((buttonView, isChecked) -> Log.i("SetupWizard", "Crash Reporting: " + isChecked));
((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_androidacy_repo))).setOnCheckedChangeListener((buttonView, isChecked) -> Log.i("SetupWizard", "Androidacy Repo: " + isChecked));
((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_magisk_alt_repo))).setOnCheckedChangeListener((buttonView, isChecked) -> Log.i("SetupWizard", "Magisk Alt Repo: " + isChecked));
@ -793,7 +793,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
case "system":
popupMenu.getMenu().findItem(R.id.theme_system).setChecked(true);
break;
// Black and transparent_light
// Black and transparent_light
case "black":
popupMenu.getMenu().findItem(R.id.theme_black).setChecked(true);
break;
@ -818,8 +818,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
// Set the theme
UiThreadHandler.handler.postDelayed(() -> {
MainApplication.getINSTANCE().updateTheme();
FoxActivity.getFoxActivity(this).setThemeRecreate(
MainApplication.getINSTANCE().getManagerThemeResId());
FoxActivity.getFoxActivity(this).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId());
}, 1);
return true;
});
@ -856,12 +855,13 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
// Sleep for 1 second to allow the user to see the changes
try {
Thread.sleep(500);
} catch (InterruptedException e) {
} catch (
InterruptedException e) {
e.printStackTrace();
}
// Log the changes if debug
if (BuildConfig.DEBUG) {
Log.i("SetupWizard", "Background update check: " + prefs.getBoolean("pref_background_update_check", false));
Log.d("SetupWizard", "Background update check: " + prefs.getBoolean("pref_background_update_check", false));
Log.i("SetupWizard", "Crash reporting: " + prefs.getBoolean("pref_crash_reporting", false));
Log.i("SetupWizard", "Magisk Alt Repo: " + prefs.getBoolean("pref_magisk_alt_repo_enabled", false));
Log.i("SetupWizard", "Androidacy Repo: " + prefs.getBoolean("pref_androidacy_repo_enabled", false));

@ -4,6 +4,8 @@ import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
@ -29,6 +31,7 @@ import com.fox2code.mmm.utils.GMSProviderInstaller;
import com.fox2code.mmm.utils.Http;
import com.fox2code.mmm.utils.SentryMain;
import com.fox2code.rosettax.LanguageSwitcher;
import com.google.common.hash.Hashing;
import com.topjohnwu.superuser.Shell;
import java.io.File;
@ -57,6 +60,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
@SuppressLint("RestrictedApi")
// Use FoxProcess wrapper helper.
private static final boolean wrapped = !FoxProcessExt.isRootLoader();
public static boolean isOfficial = false;
private static Locale timeFormatLocale = Resources.getSystem().getConfiguration().locale;
private static SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString, timeFormatLocale);
private static SharedPreferences bootSharedPreferences;
@ -283,6 +287,19 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
if (BuildConfig.DEBUG) {
Log.d("MainApplication", "Starting FoxMMM version " + BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + "), commit " + BuildConfig.COMMIT_HASH);
}
// Determine if this is an official build based on the signature
try {
// Get the signature of the key used to sign the app
@SuppressLint("PackageManagerGetSignatures") Signature[] signatures = this.getPackageManager().getPackageInfo(this.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
String officialSignatureHash = "7bec7c4462f4aac616612d9f56a023ee3046e83afa956463b5fab547fd0a0be6";
String ourSignatureHash = Hashing.sha256().hashBytes(signatures[0].toByteArray()).toString();
isOfficial = ourSignatureHash.equals(officialSignatureHash);
} catch (
PackageManager.NameNotFoundException ignored) {
}
if (!isOfficial) {
Log.w("MainApplication", "This is not an official build of FoxMMM. This warning can be safely ignored if this is expected, otherwise you may be running an untrusted build.");
}
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences();
// We are only one process so it's ok to do this
SharedPreferences bootPrefs = MainApplication.bootSharedPreferences = this.getSharedPreferences("mmm_boot", MODE_PRIVATE);

@ -108,7 +108,8 @@ public final class AndroidacyActivity extends FoxActivity {
// get from shared preferences
try {
device_id = AndroidacyRepoData.generateDeviceId();
} catch (NoSuchAlgorithmException e) {
} catch (
NoSuchAlgorithmException e) {
e.printStackTrace();
}
url = url + "&device_id=" + device_id;
@ -136,7 +137,8 @@ public final class AndroidacyActivity extends FoxActivity {
IntentHelper.openConfig(this, config);
return true;
});
} catch (PackageManager.NameNotFoundException ignored) {
} catch (
PackageManager.NameNotFoundException ignored) {
}
}
}
@ -164,9 +166,9 @@ public final class AndroidacyActivity extends FoxActivity {
public boolean shouldOverrideUrlLoading(@NonNull WebView view, @NonNull WebResourceRequest request) {
// Don't open non Androidacy urls inside WebView
if (request.isForMainFrame() && !AndroidacyUtil.isAndroidacyLink(request.getUrl())) {
if (downloadMode || backOnResume) return true;
Log.i(TAG,
"Exiting WebView " + AndroidacyUtil.hideToken(request.getUrl().toString()));
if (downloadMode || backOnResume)
return true;
Log.i(TAG, "Exiting WebView " + AndroidacyUtil.hideToken(request.getUrl().toString()));
IntentHelper.openUri(view.getContext(), request.getUrl().toString());
return true;
}
@ -240,7 +242,7 @@ public final class AndroidacyActivity extends FoxActivity {
Log.e(TAG, consoleMessage.message());
break;
case DEBUG:
Log.i(TAG, consoleMessage.message());
Log.d(TAG, consoleMessage.message());
break;
}
}
@ -249,7 +251,8 @@ public final class AndroidacyActivity extends FoxActivity {
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (downloadMode) return;
if (downloadMode)
return;
if (newProgress != 100 && // Show progress bar
progressIndicator.getVisibility() != View.VISIBLE)
progressIndicator.setVisibility(View.VISIBLE);
@ -260,13 +263,15 @@ public final class AndroidacyActivity extends FoxActivity {
}
});
this.webView.setDownloadListener((downloadUrl, userAgent, contentDisposition, mimetype, contentLength) -> {
if (this.downloadMode || this.isDownloadUrl(downloadUrl)) return;
if (this.downloadMode || this.isDownloadUrl(downloadUrl))
return;
if (AndroidacyUtil.isAndroidacyLink(downloadUrl) && !this.backOnResume) {
AndroidacyWebAPI androidacyWebAPI = this.androidacyWebAPI;
if (androidacyWebAPI != null) {
if (!androidacyWebAPI.downloadMode) {
// Native module popup may cause download after consumed action
if (androidacyWebAPI.consumedAction) return;
if (androidacyWebAPI.consumedAction)
return;
// Workaround Androidacy bug
final String moduleId = moduleIdOfUrl(downloadUrl);
if (this.megaIntercept(webView.getUrl(), downloadUrl)) {
@ -294,7 +299,8 @@ public final class AndroidacyActivity extends FoxActivity {
this.androidacyWebAPI = new AndroidacyWebAPI(this, allowInstall);
XHooks.onWebViewInitialize(this.webView, allowInstall);
this.webView.addJavascriptInterface(this.androidacyWebAPI, "mmm");
if (compatLevel != 0) androidacyWebAPI.notifyCompatModeRaw(compatLevel);
if (compatLevel != 0)
androidacyWebAPI.notifyCompatModeRaw(compatLevel);
HashMap<String, String> headers = new HashMap<>();
headers.put("Accept-Language", this.getResources().getConfiguration().locale.toLanguageTag());
if (BuildConfig.DEBUG) {
@ -328,8 +334,10 @@ public final class AndroidacyActivity extends FoxActivity {
private String moduleIdOfUrl(String url) {
for (String prefix : new String[]{"https://production-api.androidacy.com/downloads/", "https://staging-api.androidacy.com/downloads/", "https://production-api.androidacy.com/magisk/readme/", "https://staging-api.androidacy.com/magisk/readme/", "https://prodiuction-api.androidacy.com/magisk/info/", "https://staging-api.androidacy.com/magisk/info/"}) { // Make both staging and non staging act the same
int i = url.indexOf('?', prefix.length());
if (i == -1) i = url.length();
if (url.startsWith(prefix)) return url.substring(prefix.length(), i);
if (i == -1)
i = url.length();
if (url.startsWith(prefix))
return url.substring(prefix.length(), i);
}
if (this.isFileUrl(url)) {
int i = url.indexOf("&module=");
@ -346,25 +354,30 @@ public final class AndroidacyActivity extends FoxActivity {
}
private boolean isFileUrl(String url) {
if (url == null) return false;
if (url == null)
return false;
for (String prefix : new String[]{"https://production-api.androidacy.com/downloads/", "https://staging-api.androidacy.com/downloads/"}) { // Make both staging and non staging act the same
if (url.startsWith(prefix)) return true;
if (url.startsWith(prefix))
return true;
}
return false;
}
private boolean isDownloadUrl(String url) {
for (String prefix : new String[]{"https://production-api.androidacy.com/magisk/downloads/", "https://staging-api.androidacy.com/magisk/downloads/"}) { // Make both staging and non staging act the same
if (url.startsWith(prefix)) return true;
if (url.startsWith(prefix))
return true;
}
return false;
}
private boolean megaIntercept(String pageUrl, String fileUrl) {
if (pageUrl == null || fileUrl == null) return false;
if (pageUrl == null || fileUrl == null)
return false;
if (this.isFileUrl(fileUrl)) {
Log.i(TAG, "megaIntercept(" + AndroidacyUtil.hideToken(pageUrl) + ", " + AndroidacyUtil.hideToken(fileUrl) + ")");
} else return false;
} else
return false;
final AndroidacyWebAPI androidacyWebAPI = this.androidacyWebAPI;
String moduleId = AndroidacyUtil.getModuleId(fileUrl);
if (moduleId == null) {

@ -189,18 +189,13 @@ public final class AndroidacyRepoData extends RepoData {
// If it's a 400, the app is probably outdated. Show a snackbar suggesting user update app and webview
if (connection.getResponseCode() == 400) {
// Show a dialog using androidacy_update_needed string
new MaterialAlertDialogBuilder(MainApplication.getINSTANCE())
.setTitle(R.string.androidacy_update_needed)
.setMessage(R.string.androidacy_update_needed_message)
.setPositiveButton(R.string.update, (dialog, which) -> {
// Open the app's page on the Play Store
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://github.com/Fox2Code/FoxMagiskModuleManager/releases/latest"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApplication.getINSTANCE().startActivity(intent);
})
.setNegativeButton(R.string.cancel, null)
.show();
new MaterialAlertDialogBuilder(MainApplication.getINSTANCE()).setTitle(R.string.androidacy_update_needed).setMessage(R.string.androidacy_update_needed_message).setPositiveButton(R.string.update, (dialog, which) -> {
// Open the app's page on the Play Store
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://github.com/Fox2Code/FoxMagiskModuleManager/releases/latest"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApplication.getINSTANCE().startActivity(intent);
}).setNegativeButton(R.string.cancel, null).show();
}
return false;
}
@ -282,7 +277,7 @@ public final class AndroidacyRepoData extends RepoData {
@Override
protected List<RepoModule> populate(JSONObject jsonObject) throws JSONException, NoSuchAlgorithmException {
if (BuildConfig.DEBUG) {
Log.i(TAG, "AndroidacyRepoData populate start");
Log.d(TAG, "AndroidacyRepoData populate start");
}
if (!jsonObject.getString("status").equals("success"))
throw new JSONException("Response is not a success!");

@ -18,21 +18,17 @@ public class AndroidacyUtil {
return url != null && isAndroidacyLink(url, Uri.parse(url));
}
static boolean isAndroidacyLink(@NonNull String url,@NonNull Uri uri) {
static boolean isAndroidacyLink(@NonNull String url, @NonNull Uri uri) {
int i; // Check both string and Uri to mitigate parse exploit
return url.startsWith("https://") &&
(i = url.indexOf("/", 8)) != -1 &&
url.substring(8, i).endsWith("api.androidacy.com") &&
uri.getHost().endsWith("api.androidacy.com");
return url.startsWith("https://") && (i = url.indexOf("/", 8)) != -1 && url.substring(8, i).endsWith("api.androidacy.com") && uri.getHost().endsWith("api.androidacy.com");
}
public static boolean isAndroidacyFileUrl(@Nullable String url) {
if (url == null) return false;
for (String prefix : new String[]{
"https://production-api.androidacy.com/magisk/file/",
"https://staging-api.androidacy.com/magisk/file/"
}) { // Make both staging and non staging act the same
if (url.startsWith(prefix)) return true;
if (url == null)
return false;
for (String prefix : new String[]{"https://production-api.androidacy.com/magisk/file/", "https://staging-api.androidacy.com/magisk/file/"}) { // Make both staging and non staging act the same
if (url.startsWith(prefix))
return true;
}
return false;
}
@ -40,16 +36,16 @@ public class AndroidacyUtil {
// Avoid logging token
public static String hideToken(@NonNull String url) {
int i = url.lastIndexOf("token=");
if (i == -1) return url;
if (i == -1)
return url;
int i2 = url.indexOf('&', i);
int i3 = url.indexOf(' ', i);
if (i3 != -1 && i3 < i2) i2 = i3;
if (i3 != -1 && i3 < i2)
i2 = i3;
if (i2 == -1) {
return url.substring(0, i + 6) +
"<token>";
return url.substring(0, i + 6) + "<token>";
} else {
return url.substring(0, i + 6) +
"<token>" + url.substring(i2);
return url.substring(0, i + 6) + "<token>" + url.substring(i2);
}
}

@ -61,14 +61,11 @@ public class AndroidacyWebAPI {
this.downloadMode = false;
}
void openNativeModuleDialogRaw(String moduleUrl, String moduleId, String installTitle,
String checksum, boolean canInstall) {
if (BuildConfig.DEBUG) Log.i(TAG, "ModuleDialog, downloadUrl: " + AndroidacyUtil.hideToken(moduleUrl) +
", moduleId: " + moduleId + ", installTitle: " + installTitle +
", checksum: " + checksum + ", canInstall: " + canInstall);
void openNativeModuleDialogRaw(String moduleUrl, String moduleId, String installTitle, String checksum, boolean canInstall) {
if (BuildConfig.DEBUG)
Log.d(TAG, "ModuleDialog, downloadUrl: " + AndroidacyUtil.hideToken(moduleUrl) + ", moduleId: " + moduleId + ", installTitle: " + installTitle + ", checksum: " + checksum + ", canInstall: " + canInstall);
this.downloadMode = false;
RepoModule repoModule = AndroidacyRepoData
.getInstance().moduleHashMap.get(installTitle);
RepoModule repoModule = AndroidacyRepoData.getInstance().moduleHashMap.get(installTitle);
String title, description;
boolean mmtReborn = false;
if (repoModule != null) {
@ -83,16 +80,13 @@ public class AndroidacyWebAPI {
title = installTitle;
String checkSumType = Hashes.checkSumName(checksum);
if (checkSumType == null) {
description = "Checksum: " + ((
checksum == null || checksum.isEmpty()) ? "null" : checksum);
description = "Checksum: " + ((checksum == null || checksum.isEmpty()) ? "null" : checksum);
} else {
description = checkSumType + ": " + checksum;
}
}
final MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this.activity);
builder.setTitle(title).setMessage(description).setCancelable(true)
.setIcon(R.drawable.ic_baseline_extension_24);
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this.activity);
builder.setTitle(title).setMessage(description).setCancelable(true).setIcon(R.drawable.ic_baseline_extension_24);
builder.setNegativeButton(R.string.download_module, (x, y) -> {
this.downloadMode = true;
IntentHelper.openCustomTab(this.activity, moduleUrl);
@ -102,17 +96,12 @@ public class AndroidacyWebAPI {
String config = null;
if (repoModule != null) {
config = repoModule.moduleInfo.config;
LocalModuleInfo localModuleInfo =
ModuleManager.getINSTANCE().getModules().get(repoModule.id);
hasUpdate = localModuleInfo != null &&
repoModule.moduleInfo.versionCode > localModuleInfo.versionCode;
LocalModuleInfo localModuleInfo = ModuleManager.getINSTANCE().getModules().get(repoModule.id);
hasUpdate = localModuleInfo != null && repoModule.moduleInfo.versionCode > localModuleInfo.versionCode;
}
final String fModuleUrl = moduleUrl, fTitle = title,
fConfig = config, fChecksum = checksum;
final String fModuleUrl = moduleUrl, fTitle = title, fConfig = config, fChecksum = checksum;
final boolean fMMTReborn = mmtReborn;
builder.setPositiveButton(hasUpdate ?
R.string.update_module : R.string.install_module, (x, y) -> IntentHelper.openInstaller(this.activity,
fModuleUrl, fTitle, fConfig, fChecksum, fMMTReborn));
builder.setPositiveButton(hasUpdate ? R.string.update_module : R.string.install_module, (x, y) -> IntentHelper.openInstaller(this.activity, fModuleUrl, fTitle, fConfig, fChecksum, fMMTReborn));
}
builder.setOnCancelListener(dialogInterface -> {
if (!this.activity.backOnResume)
@ -122,11 +111,10 @@ public class AndroidacyWebAPI {
this.downloadMode = true;
try {
return this.activity.downloadFileAsync(moduleUrl);
} catch (IOException e) {
} catch (
IOException e) {
Log.e(TAG, "Failed to download module", e);
AndroidacyWebAPI.this.activity.runOnUiThread(() ->
Toast.makeText(AndroidacyWebAPI.this.activity,
R.string.failed_download, Toast.LENGTH_SHORT).show());
AndroidacyWebAPI.this.activity.runOnUiThread(() -> Toast.makeText(AndroidacyWebAPI.this.activity, R.string.failed_download, Toast.LENGTH_SHORT).show());
return null;
}
}, "androidacy_repo");
@ -144,8 +132,10 @@ public class AndroidacyWebAPI {
}
void notifyCompatModeRaw(int value) {
if (this.consumedAction) return;
if (BuildConfig.DEBUG) Log.i(TAG, "Androidacy Compat mode: " + value);
if (this.consumedAction)
return;
if (BuildConfig.DEBUG)
Log.d(TAG, "Androidacy Compat mode: " + value);
this.notifiedCompatMode = value;
if (value < 0) {
value = 0;
@ -158,7 +148,8 @@ public class AndroidacyWebAPI {
@JavascriptInterface
public void forceQuit(String error) {
// Allow forceQuit and cancel in downloadMode
if (this.consumedAction && !this.downloadMode) return;
if (this.consumedAction && !this.downloadMode)
return;
this.consumedAction = true;
this.forceQuitRaw(error);
}
@ -166,10 +157,10 @@ public class AndroidacyWebAPI {
@JavascriptInterface
public void cancel() {
// Allow forceQuit and cancel in downloadMode
if (this.consumedAction && !this.downloadMode) return;
if (this.consumedAction && !this.downloadMode)
return;
this.consumedAction = true;
this.activity.runOnUiThread(
this.activity::forceBackPressed);
this.activity.runOnUiThread(this.activity::forceBackPressed);
}
/**
@ -177,10 +168,12 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public void openUrl(String url) {
if (this.consumedAction) return;
if (this.consumedAction)
return;
this.consumedAction = true;
this.downloadMode = false;
if (BuildConfig.DEBUG) Log.i(TAG, "Received openUrl request: " + url);
if (BuildConfig.DEBUG)
Log.d(TAG, "Received openUrl request: " + url);
if (Uri.parse(url).getScheme().equals("https")) {
IntentHelper.openUrl(this.activity, url);
}
@ -191,10 +184,12 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public void openCustomTab(String url) {
if (this.consumedAction) return;
if (this.consumedAction)
return;
this.consumedAction = true;
this.downloadMode = false;
if (BuildConfig.DEBUG) Log.i(TAG, "Received openCustomTab request: " + url);
if (BuildConfig.DEBUG)
Log.d(TAG, "Received openCustomTab request: " + url);
if (Uri.parse(url).getScheme().equals("https")) {
IntentHelper.openCustomTab(this.activity, url);
}
@ -223,8 +218,7 @@ public class AndroidacyWebAPI {
@JavascriptInterface
public boolean canInstall() {
// With lockdown mode enabled or lack of root, install should not have any effect
return this.allowInstall && this.hasRoot() &&
!MainApplication.isShowcaseMode();
return this.allowInstall && this.hasRoot() && !MainApplication.isShowcaseMode();
}
/**
@ -238,8 +232,8 @@ public class AndroidacyWebAPI {
}
this.consumedAction = true;
this.downloadMode = false;
if (BuildConfig.DEBUG) Log.i(TAG, "Received install request: " +
moduleUrl + " " + installTitle + " " + checksum);
if (BuildConfig.DEBUG)
Log.d(TAG, "Received install request: " + moduleUrl + " " + installTitle + " " + checksum);
if (!AndroidacyUtil.isAndroidacyLink(moduleUrl)) {
this.forceQuitRaw("Non Androidacy module link used on Androidacy");
return;
@ -257,14 +251,12 @@ public class AndroidacyWebAPI {
if (this.effectiveCompatMode < 1) {
if (!this.canInstall()) {
this.downloadMode = true;
this.activity.runOnUiThread(() ->
this.activity.webView.loadUrl(moduleUrl));
this.activity.runOnUiThread(() -> this.activity.webView.loadUrl(moduleUrl));
} else {
this.openNativeModuleDialogRaw(moduleUrl, moduleId, installTitle, checksum, true);
}
} else {
RepoModule repoModule = AndroidacyRepoData
.getInstance().moduleHashMap.get(installTitle);
RepoModule repoModule = AndroidacyRepoData.getInstance().moduleHashMap.get(installTitle);
String config = null;
boolean mmtReborn = false;
if (repoModule != null && repoModule.moduleInfo.name.length() >= 3) {
@ -273,8 +265,7 @@ public class AndroidacyWebAPI {
mmtReborn = repoModule.moduleInfo.mmtReborn;
}
this.activity.backOnResume = true;
IntentHelper.openInstaller(this.activity,
moduleUrl, installTitle, config, checksum, mmtReborn);
IntentHelper.openInstaller(this.activity, moduleUrl, installTitle, config, checksum, mmtReborn);
}
}
@ -283,7 +274,8 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public void openNativeModuleDialog(String moduleUrl, String moduleId, String checksum) {
if (this.consumedAction) return;
if (this.consumedAction)
return;
this.consumedAction = true;
this.downloadMode = false;
if (!AndroidacyUtil.isAndroidacyLink(moduleUrl)) {
@ -342,15 +334,15 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public void hideActionBar() {
if (this.consumedAction) return;
if (this.consumedAction)
return;
this.consumedAction = true;
this.activity.runOnUiThread(() -> {
this.activity.hideActionBar();
this.consumedAction = false;
if (this.allowHideNote) {
this.allowHideNote = false;
this.activity.webViewNote
.setVisibility(View.GONE);
this.activity.webViewNote.setVisibility(View.GONE);
}
});
}
@ -361,7 +353,8 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public void showActionBar(final String title) {
if (this.consumedAction) return;
if (this.consumedAction)
return;
this.consumedAction = true;
this.activity.runOnUiThread(() -> {
this.activity.showActionBar();
@ -379,8 +372,7 @@ public class AndroidacyWebAPI {
@JavascriptInterface
public boolean isAndroidacyModule(String moduleId) {
LocalModuleInfo localModuleInfo = ModuleManager.getINSTANCE().getModules().get(moduleId);
return localModuleInfo != null && ("Androidacy".equals(localModuleInfo.author) ||
AndroidacyUtil.isAndroidacyLink(localModuleInfo.config));
return localModuleInfo != null && ("Androidacy".equals(localModuleInfo.author) || AndroidacyUtil.isAndroidacyLink(localModuleInfo.config));
}
/**
@ -389,15 +381,16 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public String getAndroidacyModuleFile(String moduleId, String moduleFile) {
if (moduleFile == null || this.consumedAction ||
!this.isAndroidacyModule(moduleId)) return "";
if (moduleFile == null || this.consumedAction || !this.isAndroidacyModule(moduleId))
return "";
File moduleFolder = new File("/data/adb/modules/" + moduleId);
File absModuleFile = new File(moduleFolder, moduleFile).getAbsoluteFile();
if (!absModuleFile.getPath().startsWith(moduleFolder.getPath())) return "";
if (!absModuleFile.getPath().startsWith(moduleFolder.getPath()))
return "";
try {
return new String(Files.readSU(absModuleFile
.getAbsoluteFile()), StandardCharsets.UTF_8);
} catch (IOException e) {
return new String(Files.readSU(absModuleFile.getAbsoluteFile()), StandardCharsets.UTF_8);
} catch (
IOException e) {
return "";
}
}
@ -408,15 +401,14 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public boolean setAndroidacyModuleMeta(String moduleId, String content) {
if (content == null || this.consumedAction ||
!this.isAndroidacyModule(moduleId)) return false;
File androidacyMetaFile = new File(
"/data/adb/modules/" + moduleId + "/.androidacy");
if (content == null || this.consumedAction || !this.isAndroidacyModule(moduleId))
return false;
File androidacyMetaFile = new File("/data/adb/modules/" + moduleId + "/.androidacy");
try {
Files.writeSU(androidacyMetaFile,
content.getBytes(StandardCharsets.UTF_8));
Files.writeSU(androidacyMetaFile, content.getBytes(StandardCharsets.UTF_8));
return true;
} catch (IOException e) {
} catch (
IOException e) {
return false;
}
}
@ -442,8 +434,7 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public int getMagiskVersionCode() {
return InstallerInitializer.peekMagiskPath() == null ? 0 :
InstallerInitializer.peekMagiskVersion();
return InstallerInitializer.peekMagiskPath() == null ? 0 : InstallerInitializer.peekMagiskVersion();
}
/**
@ -480,8 +471,7 @@ public class AndroidacyWebAPI {
Resources.Theme theme = this.activity.getTheme();
TypedValue typedValue = new TypedValue();
theme.resolveAttribute(R.attr.colorPrimary, typedValue, true);
if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
return typedValue.data;
}
theme.resolveAttribute(android.R.attr.colorAccent, typedValue, true);
@ -504,8 +494,7 @@ public class AndroidacyWebAPI {
Resources.Theme theme = this.activity.getTheme();
TypedValue typedValue = new TypedValue();
theme.resolveAttribute(R.attr.backgroundColor, typedValue, true);
if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
return typedValue.data;
}
theme.resolveAttribute(android.R.attr.background, typedValue, true);
@ -517,11 +506,9 @@ public class AndroidacyWebAPI {
*/
@JavascriptInterface
public String getMonetColor(String id) {
@SuppressLint("DiscouragedApi") int nameResourceID = this.activity.getResources().getIdentifier("@android:color/" + id,
"color", this.activity.getApplicationInfo().packageName);
@SuppressLint("DiscouragedApi") int nameResourceID = this.activity.getResources().getIdentifier("@android:color/" + id, "color", this.activity.getApplicationInfo().packageName);
if (nameResourceID == 0) {
throw new IllegalArgumentException(
"No resource string found with name " + id);
throw new IllegalArgumentException("No resource string found with name " + id);
} else {
int color = ContextCompat.getColor(this.activity, nameResourceID);
int red = Color.red(color);

@ -70,12 +70,12 @@ public final class ModuleManager extends SyncManager {
if (!FORCE_NEED_FALLBACK && needFallback) {
Log.e(TAG, "Failed to detect modules folder, using fallback instead.");
}
if (BuildConfig.DEBUG) Log.i("NoodleDebug", "Scan");
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Scan");
if (modules != null) {
for (String module : modules) {
if (!new SuFile("/data/adb/modules/" + module).isDirectory())
continue; // Ignore non directory files inside modules folder
if (BuildConfig.DEBUG) Log.i("NoodleDebug", module);
if (BuildConfig.DEBUG) Log.d("NoodleDebug", module);
LocalModuleInfo moduleInfo = moduleInfos.get(module);
if (moduleInfo == null) {
moduleInfo = new LocalModuleInfo(module);
@ -113,18 +113,18 @@ public final class ModuleManager extends SyncManager {
PropUtils.readProperties(moduleInfo,
"/data/adb/modules/" + module + "/module.prop", true);
} catch (Exception e) {
if (BuildConfig.DEBUG) Log.i(TAG, "Failed to parse metadata!", e);
if (BuildConfig.DEBUG) Log.d(TAG, "Failed to parse metadata!", e);
moduleInfo.flags |= FLAG_MM_INVALID;
}
}
}
if (BuildConfig.DEBUG) Log.i("NoodleDebug", "Scan update");
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Scan update");
String[] modules_update = new SuFile("/data/adb/modules_update").list();
if (modules_update != null) {
for (String module : modules_update) {
if (!new SuFile("/data/adb/modules_update/" + module).isDirectory())
continue; // Ignore non directory files inside modules folder
if (BuildConfig.DEBUG) Log.i("NoodleDebug", module);
if (BuildConfig.DEBUG) Log.d("NoodleDebug", module);
LocalModuleInfo moduleInfo = moduleInfos.get(module);
if (moduleInfo == null) {
moduleInfo = new LocalModuleInfo(module);
@ -136,18 +136,18 @@ public final class ModuleManager extends SyncManager {
PropUtils.readProperties(moduleInfo,
"/data/adb/modules_update/" + module + "/module.prop", true);
} catch (Exception e) {
if (BuildConfig.DEBUG) Log.i(TAG, "Failed to parse metadata!", e);
if (BuildConfig.DEBUG) Log.d(TAG, "Failed to parse metadata!", e);
moduleInfo.flags |= FLAG_MM_INVALID;
}
}
}
if (BuildConfig.DEBUG) Log.i("NoodleDebug", "Finalize scan");
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Finalize scan");
this.updatableModuleCount = 0;
Iterator<LocalModuleInfo> moduleInfoIterator =
this.moduleInfos.values().iterator();
while (moduleInfoIterator.hasNext()) {
LocalModuleInfo moduleInfo = moduleInfoIterator.next();
if (BuildConfig.DEBUG) Log.i("NoodleDebug", moduleInfo.id);
if (BuildConfig.DEBUG) Log.d("NoodleDebug", moduleInfo.id);
if ((moduleInfo.flags & FLAG_MM_UNPROCESSED) != 0) {
moduleInfoIterator.remove();
continue; // Don't process fallbacks if unreferenced

@ -28,8 +28,7 @@ public class MarkdownUrlLinker {
endCh != '>' && endCh != ')' && endCh != ']') {
linkifyTasks.add(new LinkifyTask(index, end));
extra += (end - index) + 4;
if (BuildConfig.DEBUG) {
Log.i(TAG, "Linkify url: " + url.substring(index, end));
if (BuildConfig.DEBUG) { Log.d(TAG, "Linkify url: " + url.substring(index, end));
}
}
}

@ -220,8 +220,7 @@ public class RepoData extends XRepo {
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled && !this.forceHide;
if (BuildConfig.DEBUG) {
Log.i("RepoData", "Repo " + this.id + " enabled: " + this.enabled + " (forced: " + this.forceHide + ") with preferenceID: " + this.getPreferenceId());
if (BuildConfig.DEBUG) { Log.d("RepoData", "Repo " + this.id + " enabled: " + this.enabled + " (forced: " + this.forceHide + ") with preferenceID: " + this.getPreferenceId());
}
MainApplication.getSharedPreferences().edit().putBoolean("pref_" + this.getPreferenceId() + "_enabled", enabled).apply();
}
@ -232,8 +231,7 @@ public class RepoData extends XRepo {
return;
}
this.forceHide = AppUpdateManager.shouldForceHide(this.id);
if (BuildConfig.DEBUG) {
Log.i("RepoData", "Repo " + this.id + " update enabled: " + this.enabled + " (forced: " + this.forceHide + ") with preferenceID: " + this.getPreferenceId());
if (BuildConfig.DEBUG) { Log.d("RepoData", "Repo " + this.id + " update enabled: " + this.enabled + " (forced: " + this.forceHide + ") with preferenceID: " + this.getPreferenceId());
}
this.enabled = (!this.forceHide) && MainApplication.getSharedPreferences().getBoolean("pref_" + this.getPreferenceId() + "_enabled", true);
}

@ -231,24 +231,24 @@ public final class RepoManager extends SyncManager {
RepoUpdater[] repoUpdaters = new RepoUpdater[repoDatas.length];
int moduleToUpdate = 0;
for (int i = 0; i < repoDatas.length; i++) {
if (BuildConfig.DEBUG) Log.i("RepoManager", "Fetching: " + repoDatas[i].getName());
if (BuildConfig.DEBUG) Log.d("RepoManager", "Fetching: " + repoDatas[i].getName());
moduleToUpdate += (repoUpdaters[i] =
new RepoUpdater(repoDatas[i])).fetchIndex();
updateListener.update(STEP1 / repoDatas.length * (i + 1));
}
if (BuildConfig.DEBUG) Log.i("RepoManag3er", "Updating meta-data");
if (BuildConfig.DEBUG) Log.d("RepoManag3er", "Updating meta-data");
int updatedModules = 0;
boolean allowLowQualityModules = MainApplication.isDisableLowQualityModuleFilter();
for (int i = 0; i < repoUpdaters.length; i++) {
// Check if the repo is enabled
if (!repoUpdaters[i].repoData.isEnabled()) {
if (BuildConfig.DEBUG) Log.i("RepoManager",
if (BuildConfig.DEBUG) Log.d("RepoManager",
"Skipping disabled repo: " + repoUpdaters[i].repoData.getName());
continue;
}
List<RepoModule> repoModules = repoUpdaters[i].toUpdate();
RepoData repoData = repoDatas[i];
if (BuildConfig.DEBUG) Log.i("RepoManager", "Registering " + repoData.getName());
if (BuildConfig.DEBUG) Log.d("RepoManager", "Registering " + repoData.getName());
for (RepoModule repoModule : repoModules) {
try {
if (repoModule.propUrl != null &&
@ -287,7 +287,7 @@ public final class RepoManager extends SyncManager {
}
}
}
if (BuildConfig.DEBUG) Log.i("RepoManager", "Finishing update");
if (BuildConfig.DEBUG) Log.d("RepoManager", "Finishing update");
this.hasInternet = false;
// Check if we have internet connection
// Attempt to contact connectivitycheck.gstatic.com/generate_204
@ -310,11 +310,11 @@ public final class RepoManager extends SyncManager {
for (int i = 0; i < repoDatas.length; i++) {
// If repo is not enabled, skip
if (!repoDatas[i].isEnabled()) {
if (BuildConfig.DEBUG) Log.i("RepoManager",
if (BuildConfig.DEBUG) Log.d("RepoManager",
"Skipping " + repoDatas[i].getName() + " because it's disabled");
continue;
}
if (BuildConfig.DEBUG) Log.i("RepoManager",
if (BuildConfig.DEBUG) Log.d("RepoManager",
"Finishing: " + repoUpdaters[i].repoData.getName());
this.repoLastSuccess = repoUpdaters[i].finish();
if (!this.repoLastSuccess) {

@ -74,8 +74,7 @@ public class RepoUpdater {
if (this.indexRaw != null) {
try {
Files.write(this.repoData.metaDataCache, this.indexRaw);
if (BuildConfig.DEBUG) {
Log.i(TAG, "Wrote index of " + this.repoData.id);
if (BuildConfig.DEBUG) { Log.d(TAG, "Wrote index of " + this.repoData.id);
}
} catch (IOException e) {
e.printStackTrace();

@ -13,8 +13,6 @@ import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@ -70,7 +68,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.internal.TextWatcherAdapter;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.textfield.MaterialAutoCompleteTextView;
import com.google.common.hash.Hashing;
import com.mikepenz.aboutlibraries.LibsBuilder;
import com.topjohnwu.superuser.internal.UiThreadHandler;
@ -126,7 +123,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
}
if (BuildConfig.DEBUG) {
Log.i(TAG, "getDevicePerformanceClass: androidVersion=" + androidVersion + " cpuCount=" + cpuCount + " memoryClass=" + memoryClass + " maxCpuFreq=" + maxCpuFreq + " devicePerformanceClass=" + devicePerformanceClass);
Log.d(TAG, "getDevicePerformanceClass: androidVersion=" + androidVersion + " cpuCount=" + cpuCount + " memoryClass=" + memoryClass + " maxCpuFreq=" + maxCpuFreq + " devicePerformanceClass=" + devicePerformanceClass);
}
return devicePerformanceClass;
@ -178,7 +175,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
// If transparent theme(s) are set, disable monet
if (themePreference.getValue().equals("transparent_light")) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Transparent theme is set, disabling monet");
Log.d(TAG, "Transparent theme is set, disabling monet");
}
findPreference("pref_enable_monet").setEnabled(false);
// Toggle monet off
@ -202,7 +199,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
});
themePreference.setOnPreferenceChangeListener((preference, newValue) -> {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Theme changed, refreshing activity. New value: " + newValue);
Log.d(TAG, "Theme changed, refreshing activity. New value: " + newValue);
}
// Immediately save
SharedPreferences.Editor editor = getPreferenceManager().getSharedPreferences().edit();
@ -210,7 +207,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
// If theme contains "transparent" then disable monet
if (newValue.toString().contains("transparent")) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Transparent theme is being set, disabling monet");
Log.d(TAG, "Transparent theme is being set, disabling monet");
}
// Show a dialogue warning the user about issues with transparent themes and
// that blur/monet will be disabled
@ -278,7 +275,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
Log.i(TAG, "Restarting app to save crash reporting preference: " + newValue);
Log.d(TAG, "Restarting app to save crash reporting preference: " + newValue);
}
System.exit(0); // Exit app process
});
@ -506,8 +503,19 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
findPreference("pref_report_bug").setVisible(false);
}
linkClickable = findPreference("pref_source_code");
// Set summary to the last commit this build was built from
linkClickable.setSummary(String.format(getString(R.string.source_code_summary), BuildConfig.COMMIT_HASH));
// Set summary to the last commit this build was built from @ User/Repo
// Build userRepo by removing all parts of REMOTE_URL that are not the user/repo
String userRepo = BuildConfig.REMOTE_URL;
// Get the index of the first slash after the protocol (https://)
int firstSlash = userRepo.indexOf('/', 8);
// Check if it ends with .git
if (userRepo.endsWith(".git")) {
// Remove the .git
userRepo = userRepo.substring(0, userRepo.length() - 4);
}
// Remove everything before the first slash
userRepo = userRepo.substring(firstSlash + 1);
linkClickable.setSummary(String.format(getString(R.string.source_code_summary), BuildConfig.COMMIT_HASH, userRepo));
linkClickable.setOnPreferenceClickListener(p -> {
if (devModeStep == 2) {
devModeStep = 0;
@ -529,7 +537,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
});
linkClickable.setOnPreferenceLongClickListener(p -> {
String toastText = requireContext().getString(R.string.link_copied);
clipboard.setPrimaryClip(ClipData.newPlainText(toastText, "https://github.com/Fox2Code/FoxMagiskModuleManager"));
clipboard.setPrimaryClip(ClipData.newPlainText(toastText, BuildConfig.REMOTE_URL + "/tree/" + BuildConfig.COMMIT_HASH));
Toast.makeText(requireContext(), toastText, Toast.LENGTH_SHORT).show();
return true;
});
@ -552,20 +560,10 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
return true;
});
// Determine if this is an official build based on the signature
boolean isOfficial = false;
try {
// Get the signature of the key used to sign the app
@SuppressLint("PackageManagerGetSignatures") Signature[] signatures = requireContext().getPackageManager().getPackageInfo(requireContext().getPackageName(), PackageManager.GET_SIGNATURES).signatures;
String officialSignatureHash = "7bec7c4462f4aac616612d9f56a023ee3046e83afa956463b5fab547fd0a0be6";
String ourSignatureHash = Hashing.sha256().hashBytes(signatures[0].toByteArray()).toString();
isOfficial = ourSignatureHash.equals(officialSignatureHash);
} catch (
PackageManager.NameNotFoundException ignored) {
}
String flavor = BuildConfig.FLAVOR;
String type = BuildConfig.BUILD_TYPE;
// Set the summary of pref_pkg_info to something like Github-debug v1.0 (123) (Official)
String pkgInfo = getString(R.string.pref_pkg_info_summary, flavor + "-" + type, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, isOfficial ? getString(R.string.official) : getString(R.string.unofficial));
String pkgInfo = getString(R.string.pref_pkg_info_summary, flavor + "-" + type, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, MainApplication.isOfficial ? getString(R.string.official) : getString(R.string.unofficial));
findPreference("pref_pkg_info").setSummary(pkgInfo);
}
@ -655,7 +653,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
Log.i(TAG, "Restarting app to save staging endpoint preference: " + newValue);
Log.d(TAG, "Restarting app to save staging endpoint preference: " + newValue);
}
System.exit(0); // Exit app process
}).setNegativeButton(android.R.string.cancel, (dialog, which) -> {
@ -680,7 +678,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
Log.i(TAG, "Restarting app to save staging endpoint preference: " + newValue);
Log.d(TAG, "Restarting app to save staging endpoint preference: " + newValue);
}
System.exit(0); // Exit app process
}).show();
@ -755,7 +753,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
Log.i(TAG, "Restarting app to save token preference: " + newValue);
Log.d(TAG, "Restarting app to save token preference: " + newValue);
}
System.exit(0); // Exit app process
}).show();
@ -805,7 +803,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
Log.i(TAG, "Restarting app to save token preference: " + newValue);
Log.d(TAG, "Restarting app to save token preference: " + newValue);
}
System.exit(0); // Exit app process
}).show();
@ -926,7 +924,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
return;
if (!preferenceName.contains("androidacy") && !preferenceName.contains("magisk_alt_repo")) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Setting preference " + preferenceName + " because it is not the Androidacy repo or the Magisk Alt Repo");
Log.d(TAG, "Setting preference " + preferenceName + " because it is not the Androidacy repo or the Magisk Alt Repo");
}
if (repoData == null || repoData.isForceHide()) {
hideRepoData(preferenceName);

@ -267,5 +267,5 @@
<string name="androidacy_update_needed">This app is outdated.</string>
<string name="androidacy_update_needed_message">Please update the app to the latest version.</string>
<string name="androidacy_webview_update_required">Your webview is outdated! Please update it.</string><string name="language_cta">Don\'t see your language?</string><string name="language_cta_desc">Help us by translating it! Tap here to find out more.</string>
<string name="source_code_summary"><b>Commit</b> %1$s</string>
<string name="source_code_summary"><b>Commit</b> %1$s @ %2$s</string>
</resources>

Loading…
Cancel
Save