Working setup box

Also bumps minimum android sdk to 23 (aka Marshmallow) Android 5.x just isn't popular anymore and magisk even has poor support for it.

Also warn about blur on low-end devices

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/242/head
androidacy-user 1 year ago
parent 2c675577cb
commit 414caf3dbe

@ -25,7 +25,7 @@ android {
defaultConfig {
applicationId "com.fox2code.mmm"
minSdk 21
minSdk 23
targetSdk 33
versionCode 61
versionName "1.0.1"

@ -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) {

@ -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();
}
}
}

@ -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;

@ -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
* <a href="https://source.android.com/setup/start/build-numbers">right here</a>
*/
@JavascriptInterface
public int getAndroidVersionCode() {

@ -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;
}
}

@ -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;

@ -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;

@ -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) {

@ -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" />

@ -222,15 +222,20 @@
<string name="official">Official</string>
<string name="unofficial">Unofficial</string>
<string name="setup_title">First time setup</string>
<string name="setup_message">Looks like this is your first time opening the app.\nPick
the basic options you desire below. You can change them later in settings.</string>
<string name="setup_message">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.</string>
<string name="setup_button">Finish setup</string>
<string name="setup_background_update_check">Allow us to check for updates in the background. May use more battery.</string>
<string name="setup_androidacy_repo">Enable the Androidacy repo, which features user reviews, automatic virus scans, fast updates, a wide selection, and is backed by Androidacy.</string>
<string name="setup_magisk_alt_repo">Enable the Magisk Alternative Repo. Less rules and reviewing than the original. Fully hosted on GitHub.</string>
<!-- Maybe once alt repo fixes their shit and stops allowing crappy modules or outright
kanged modules, we'll reword this. -->
<string name="setup_magisk_alt_repo">Enable the Magisk Alternative Repo. Significantly more lax
than the original, but at the cost of some safety and privacy. Fully hosted on GitHub
.</string>
<string name="setup_crash_reporting">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.</string>
<string name="setup_custom_repos">You can add custom repos later in settings.</string>
<string name="repos">Repos</string>
<string name="misc">Misc settings</string>
<string name="setup_button_skip">Skip</string>
<string name="setup_button_skip">Skip</string><string name="low_performance_device_dialogue_title">Enabling blur on lower-end device</string><string name="low_performance_device_dialogue_message">You 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.</string>
</resources>

@ -1,35 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:key="pref_magisk_alt_repo"
app:title="@string/loading">
<SwitchPreferenceCompat
app:icon="@drawable/ic_baseline_extension_24"
app:key="pref_magisk_alt_repo_enabled"
app:singleLineTitle="false"
app:switchTextOff="@string/repo_disabled"
app:switchTextOn="@string/repo_enabled" />
<com.fox2code.mmm.settings.LongClickablePreference
app:icon="@drawable/ic_baseline_language_24"
app:key="pref_magisk_alt_repo_website"
app:singleLineTitle="false"
app:title="@string/website" />
<com.fox2code.mmm.settings.LongClickablePreference
app:icon="@drawable/ic_baseline_support_24"
app:key="pref_magisk_alt_repo_support"
app:singleLineTitle="false"
app:title="@string/support" />
<com.fox2code.mmm.settings.LongClickablePreference
app:icon="@drawable/ic_baseline_monetization_on_24"
app:key="pref_magisk_alt_repo_donate"
app:singleLineTitle="false"
app:title="@string/donate" />
<com.fox2code.mmm.settings.LongClickablePreference
app:icon="@drawable/ic_baseline_upload_file_24"
app:key="pref_magisk_alt_repo_submit"
app:singleLineTitle="false"
app:title="@string/submit_modules" />
</PreferenceCategory>
<PreferenceCategory
app:key="pref_androidacy_repo"
app:title="@string/loading">
@ -87,6 +57,36 @@
app:singleLineTitle="false"
app:summary="@string/androidacy_repo_info" />
</PreferenceCategory>
<PreferenceCategory
app:key="pref_magisk_alt_repo"
app:title="@string/loading">
<SwitchPreferenceCompat
app:icon="@drawable/ic_baseline_extension_24"
app:key="pref_magisk_alt_repo_enabled"
app:singleLineTitle="false"
app:switchTextOff="@string/repo_disabled"
app:switchTextOn="@string/repo_enabled" />
<com.fox2code.mmm.settings.LongClickablePreference
app:icon="@drawable/ic_baseline_language_24"
app:key="pref_magisk_alt_repo_website"
app:singleLineTitle="false"
app:title="@string/website" />
<com.fox2code.mmm.settings.LongClickablePreference
app:icon="@drawable/ic_baseline_support_24"
app:key="pref_magisk_alt_repo_support"
app:singleLineTitle="false"
app:title="@string/support" />
<com.fox2code.mmm.settings.LongClickablePreference
app:icon="@drawable/ic_baseline_monetization_on_24"
app:key="pref_magisk_alt_repo_donate"
app:singleLineTitle="false"
app:title="@string/donate" />
<com.fox2code.mmm.settings.LongClickablePreference
app:icon="@drawable/ic_baseline_upload_file_24"
app:key="pref_magisk_alt_repo_submit"
app:singleLineTitle="false"
app:title="@string/submit_modules" />
</PreferenceCategory>
<PreferenceCategory
app:key="pref_custom_repo_0"
app:title="@string/loading">

Loading…
Cancel
Save