diff --git a/app/build.gradle b/app/build.gradle
index 2dca1f1..6d5b5bf 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -25,7 +25,7 @@ android {
defaultConfig {
applicationId "com.fox2code.mmm"
- minSdk 21
+ minSdk 23
targetSdk 33
versionCode 61
versionName "1.0.1"
diff --git a/app/src/main/java/com/fox2code/mmm/AppUpdateManager.java b/app/src/main/java/com/fox2code/mmm/AppUpdateManager.java
index d29f460..b02c5af 100644
--- a/app/src/main/java/com/fox2code/mmm/AppUpdateManager.java
+++ b/app/src/main/java/com/fox2code/mmm/AppUpdateManager.java
@@ -111,9 +111,9 @@ public class AppUpdateManager {
this.latestPreRelease = "";
this.preReleaseNewer = false;
}
- Log.d(TAG, "Latest release: " + latestRelease);
- Log.d(TAG, "Latest pre-release: " + latestPreRelease);
- Log.d(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) {
diff --git a/app/src/main/java/com/fox2code/mmm/MainActivity.java b/app/src/main/java/com/fox2code/mmm/MainActivity.java
index 65fccd1..069073b 100644
--- a/app/src/main/java/com/fox2code/mmm/MainActivity.java
+++ b/app/src/main/java/com/fox2code/mmm/MainActivity.java
@@ -26,10 +26,10 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView;
import androidx.cardview.widget.CardView;
+import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
@@ -87,6 +87,8 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
private CardView searchCard;
private SearchView searchView;
private boolean initMode;
+ private boolean doSetupNowRunning;
+ private boolean urlFactoryInstalled = false;
public MainActivity() {
this.moduleViewListBuilder = new ModuleViewListBuilder(this);
@@ -104,6 +106,16 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
this.initMode = true;
// Ensure HTTP Cache directories are created
Http.ensureCacheDirs(this);
+ if (!urlFactoryInstalled) {
+ try {
+ ExperimentalCronetEngine cronetEngine = new ExperimentalCronetEngine.Builder(this).build();
+ CronetURLStreamHandlerFactory cronetURLStreamHandlerFactory = new CronetURLStreamHandlerFactory(cronetEngine);
+ URL.setURLStreamHandlerFactory(cronetURLStreamHandlerFactory);
+ urlFactoryInstalled = true;
+ } catch (Throwable t) {
+ Log.e(TAG, "Failed to install CronetURLStreamHandlerFactory", t);
+ }
+ }
BackgroundUpdateChecker.onMainActivityCreate(this);
super.onCreate(savedInstanceState);
this.setActionBarExtraMenuButton(R.drawable.ic_baseline_settings_24, v -> {
@@ -185,6 +197,21 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
}
public void commonNext() {
+ doSetupNowRunning = true;
+ doSetupNow();
+
+ // Wait for doSetupNow to finish
+ while (doSetupNowRunning) {
+ try {
+ //noinspection BusyWait
+ Thread.sleep(100);
+ } catch (InterruptedException ignored) {
+ }
+ }
+ /*if (BuildConfig.DEBUG) {
+ SharedPreferences prefs = MainApplication.getSharedPreferences();
+ if (BuildConfig.DEBUG) Log.d("MainActivity", String.format("Background update check: %s, Crash reporting: %s, Androidacy repo: %s, Magisk alt repo: %s", prefs.getBoolean("pref_background_update_check", false), prefs.getBoolean("pref_crash_reporting", false), prefs.getBoolean("pref_androidacy_repo_enabled", false), prefs.getBoolean("pref_magisk_alt_repo_enabled", false)));
+ }*/
swipeRefreshBlocker = System.currentTimeMillis() + 5_000L;
updateScreenInsets(); // Fix an edge case
if (MainApplication.isShowcaseMode())
@@ -199,21 +226,12 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
updateScreenInsets(getResources().getConfiguration());
});
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- showSetupBox();
-
- // Wait for pref_first_launch to be false
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
- while (prefs.getBoolean("pref_first_launch", true)) {
- try {
- //noinspection BusyWait
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
+ // On every preferences change, log the change if debug is enabled
+ if (BuildConfig.DEBUG) {
+ Log.i("PrefsListener", "onCreate: Preferences: " + MainApplication.getSharedPreferences().getAll());
+ // Log all preferences changes
+ MainApplication.getSharedPreferences().registerOnSharedPreferenceChangeListener((prefs, key) -> Log.i("PrefsListener", "onSharedPreferenceChanged: " + key + " = " + prefs.getAll().get(key)));
}
- ensurePermissions();
Log.i(TAG, "Scanning for modules!");
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Initialize Update");
final int max = ModuleManager.getINSTANCE().getUpdatableModuleCount();
@@ -222,9 +240,18 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
}
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check Update Compat");
AppUpdateManager.getAppUpdateManager().checkUpdateCompat();
+ /*if (BuildConfig.DEBUG) {
+ SharedPreferences prefs = MainApplication.getSharedPreferences();
+ Log.d("MainActivity", String.format("Background update check: %s, Crash reporting: %s, Androidacy repo: %s, Magisk alt repo: %s", prefs.getBoolean("pref_background_update_check", false), prefs.getBoolean("pref_crash_reporting", false), prefs.getBoolean("pref_androidacy_repo_enabled", false), prefs.getBoolean("pref_magisk_alt_repo_enabled", false)));
+ }*/
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)));
NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder);
+
+ /*if (BuildConfig.DEBUG) {
+ SharedPreferences prefs = MainApplication.getSharedPreferences();
+ Log.d("MainActivity", String.format("Background update check: %s, Crash reporting: %s, Androidacy repo: %s, Magisk alt repo: %s", prefs.getBoolean("pref_background_update_check", false), prefs.getBoolean("pref_crash_reporting", false), prefs.getBoolean("pref_androidacy_repo_enabled", false), prefs.getBoolean("pref_magisk_alt_repo_enabled", false)));
+ }*/
if (!NotificationType.NO_INTERNET.shouldRemove()) {
moduleViewListBuilder.addNotification(NotificationType.NO_INTERNET);
} else if (!NotificationType.REPO_UPDATE_FAILED.shouldRemove()) {
@@ -237,6 +264,11 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
moduleViewListBuilder.addNotification(NotificationType.UPDATE_AVAILABLE);
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Check Json Update");
if (max != 0) {
+
+ /*if (BuildConfig.DEBUG) {
+ SharedPreferences prefs = MainApplication.getSharedPreferences();
+ Log.d("MainActivity", String.format("Background update check: %s, Crash reporting: %s, Androidacy repo: %s, Magisk alt repo: %s", prefs.getBoolean("pref_background_update_check", false), prefs.getBoolean("pref_crash_reporting", false), prefs.getBoolean("pref_androidacy_repo_enabled", false), prefs.getBoolean("pref_magisk_alt_repo_enabled", false)));
+ }*/
int current = 0;
// noodleDebug.push("");
for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) {
@@ -263,6 +295,11 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
});
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Apply");
RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendRemoteModules);
+
+ /*if (BuildConfig.DEBUG) {
+ SharedPreferences prefs = MainApplication.getSharedPreferences();
+ Log.d("MainActivity", String.format("Background update check: %s, Crash reporting: %s, Androidacy repo: %s, Magisk alt repo: %s", prefs.getBoolean("pref_background_update_check", false), prefs.getBoolean("pref_crash_reporting", false), prefs.getBoolean("pref_androidacy_repo_enabled", false), prefs.getBoolean("pref_magisk_alt_repo_enabled", false)));
+ }*/
moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
Log.i(TAG, "Finished app opening state!");
// noodleDebug.unbind();
@@ -279,16 +316,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
String lastEventId = preferences.getString("lastEventId", "");
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Last Event ID: " + lastEventId);
if (!lastEventId.equals("")) {
- try {
- ExperimentalCronetEngine cronetEngine = new ExperimentalCronetEngine.Builder(this).build();
- CronetURLStreamHandlerFactory cronetURLStreamHandlerFactory = new CronetURLStreamHandlerFactory(cronetEngine);
- URL.setURLStreamHandlerFactory(cronetURLStreamHandlerFactory);
- } catch (Exception e) {
- if (BuildConfig.DEBUG) {
- Log.w(TAG, "Failed to setup cronet HTTPURLConnection factory", e);
- Log.w(TAG, "This might mean the factory is already set");
- }
- }
// Three edit texts for the user to enter their email, name and a description of the issue
EditText email = new EditText(this);
email.setHint(R.string.email);
@@ -319,10 +346,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
// Prevent strict mode violation
new Thread(() -> {
try {
- // Use HTTPConnectionURL to send a post request to the sentry server
- ExperimentalCronetEngine cronetEngine = new ExperimentalCronetEngine.Builder(this).build();
- CronetURLStreamHandlerFactory cronetURLStreamHandlerFactory = new CronetURLStreamHandlerFactory(cronetEngine);
- URL.setURLStreamHandlerFactory(cronetURLStreamHandlerFactory);
HttpURLConnection connection = (HttpURLConnection) new URL("https" + "://sentry.io/api/0/projects/androidacy-i6/foxmmm/user-feedback/").openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
@@ -588,33 +611,50 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
@SuppressLint("RestrictedApi")
private void ensurePermissions() {
+ if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Ensure Permissions");
// First, check if user has said don't ask again by checking if pref_dont_ask_again_notification_permission is true
if (!PreferenceManager.getDefaultSharedPreferences(this).getBoolean("pref_dont_ask_again_notification_permission", false)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
- // Show a dialog explaining why we need this permission, which is to show
- // notifications for updates
- runOnUiThread(() -> {
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
- builder.setTitle(R.string.permission_notification_title);
- builder.setMessage(R.string.permission_notification_message);
- // Don't ask again checkbox
- View view = getLayoutInflater().inflate(R.layout.dialog_checkbox, null);
- CheckBox checkBox = view.findViewById(R.id.checkbox);
- checkBox.setText(R.string.dont_ask_again);
- checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("pref_dont_ask_again_notification_permission", isChecked).apply());
- builder.setView(view);
- builder.setPositiveButton(R.string.permission_notification_grant, (dialog, which) -> {
- // Request the permission
- this.requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, 0);
- });
- builder.setNegativeButton(R.string.cancel, (dialog, which) -> {
- // Set pref_background_update_check to false and dismiss dialog
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- prefs.edit().putBoolean("pref_background_update_check", false).apply();
- dialog.dismiss();
+ if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Request Notification Permission");
+ if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.POST_NOTIFICATIONS)) {
+ // Show a dialog explaining why we need this permission, which is to show
+ // notifications for updates
+ runOnUiThread(() -> {
+ if (BuildConfig.DEBUG)
+ Log.d("NoodleDebug", "Show Notification Permission Dialog");
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
+ builder.setTitle(R.string.permission_notification_title);
+ builder.setMessage(R.string.permission_notification_message);
+ // Don't ask again checkbox
+ View view = getLayoutInflater().inflate(R.layout.dialog_checkbox, null);
+ CheckBox checkBox = view.findViewById(R.id.checkbox);
+ checkBox.setText(R.string.dont_ask_again);
+ checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("pref_dont_ask_again_notification_permission", isChecked).apply());
+ builder.setView(view);
+ builder.setPositiveButton(R.string.permission_notification_grant, (dialog, which) -> {
+ // Request the permission
+ this.requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, 0);
+ });
+ builder.setNegativeButton(R.string.cancel, (dialog, which) -> {
+ // Set pref_background_update_check to false and dismiss dialog
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.edit().putBoolean("pref_background_update_check", false).apply();
+ dialog.dismiss();
+ });
+ builder.show();
+ if (BuildConfig.DEBUG)
+ Log.d("NoodleDebug", "Show Notification Permission Dialog Done");
});
- builder.show();
- });
+ } else {
+ // Request the permission
+ if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Request Notification Permission");
+ this.requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, 0);
+ if (BuildConfig.DEBUG) {
+ // Log if granted via onRequestPermissionsResult
+ Log.d("NoodleDebug", "Request Notification Permission Done. Result: " + (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED));
+ }
+ doSetupNowRunning = false;
+ }
// Next branch is for < android 13 and user has blocked notifications
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU && !NotificationManagerCompat.from(this).areNotificationsEnabled()) {
runOnUiThread(() -> {
@@ -634,65 +674,77 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
+ doSetupNowRunning = false;
});
builder.setNegativeButton(R.string.cancel, (dialog, which) -> {
// Set pref_background_update_check to false and dismiss dialog
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putBoolean("pref_background_update_check", false).apply();
dialog.dismiss();
+ doSetupNowRunning = false;
});
builder.show();
});
+ } else {
+ doSetupNowRunning = false;
}
+ } else {
+ if (BuildConfig.DEBUG)
+ Log.d("NoodleDebug", "Notification Permission Already Granted or Don't Ask Again");
+ doSetupNowRunning = false;
}
}
// Method to show a setup box on first launch
- @RequiresApi(api = Build.VERSION_CODES.M)
@SuppressLint({"InflateParams", "RestrictedApi", "UnspecifiedImmutableFlag", "ApplySharedPref"})
- private void showSetupBox() {
+ private void doSetupNow() {
+ if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Do setup now");
// Check if this is the first launch
- if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("pref_first_launch", true)) {
- MainApplication.getBootSharedPreferences().edit().putBoolean("mm_first_scan", false).commit();
+ SharedPreferences prefs = MainApplication.getSharedPreferences();
+ boolean firstLaunch = MainApplication.getBootSharedPreferences().getBoolean("first_launch", true);
+ if (BuildConfig.DEBUG) Log.d("Noodle", "First launch: " + firstLaunch);
+ if (firstLaunch) {
// Show setup box
runOnUiThread(() -> {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
builder.setCancelable(false);
builder.setTitle(R.string.setup_title);
- builder.setView(getLayoutInflater().inflate(R.layout.setup_box, null));
+ View view = getLayoutInflater().inflate(R.layout.setup_box, null);
+ builder.setView(view);
// For now, we'll just have the positive button save the preferences and dismiss the dialog
builder.setPositiveButton(R.string.setup_button, (dialog, which) -> {
// Set the preferences
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- prefs.edit().putBoolean("pref_background_update_check",
- ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_background_update_check))).isChecked()).commit();
+ prefs.edit().putBoolean("pref_background_update_check", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_background_update_check))).isChecked()).commit();
prefs.edit().putBoolean("pref_crash_reporting", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_crash_reporting))).isChecked()).commit();
prefs.edit().putBoolean("pref_androidacy_repo_enabled", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_androidacy_repo))).isChecked()).commit();
prefs.edit().putBoolean("pref_magisk_alt_repo_enabled", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_magisk_alt_repo))).isChecked()).commit();
if (BuildConfig.DEBUG) {
- Log.d("MainActivity", String.format("Background update check: %s, Crash reporting: %s, Androidacy repo: %s, Magisk alt repo: %s",
- prefs.getBoolean("pref_background_update_check", false),
- prefs.getBoolean("pref_crash_reporting", false),
- prefs.getBoolean("pref_androidacy_repo_enabled", false),
- prefs.getBoolean("pref_magisk_alt_repo_enabled", false)));
+ Log.d("MainActivity", String.format("Background update check: %s, Crash reporting: %s, Androidacy repo: %s, Magisk alt repo: %s", prefs.getBoolean("pref_background_update_check", false), prefs.getBoolean("pref_crash_reporting", false), prefs.getBoolean("pref_androidacy_repo_enabled", false), prefs.getBoolean("pref_magisk_alt_repo_enabled", false)));
}
// Set pref_first_launch to false
- PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("pref_first_launch",
- false).commit();
+ MainApplication.getBootSharedPreferences().edit().putBoolean("first_launch", false).commit();
// Restart the app
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
finish();
+ startActivity(intent);
+ ensurePermissions();
});
builder.setNegativeButton(R.string.setup_button_skip, (dialog, which) -> {
- // Set pref_first_launch to false
- PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("pref_first_launch",
- false).commit();
+ MainApplication.getBootSharedPreferences().edit().putBoolean("first_launch", false).commit();
dialog.dismiss();
+ ensurePermissions();
});
builder.show();
+ // Set the switches appropriately
+ ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_background_update_check))).setChecked(BuildConfig.ENABLE_AUTO_UPDATER);
+ ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_crash_reporting))).setChecked(BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING);
+ // Repos are a little harder, as the enabled_repos build config is an arraylist
+ ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_androidacy_repo))).setChecked(BuildConfig.ENABLED_REPOS.contains("androidacy_repo"));
+ ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_magisk_alt_repo))).setChecked(BuildConfig.ENABLED_REPOS.contains("magisk_alt_repo"));
});
+ } else {
+ ensurePermissions();
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java
index f14de34..b9258ae 100644
--- a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java
+++ b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java
@@ -108,7 +108,7 @@ public final class AndroidacyRepoData extends RepoData {
deviceId = output;
}
}
- // Now, get device model, manufacturer, and Android version
+ // Now, get device model, manufacturer, and Android version originally from
String deviceModel = android.os.Build.MODEL;
String deviceManufacturer = android.os.Build.MANUFACTURER;
String androidVersion = android.os.Build.VERSION.RELEASE;
diff --git a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyWebAPI.java b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyWebAPI.java
index b2cfb06..13ca53b 100644
--- a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyWebAPI.java
+++ b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyWebAPI.java
@@ -63,7 +63,7 @@ public class AndroidacyWebAPI {
void openNativeModuleDialogRaw(String moduleUrl, String moduleId, String installTitle,
String checksum, boolean canInstall) {
- Log.d(TAG, "ModuleDialog, downloadUrl: " + AndroidacyUtil.hideToken(moduleUrl) +
+ if (BuildConfig.DEBUG) Log.d(TAG, "ModuleDialog, downloadUrl: " + AndroidacyUtil.hideToken(moduleUrl) +
", moduleId: " + moduleId + ", installTitle: " + installTitle +
", checksum: " + checksum + ", canInstall: " + canInstall);
this.downloadMode = false;
@@ -145,7 +145,7 @@ public class AndroidacyWebAPI {
void notifyCompatModeRaw(int value) {
if (this.consumedAction) return;
- Log.d(TAG, "Androidacy Compat mode: " + value);
+ if (BuildConfig.DEBUG) Log.d(TAG, "Androidacy Compat mode: " + value);
this.notifiedCompatMode = value;
if (value < 0) {
value = 0;
@@ -180,7 +180,7 @@ public class AndroidacyWebAPI {
if (this.consumedAction) return;
this.consumedAction = true;
this.downloadMode = false;
- Log.d(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);
}
@@ -194,7 +194,7 @@ public class AndroidacyWebAPI {
if (this.consumedAction) return;
this.consumedAction = true;
this.downloadMode = false;
- Log.d(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);
}
@@ -238,7 +238,7 @@ public class AndroidacyWebAPI {
}
this.consumedAction = true;
this.downloadMode = false;
- Log.d(TAG, "Received install request: " +
+ 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");
@@ -375,6 +375,7 @@ public class AndroidacyWebAPI {
/**
* Return true if the module is an Andoridacy module.
*/
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
@JavascriptInterface
public boolean isAndroidacyModule(String moduleId) {
LocalModuleInfo localModuleInfo = ModuleManager.getINSTANCE().getModules().get(moduleId);
@@ -447,7 +448,7 @@ public class AndroidacyWebAPI {
/**
* Return current android sdk-int version code, see:
- * https://source.android.com/setup/start/build-numbers
+ * right here
*/
@JavascriptInterface
public int getAndroidVersionCode() {
diff --git a/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java b/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java
index df4f53e..3d8888a 100644
--- a/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java
+++ b/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java
@@ -113,7 +113,7 @@ public final class ModuleManager extends SyncManager {
PropUtils.readProperties(moduleInfo,
"/data/adb/modules/" + module + "/module.prop", true);
} catch (Exception e) {
- Log.d(TAG, "Failed to parse metadata!", e);
+ if (BuildConfig.DEBUG) Log.d(TAG, "Failed to parse metadata!", e);
moduleInfo.flags |= FLAG_MM_INVALID;
}
}
@@ -136,7 +136,7 @@ public final class ModuleManager extends SyncManager {
PropUtils.readProperties(moduleInfo,
"/data/adb/modules_update/" + module + "/module.prop", true);
} catch (Exception e) {
- Log.d(TAG, "Failed to parse metadata!", e);
+ if (BuildConfig.DEBUG) Log.d(TAG, "Failed to parse metadata!", e);
moduleInfo.flags |= FLAG_MM_INVALID;
}
}
diff --git a/app/src/main/java/com/fox2code/mmm/repo/RepoData.java b/app/src/main/java/com/fox2code/mmm/repo/RepoData.java
index 26aa6c6..02712b4 100644
--- a/app/src/main/java/com/fox2code/mmm/repo/RepoData.java
+++ b/app/src/main/java/com/fox2code/mmm/repo/RepoData.java
@@ -42,7 +42,7 @@ public class RepoData extends XRepo {
public String name, website, support, donate, submitModule;
private boolean forceHide, enabled; // Cache for speed
- protected RepoData(String url, File cacheRoot, SharedPreferences cachedPreferences) {
+ public RepoData(String url, File cacheRoot, SharedPreferences cachedPreferences) {
this.url = url;
this.id = RepoManager.internalIdOfUrl(url);
this.cacheRoot = cacheRoot;
diff --git a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java
index 9e8dc38..659d24d 100644
--- a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java
+++ b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java
@@ -75,12 +75,12 @@ public final class RepoManager extends SyncManager {
this.repoData = new LinkedHashMap<>();
this.modules = new HashMap<>();
// We do not have repo list config yet.
+ this.androidacyRepoData = this.addAndroidacyRepoData();
RepoData altRepo = this.addRepoData(
MAGISK_ALT_REPO, "Magisk Modules Alt Repo");
altRepo.defaultWebsite = RepoManager.MAGISK_ALT_REPO_HOMEPAGE;
altRepo.defaultSubmitModule =
"https://github.com/Magisk-Modules-Alt-Repo/submission/issues";
- this.androidacyRepoData = this.addAndroidacyRepoData();
this.customRepoManager = new CustomRepoManager(mainApplication, this);
XHooks.onRepoManagerInitialize();
// Populate default cache
@@ -145,10 +145,10 @@ public final class RepoManager extends SyncManager {
static boolean isBuiltInRepo(String repo) {
switch (repo) {
- case RepoManager.MAGISK_ALT_REPO:
- case RepoManager.MAGISK_ALT_REPO_JSDELIVR:
case RepoManager.ANDROIDACY_MAGISK_REPO_ENDPOINT:
case RepoManager.ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT:
+ case RepoManager.MAGISK_ALT_REPO:
+ case RepoManager.MAGISK_ALT_REPO_JSDELIVR:
return true;
}
return false;
diff --git a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java
index 58ba64d..907e635 100644
--- a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java
+++ b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java
@@ -1,6 +1,9 @@
package com.fox2code.mmm.settings;
+import static java.lang.Integer.parseInt;
+
import android.annotation.SuppressLint;
+import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
@@ -70,8 +73,10 @@ import com.topjohnwu.superuser.internal.UiThreadHandler;
import org.json.JSONException;
import java.io.IOException;
+import java.io.RandomAccessFile;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
+import java.util.Locale;
import java.util.Objects;
import java.util.Random;
@@ -81,6 +86,50 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
private static boolean devModeStepFirstBootIgnore = MainApplication.isDeveloper();
private static int devModeStep = 0;
+ // Shamelessly adapted from https://github.com/DrKLO/Telegram/blob/2c71f6c92b45386f0c2b25f1442596462404bb39/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java#L1254
+ public final static int PERFORMANCE_CLASS_LOW = 0;
+ public final static int PERFORMANCE_CLASS_AVERAGE = 1;
+ public final static int PERFORMANCE_CLASS_HIGH = 2;
+
+ @PerformanceClass
+ public static int getDevicePerformanceClass() {
+ int devicePerformanceClass;
+ int androidVersion = Build.VERSION.SDK_INT;
+ int cpuCount = Runtime.getRuntime().availableProcessors();
+ int memoryClass =
+ ((ActivityManager) MainApplication.getINSTANCE().getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
+ int totalCpuFreq = 0;
+ int freqResolved = 0;
+ for (int i = 0; i < cpuCount; i++) {
+ try {
+ RandomAccessFile reader = new RandomAccessFile(String.format(Locale.ENGLISH, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", i), "r");
+ String line = reader.readLine();
+ if (line != null) {
+ totalCpuFreq += parseInt(line) / 1000;
+ freqResolved++;
+ }
+ reader.close();
+ } catch (Throwable ignore) {}
+ }
+ int maxCpuFreq = freqResolved == 0 ? -1 : (int) Math.ceil(totalCpuFreq / (float) freqResolved);
+
+ if (androidVersion < 21 || cpuCount <= 2 || memoryClass <= 100 || cpuCount <= 4 && maxCpuFreq != -1 && maxCpuFreq <= 1250 || cpuCount <= 4 && maxCpuFreq <= 1600 && memoryClass <= 128 && androidVersion <= 21 || cpuCount <= 4 && maxCpuFreq <= 1300 && memoryClass <= 128 && androidVersion <= 24) {
+ devicePerformanceClass = PERFORMANCE_CLASS_LOW;
+ } else if (cpuCount < 8 || memoryClass <= 160 || maxCpuFreq != -1 && maxCpuFreq <= 2050 || maxCpuFreq == -1 && cpuCount == 8 && androidVersion <= 23) {
+ devicePerformanceClass = PERFORMANCE_CLASS_AVERAGE;
+ } else {
+ devicePerformanceClass = PERFORMANCE_CLASS_HIGH;
+ }
+
+ if (BuildConfig.DEBUG) {
+ Log.d(TAG, "getDevicePerformanceClass: androidVersion=" + androidVersion + " cpuCount=" + cpuCount + " memoryClass=" + memoryClass + " maxCpuFreq=" + maxCpuFreq + " devicePerformanceClass=" + devicePerformanceClass);
+ }
+
+ return devicePerformanceClass;
+ }
+
+ public @interface PerformanceClass {}
+
@Override
protected void onCreate(Bundle savedInstanceState) {
devModeStep = 0;
@@ -232,13 +281,8 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
int mPendingIntentId = 123456;
// If < 23, FLAG_IMMUTABLE is not available
PendingIntent mPendingIntent;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- } else {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
- }
+ mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
+ mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
@@ -252,9 +296,36 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
return true;
});
Preference enableBlur = findPreference("pref_enable_blur");
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
- enableBlur.setSummary(R.string.require_android_6);
- enableBlur.setEnabled(false);
+ // Disable blur on low performance devices
+ if (getDevicePerformanceClass() < PERFORMANCE_CLASS_AVERAGE) {
+ // Show a warning
+ enableBlur.setOnPreferenceChangeListener((preference, newValue) -> {
+ if (newValue.equals(true)) {
+ new MaterialAlertDialogBuilder(requireContext())
+ .setTitle(R.string.low_performance_device_dialogue_title)
+ .setMessage(R.string.low_performance_device_dialogue_message)
+ .setPositiveButton(R.string.ok, (dialog, which) -> {
+ // Toggle blur on
+ ((TwoStatePreference) findPreference("pref_enable_blur")).setChecked(true);
+ SharedPreferences.Editor editor =
+ getPreferenceManager().getSharedPreferences().edit();
+ editor.putBoolean("pref_enable_blur", true).apply();
+ // Set summary
+ findPreference("pref_enable_blur").setSummary(R.string.blur_disabled_summary);
+ })
+ .setNegativeButton(R.string.cancel, (dialog, which) -> {
+ // Revert to blur on
+ ((TwoStatePreference) findPreference("pref_enable_blur")).setChecked(false);
+ SharedPreferences.Editor editor =
+ getPreferenceManager().getSharedPreferences().edit();
+ editor.putBoolean("pref_enable_blur", false).apply();
+ // Set summary
+ findPreference("pref_enable_blur").setSummary(null);
+ })
+ .show();
+ }
+ return true;
+ });
}
Preference disableMonet = findPreference("pref_enable_monet");
@@ -566,13 +637,8 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
int mPendingIntentId = 123456;
// If < 23, FLAG_IMMUTABLE is not available
PendingIntent mPendingIntent;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- } else {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
- }
+ mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
+ mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
@@ -603,13 +669,8 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
int mPendingIntentId = 123456;
// If < 23, FLAG_IMMUTABLE is not available
PendingIntent mPendingIntent;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- } else {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
- }
+ mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
+ mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
@@ -694,13 +755,8 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
int mPendingIntentId = 123456;
// If < 23, FLAG_IMMUTABLE is not available
PendingIntent mPendingIntent;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- } else {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
- }
+ mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
+ mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
@@ -752,13 +808,8 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
int mPendingIntentId = 123456;
// If < 23, FLAG_IMMUTABLE is not available
PendingIntent mPendingIntent;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- } else {
- mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
- mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
- }
+ mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId,
+ mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
if (BuildConfig.DEBUG) {
diff --git a/app/src/main/res/layout/setup_box.xml b/app/src/main/res/layout/setup_box.xml
index c362f2c..994d6bb 100644
--- a/app/src/main/res/layout/setup_box.xml
+++ b/app/src/main/res/layout/setup_box.xml
@@ -42,7 +42,7 @@
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
- android:checked="true"
+ android:checked="false"
android:key="pref_androidacy_repo_enabled"
android:text="@string/setup_androidacy_repo"
android:textSize="14sp" />
@@ -65,7 +65,7 @@
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="2dp"
- android:checked="true"
+ android:checked="false"
android:text="@string/setup_custom_repos"
android:textSize="12sp" />
@@ -86,7 +86,7 @@
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
- android:checked="true"
+ android:checked="false"
android:key="pref_crash_reporting_enabled"
android:text="@string/setup_crash_reporting"
android:textSize="14sp" />
@@ -98,7 +98,7 @@
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
- android:checked="true"
+ android:checked="false"
android:key="pref_background_update_check"
android:text="@string/setup_background_update_check"
android:textSize="14sp" />
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0e85cc0..bd522d7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -222,15 +222,20 @@
Official
Unofficial
First time setup
- Looks like this is your first time opening the app.\nPick
- the basic options you desire below. You can change them later in settings.
+ Welcome! This app will help you install and manage modules
+ for Magisk. To get started, please select the options below. Everything can be
+ configured from settings later.
Finish setup
Allow us to check for updates in the background. May use more battery.
Enable the Androidacy repo, which features user reviews, automatic virus scans, fast updates, a wide selection, and is backed by Androidacy.
- Enable the Magisk Alternative Repo. Less rules and reviewing than the original. Fully hosted on GitHub.
+
+ Enable the Magisk Alternative Repo. Significantly more lax
+ than the original, but at the cost of some safety and privacy. Fully hosted on GitHub
+ .
Enable automatic crash reporting and performance monitoring. Crash reports are anonymized with all personal info removed, and are onlly accessible to the developers. Uses sentry.io.
You can add custom repos later in settings.
Repos
Misc settings
- Skip
+ SkipEnabling blur on lower-end deviceYou are trying to enable blur on a device that may not perform well with it.\nYou may enable it, but this may lead to a poor user experience and we recommend you don\'t.
diff --git a/app/src/main/res/xml/repo_preferences.xml b/app/src/main/res/xml/repo_preferences.xml
index d85af87..d8b0e2a 100644
--- a/app/src/main/res/xml/repo_preferences.xml
+++ b/app/src/main/res/xml/repo_preferences.xml
@@ -1,35 +1,5 @@
-
-
-
-
-
-
-
@@ -87,6 +57,36 @@
app:singleLineTitle="false"
app:summary="@string/androidacy_repo_info" />
+
+
+
+
+
+
+