diff --git a/app/src/main/java/com/fox2code/mmm/MainActivity.java b/app/src/main/java/com/fox2code/mmm/MainActivity.java index ed9e858..b0a079e 100644 --- a/app/src/main/java/com/fox2code/mmm/MainActivity.java +++ b/app/src/main/java/com/fox2code/mmm/MainActivity.java @@ -56,6 +56,7 @@ import org.chromium.net.CronetEngine; import java.io.File; import java.net.URL; +import java.util.Objects; import timber.log.Timber; @@ -135,7 +136,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe } setContentView(R.layout.activity_main); this.setTitle(R.string.app_name); - this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 0); + this.getWindow().setFlags(WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW, WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW); setActionBarBackground(null); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes(); @@ -285,9 +286,8 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe // On every preferences change, log the change if debug is enabled if (BuildConfig.DEBUG) { - Timber.d("onCreate: Preferences: %s", MainApplication.getSharedPreferences("mmm").getAll()); // Log all preferences changes - MainApplication.getSharedPreferences("mmm").registerOnSharedPreferenceChangeListener((prefs, key) -> Timber.i("onSharedPreferenceChanged: " + key + " = " + prefs.getAll().get(key))); + MainApplication.getSharedPreferences().registerOnSharedPreferenceChangeListener((prefs, key) -> Timber.i("onSharedPreferenceChanged: " + key + " = " + prefs.getAll().get(key))); } Timber.i("Scanning for modules!"); @@ -379,17 +379,21 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe private void updateScreenInsets(Configuration configuration) { boolean landscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE; int bottomInset = (landscape ? 0 : this.getNavigationBarHeight()); - int statusBarHeight = getStatusBarHeight(); + int statusBarHeight = getStatusBarHeight() + FoxDisplay.dpToPixel(2); int actionBarHeight = getActionBarHeight(); int combinedBarsHeight = statusBarHeight + actionBarHeight; this.swipeRefreshLayout.setProgressViewOffset(false, swipeRefreshLayoutOrigStartOffset + combinedBarsHeight, swipeRefreshLayoutOrigEndOffset + combinedBarsHeight); - this.moduleViewListBuilder.setHeaderPx(Math.max(statusBarHeight, combinedBarsHeight - FoxDisplay.dpToPixel(4))); + this.moduleViewListBuilder.setHeaderPx(Math.max(statusBarHeight, combinedBarsHeight)); + this.moduleViewListBuilderOnline.setHeaderPx(Math.max(statusBarHeight, combinedBarsHeight)); this.moduleViewListBuilder.setFooterPx(FoxDisplay.dpToPixel(4) + bottomInset + this.searchCard.getHeight()); + this.moduleViewListBuilderOnline.setFooterPx(FoxDisplay.dpToPixel(4) + bottomInset + this.searchCard.getHeight()); this.searchCard.setRadius(this.searchCard.getHeight() / 2F); this.moduleViewListBuilder.updateInsets(); //this.actionBarBlur.invalidate(); this.overScrollInsetTop = combinedBarsHeight; this.overScrollInsetBottom = bottomInset; + // set root_container to have zero padding + findViewById(R.id.root_container).setPadding(0, statusBarHeight, 0, 0); Timber.i("(" + this.searchCard.getHeight() + ")"); } @@ -705,11 +709,18 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe private void checkShowInitialSetup() { if (BuildConfig.DEBUG) Timber.i("Checking if we need to run setup"); - // Check if this is the first launch - SharedPreferences prefs = MainApplication.getSharedPreferences("mmm"); - boolean firstLaunch = prefs.getString("last_shown_setup", null) == null; - if (BuildConfig.DEBUG) - Timber.i("First launch: %s", firstLaunch); + // Check if this is the first launch using prefs and if doSetupRestarting was passed in the intent + SharedPreferences prefs = MainApplication.getSharedPreferences(); + boolean firstLaunch = !Objects.equals(prefs.getString("last_shown_setup", null), "v1"); + // First launch + // this is intentionally separate from the above if statement, because it needs to be checked even if the first launch check is true due to some weird edge cases + if (getIntent().getBooleanExtra("doSetupRestarting", false)) { + // Restarting setup + firstLaunch = false; + } + if (BuildConfig.DEBUG) { + Timber.i("First launch: %s, pref value: %s", firstLaunch, prefs.getString("last_shown_setup", null)); + } if (firstLaunch) { doSetupNowRunning = true; // Launch setup wizard diff --git a/app/src/main/java/com/fox2code/mmm/MainApplication.java b/app/src/main/java/com/fox2code/mmm/MainApplication.java index 1822928..564e84e 100644 --- a/app/src/main/java/com/fox2code/mmm/MainApplication.java +++ b/app/src/main/java/com/fox2code/mmm/MainApplication.java @@ -12,8 +12,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; import android.os.SystemClock; -import android.security.keystore.KeyProperties; -import android.util.Base64; import android.util.Log; import androidx.annotation.NonNull; @@ -36,16 +34,6 @@ import com.google.common.hash.Hashing; import com.topjohnwu.superuser.Shell; import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; @@ -55,13 +43,6 @@ import java.util.Locale; import java.util.Objects; import java.util.Random; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; - import io.noties.markwon.Markwon; import io.noties.markwon.html.HtmlPlugin; import io.noties.markwon.image.ImagesPlugin; @@ -125,6 +106,10 @@ public class MainApplication extends FoxApplication implements androidx.work.Con intent.putExtra("secret", secret); } + public static SharedPreferences getSharedPreferences() { + return INSTANCE.getSharedPreferences("mmm", MODE_PRIVATE); + } + // Is application wrapped, and therefore must reduce it's feature set. @SuppressWarnings("BooleanMethodIsAlwaysInverted") public static boolean isWrapped() { @@ -135,62 +120,58 @@ public class MainApplication extends FoxApplication implements androidx.work.Con return intent != null && intent.getLongExtra("secret", ~secret) == secret; } - public static SharedPreferences getSharedPreferences(String store) { - return FoxApplication.getInitialApplication().getSharedPreferences(store, Context.MODE_PRIVATE); - } - public static boolean isShowcaseMode() { - return getSharedPreferences("mmm").getBoolean("pref_showcase_mode", false); + return getSharedPreferences().getBoolean("pref_showcase_mode", false); } public static boolean shouldPreventReboot() { - return getSharedPreferences("mmm").getBoolean("pref_prevent_reboot", true); + return getSharedPreferences().getBoolean("pref_prevent_reboot", true); } public static boolean isShowIncompatibleModules() { - return getSharedPreferences("mmm").getBoolean("pref_show_incompatible", false); + return getSharedPreferences().getBoolean("pref_show_incompatible", false); } public static boolean isForceDarkTerminal() { - return getSharedPreferences("mmm").getBoolean("pref_force_dark_terminal", false); + return getSharedPreferences().getBoolean("pref_force_dark_terminal", false); } public static boolean isTextWrapEnabled() { - return getSharedPreferences("mmm").getBoolean("pref_wrap_text", false); + return getSharedPreferences().getBoolean("pref_wrap_text", false); } public static boolean isDohEnabled() { - return getSharedPreferences("mmm").getBoolean("pref_dns_over_https", true); + return getSharedPreferences().getBoolean("pref_dns_over_https", true); } public static boolean isMonetEnabled() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && getSharedPreferences("mmm").getBoolean("pref_enable_monet", true); + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && getSharedPreferences().getBoolean("pref_enable_monet", true); } public static boolean isBlurEnabled() { - return getSharedPreferences("mmm").getBoolean("pref_enable_blur", false); + return getSharedPreferences().getBoolean("pref_enable_blur", false); } public static boolean isDeveloper() { if (BuildConfig.DEBUG) return true; - return getSharedPreferences("mmm").getBoolean("developer", false); + return getSharedPreferences().getBoolean("developer", false); } public static boolean isDisableLowQualityModuleFilter() { - return getSharedPreferences("mmm").getBoolean("pref_disable_low_quality_module_filter", false) && isDeveloper(); + return getSharedPreferences().getBoolean("pref_disable_low_quality_module_filter", false) && isDeveloper(); } public static boolean isUsingMagiskCommand() { - return InstallerInitializer.peekMagiskVersion() >= Constants.MAGISK_VER_CODE_INSTALL_COMMAND && getSharedPreferences("mmm").getBoolean("pref_use_magisk_install_command", false) && isDeveloper(); + return InstallerInitializer.peekMagiskVersion() >= Constants.MAGISK_VER_CODE_INSTALL_COMMAND && getSharedPreferences().getBoolean("pref_use_magisk_install_command", false) && isDeveloper(); } public static boolean isBackgroundUpdateCheckEnabled() { - return !wrapped && getSharedPreferences("mmm").getBoolean("pref_background_update_check", true); + return !wrapped && getSharedPreferences().getBoolean("pref_background_update_check", true); } public static boolean isAndroidacyTestMode() { - return isDeveloper() && getSharedPreferences("mmm").getBoolean("pref_androidacy_test_mode", false); + return isDeveloper() && getSharedPreferences().getBoolean("pref_androidacy_test_mode", false); } public static boolean isFirstBoot() { @@ -198,11 +179,11 @@ public class MainApplication extends FoxApplication implements androidx.work.Con } public static void setHasGottenRootAccess(boolean bool) { - getSharedPreferences("mmm").edit().putBoolean("has_root_access", bool).apply(); + getSharedPreferences().edit().putBoolean("has_root_access", bool).apply(); } public static boolean isCrashReportingEnabled() { - return SentryMain.IS_SENTRY_INSTALLED && getSharedPreferences("mmm").getBoolean("pref_crash_reporting", BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING); + return SentryMain.IS_SENTRY_INSTALLED && getSharedPreferences().getBoolean("pref_crash_reporting", BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING); } public static SharedPreferences getBootSharedPreferences() { @@ -243,7 +224,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con @StyleRes int themeResId; String theme; boolean monet = isMonetEnabled(); - switch (theme = getSharedPreferences("mmm").getString("pref_theme", "system")) { + switch (theme = getSharedPreferences().getString("pref_theme", "system")) { default: Timber.w("Unknown theme id: %s", theme); case "system": @@ -289,9 +270,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con (this.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES; case R.style.Theme_MagiskModuleManager_Monet_Light, R.style.Theme_MagiskModuleManager_Light -> true; - case R.style.Theme_MagiskModuleManager_Monet_Dark, R.style.Theme_MagiskModuleManager_Dark -> - false; - case R.style.Theme_MagiskModuleManager_Monet_Black, R.style.Theme_MagiskModuleManager_Black -> + case R.style.Theme_MagiskModuleManager_Monet_Dark, R.style.Theme_MagiskModuleManager_Dark, R.style.Theme_MagiskModuleManager_Monet_Black, R.style.Theme_MagiskModuleManager_Black -> false; default -> super.isLightTheme(); }; @@ -363,9 +342,9 @@ public class MainApplication extends FoxApplication implements androidx.work.Con } catch ( PackageManager.NameNotFoundException ignored) { } - SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm"); + SharedPreferences sharedPreferences = MainApplication.getSharedPreferences(); // We are only one process so it's ok to do this - SharedPreferences bootPrefs = MainApplication.bootSharedPreferences = MainApplication.getSharedPreferences("mmm_boot"); + SharedPreferences bootPrefs = MainApplication.bootSharedPreferences = MainApplication.getINSTANCE().getSharedPreferences("mmm_boot", Context.MODE_PRIVATE); long lastBoot = System.currentTimeMillis() - SystemClock.elapsedRealtime(); long lastBootPrefs = bootPrefs.getLong("last_boot", 0); if (lastBootPrefs == 0 || Math.abs(lastBoot - lastBootPrefs) > 100) { @@ -506,63 +485,6 @@ public class MainApplication extends FoxApplication implements androidx.work.Con } } - // Access the encrypted key in the keystore, decrypt it with the secret, - // and use it to open and read from the realm again - public byte[] getExistingKey() { - Timber.d("Getting existing key..."); - long startTime = System.currentTimeMillis(); - // open a connection to the android keystore - KeyStore keyStore; - try { - keyStore = KeyStore.getInstance("AndroidKeyStore"); - keyStore.load(null); - } catch (KeyStoreException | NoSuchAlgorithmException - | CertificateException | IOException e) { - throw new RuntimeException(e); - } - // access the encrypted key that's stored in shared preferences - byte[] initializationVectorAndEncryptedKey = Base64.decode(getSharedPreferences("realm_key") - .getString("iv_and_encrypted_key", null), Base64.DEFAULT); - ByteBuffer buffer = ByteBuffer.wrap(initializationVectorAndEncryptedKey); - buffer.order(ByteOrder.BIG_ENDIAN); - // extract the length of the initialization vector from the buffer - int initializationVectorLength = buffer.getInt(); - // extract the initialization vector based on that length - byte[] initializationVector = new byte[initializationVectorLength]; - buffer.get(initializationVector); - // extract the encrypted key - byte[] encryptedKey = new byte[initializationVectorAndEncryptedKey.length - - Integer.BYTES - - initializationVectorLength]; - buffer.get(encryptedKey); - // create a cipher that uses AES encryption to decrypt our key - Cipher cipher; - try { - cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES - + "/" + KeyProperties.BLOCK_MODE_CBC - + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7); - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { - throw new RuntimeException(e); - } - // decrypt the encrypted key with the secret key stored in the keystore - byte[] decryptedKey; - try { - final SecretKey secretKey = - (SecretKey) keyStore.getKey("realm_key", null); - final IvParameterSpec initializationVectorSpec = - new IvParameterSpec(initializationVector); - cipher.init(Cipher.DECRYPT_MODE, secretKey, initializationVectorSpec); - decryptedKey = cipher.doFinal(encryptedKey); - } catch (InvalidKeyException | UnrecoverableKeyException | NoSuchAlgorithmException | - BadPaddingException | KeyStoreException | IllegalBlockSizeException | - InvalidAlgorithmParameterException e) { - throw new RuntimeException(e); - } - long endTime = System.currentTimeMillis(); - Timber.d("Got existing key in %d ms", endTime - startTime); - return decryptedKey; // pass to a realm configuration via encryptionKey() - } - private static class ReleaseTree extends Timber.Tree { @Override protected void log(int priority, String tag, @NonNull String message, Throwable t) { diff --git a/app/src/main/java/com/fox2code/mmm/SetupActivity.java b/app/src/main/java/com/fox2code/mmm/SetupActivity.java index fc04611..b6b5278 100644 --- a/app/src/main/java/com/fox2code/mmm/SetupActivity.java +++ b/app/src/main/java/com/fox2code/mmm/SetupActivity.java @@ -3,14 +3,13 @@ package com.fox2code.mmm; import static com.fox2code.mmm.utils.IntentHelper.getActivity; import android.annotation.SuppressLint; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Bundle; -import android.security.keystore.KeyGenParameterSpec; -import android.security.keystore.KeyProperties; import android.util.Base64; import android.view.View; import android.view.WindowManager; @@ -34,26 +33,8 @@ import com.topjohnwu.superuser.internal.UiThreadHandler; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SecureRandom; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; import java.util.Objects; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.KeyGenerator; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; - import io.realm.Realm; import io.realm.RealmConfiguration; import timber.log.Timber; @@ -78,7 +59,7 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { createFiles(); disableUpdateActivityForFdroidFlavor(); // Set theme - SharedPreferences prefs = MainApplication.getSharedPreferences("mmm"); + SharedPreferences prefs = MainApplication.getSharedPreferences(); switch (prefs.getString("theme", "system")) { case "light" -> setTheme(R.style.Theme_MagiskModuleManager_Monet_Light); case "dark" -> setTheme(R.style.Theme_MagiskModuleManager_Monet_Dark); @@ -209,8 +190,12 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { } // Restart the activity MainActivity.doSetupRestarting = true; - Intent intent = new Intent(this, MainActivity.class); - startActivity(intent); + PendingIntent intent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_IMMUTABLE); + try { + intent.send(); + } catch (PendingIntent.CanceledException e) { + e.printStackTrace(); + } finish(); }); // Cancel button @@ -230,7 +215,7 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { public Resources.Theme getTheme() { Resources.Theme theme = super.getTheme(); // Set the theme - SharedPreferences prefs = MainApplication.getSharedPreferences("mmm"); + SharedPreferences prefs = MainApplication.getSharedPreferences(); switch (prefs.getString("pref_theme", "system")) { case "light" -> theme.applyStyle(R.style.Theme_MagiskModuleManager_Monet_Light, true); case "dark" -> theme.applyStyle(R.style.Theme_MagiskModuleManager_Monet_Dark, true); @@ -314,10 +299,16 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { File cookieFile = new File(MainApplication.getINSTANCE().getFilesDir(), cookieFileName); // if the file exists, delete it if (cookieFile.exists()) { - cookieFile.delete(); + if (!cookieFile.delete()) { + Timber.e("Failed to delete cookie file"); + throw new IllegalStateException("Failed to create cookie file. This probably means that the app doesn't have permission to write to the files directory"); + } } // create the file - cookieFile.createNewFile(); + if (!cookieFile.createNewFile()) { + Timber.e("Failed to create cookie file"); + throw new IllegalStateException("Failed to create cookie file. This probably means that the app doesn't have permission to write to the files directory"); + } // create the file output stream FileOutputStream fileOutputStream = new FileOutputStream(cookieFile); // write the initial cookie to the file @@ -357,75 +348,4 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { } } } - - @SuppressLint("NewApi") - public byte[] getNewKey() { - long startTime; - if (MainApplication.getSharedPreferences("mmm").getBoolean("keygen", false)) { - Timber.d("Key already generated, returning"); - return MainApplication.getINSTANCE().getExistingKey(); - } else { - startTime = System.currentTimeMillis(); - Timber.d("Generating new key for realm"); - } - // open a connection to the android keystore - KeyStore keyStore; - try { - keyStore = KeyStore.getInstance("AndroidKeyStore"); - keyStore.load(null); - } catch (java.security.KeyStoreException | NoSuchAlgorithmException | CertificateException | - IOException e) { - throw new RuntimeException(e); - } - // create a securely generated random asymmetric RSA key - byte[] realmKey = new byte[Realm.ENCRYPTION_KEY_LENGTH]; - new SecureRandom().nextBytes(realmKey); - // create a cipher that uses AES encryption -- we'll use this to encrypt our key - Cipher cipher; - try { - cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7); - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { - throw new RuntimeException(e); - } - // generate secret key - KeyGenerator keyGenerator; - try { - keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - throw new RuntimeException(e); - } - KeyGenParameterSpec keySpec = new KeyGenParameterSpec.Builder("realm_key", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT).setBlockModes(KeyProperties.BLOCK_MODE_CBC).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7).setUserAuthenticationRequired(false).build(); - try { - keyGenerator.init(keySpec); - } catch (InvalidAlgorithmParameterException e) { - throw new RuntimeException(e); - } - keyGenerator.generateKey(); - // access the generated key in the android keystore, then - // use the cipher to create an encrypted version of the key - byte[] initializationVector; - byte[] encryptedKeyForRealm; - try { - SecretKey secretKey = (SecretKey) keyStore.getKey("realm_key", null); - cipher.init(Cipher.ENCRYPT_MODE, secretKey); - encryptedKeyForRealm = cipher.doFinal(realmKey); - initializationVector = cipher.getIV(); - } catch (InvalidKeyException | UnrecoverableKeyException | NoSuchAlgorithmException | - KeyStoreException | BadPaddingException | IllegalBlockSizeException e) { - throw new RuntimeException(e); - } - // keep the encrypted key in shared preferences - // to persist it across application runs - byte[] initializationVectorAndEncryptedKey = new byte[Integer.BYTES + initializationVector.length + encryptedKeyForRealm.length]; - ByteBuffer buffer = ByteBuffer.wrap(initializationVectorAndEncryptedKey); - buffer.order(ByteOrder.BIG_ENDIAN); - buffer.putInt(initializationVector.length); - buffer.put(initializationVector); - buffer.put(encryptedKeyForRealm); - MainApplication.getSharedPreferences("realm_key").edit().putString("iv_and_encrypted_key", Base64.encodeToString(initializationVectorAndEncryptedKey, Base64.NO_WRAP)).apply(); - MainApplication.getSharedPreferences("mmm").edit().putBoolean("keygen", true).apply(); - long endTime = System.currentTimeMillis(); - Timber.d("Key generation took %s ms", endTime - startTime); - return realmKey; // pass to a realm configuration via encryptionKey() - } } \ 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 74d40eb..fa6cc27 100644 --- a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java +++ b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java @@ -1,6 +1,7 @@ package com.fox2code.mmm.androidacy; import android.annotation.SuppressLint; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; @@ -43,7 +44,7 @@ import timber.log.Timber; @SuppressWarnings("KotlinInternalInJava") public final class AndroidacyRepoData extends RepoData { - public static String token = MainApplication.getSharedPreferences("androidacy").getString("pref_androidacy_api_token", null); + public static String token = MainApplication.getINSTANCE().getSharedPreferences("androidacy", Context.MODE_PRIVATE).getString("pref_androidacy_api_token", null); static { HttpUrl.Builder OK_HTTP_URL_BUILDER = new HttpUrl.Builder().scheme("https"); @@ -54,7 +55,7 @@ public final class AndroidacyRepoData extends RepoData { @SuppressWarnings("unused") public final String ClientID = BuildConfig.ANDROIDACY_CLIENT_ID; - public final SharedPreferences cachedPreferences = MainApplication.getSharedPreferences("androidacy"); + public final SharedPreferences cachedPreferences = MainApplication.getINSTANCE().getSharedPreferences("androidacy", Context.MODE_PRIVATE); private final boolean testMode; private final String host; public String[][] userInfo = new String[][]{{"role", null}, {"permissions", null}}; @@ -88,7 +89,7 @@ public final class AndroidacyRepoData extends RepoData { // limiting and fraud detection. public static String generateDeviceId() { // Try to get the device ID from the shared preferences - SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("androidacy"); + SharedPreferences sharedPreferences = MainApplication.getINSTANCE().getSharedPreferences("androidacy", Context.MODE_PRIVATE); String deviceIdPref = sharedPreferences.getString("device_id", null); if (deviceIdPref != null) { return deviceIdPref; @@ -181,7 +182,7 @@ public final class AndroidacyRepoData extends RepoData { protected boolean prepare() { // If ANDROIDACY_CLIENT_ID is not set or is empty, disable this repo and return if (Objects.equals(BuildConfig.ANDROIDACY_CLIENT_ID, "")) { - SharedPreferences.Editor editor = MainApplication.getSharedPreferences("mmm").edit(); + SharedPreferences.Editor editor = MainApplication.getSharedPreferences().edit(); editor.putBoolean("pref_androidacy_repo_enabled", false); editor.apply(); return false; @@ -272,7 +273,7 @@ public final class AndroidacyRepoData extends RepoData { return false; } // Save token to shared preference - SharedPreferences.Editor editor = MainApplication.getSharedPreferences("androidacy").edit(); + SharedPreferences.Editor editor = MainApplication.getINSTANCE().getSharedPreferences("androidacy", Context.MODE_PRIVATE).edit(); editor.putString("pref_androidacy_api_token", token); editor.apply(); } catch ( diff --git a/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java b/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java index cf24466..ef34348 100644 --- a/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java +++ b/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java @@ -43,6 +43,7 @@ import java.util.concurrent.TimeUnit; import timber.log.Timber; +@SuppressWarnings("SpellCheckingInspection") public class BackgroundUpdateChecker extends Worker { public static final String NOTIFICATION_CHANNEL_ID = "background_update"; public static final String NOTIFICATION_CHANNEL_ID_APP = "background_update_app"; @@ -59,7 +60,7 @@ public class BackgroundUpdateChecker extends Worker { static void doCheck(Context context) { // first, check if the user has enabled background update checking - if (!MainApplication.getSharedPreferences("mmm").getBoolean("pref_background_update_check", false)) { + if (!MainApplication.getSharedPreferences().getBoolean("pref_background_update_check", false)) { return; } if (MainApplication.getINSTANCE().isInForeground()) { @@ -67,7 +68,7 @@ public class BackgroundUpdateChecker extends Worker { return; } // next, check if user requires wifi - if (MainApplication.getSharedPreferences("mmm").getBoolean("pref_background_update_check_wifi", true)) { + if (MainApplication.getSharedPreferences().getBoolean("pref_background_update_check_wifi", true)) { // check if wifi is connected ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); Network networkInfo = connectivityManager.getActiveNetwork(); @@ -106,7 +107,7 @@ public class BackgroundUpdateChecker extends Worker { continue; // exclude all modules with id's stored in the pref pref_background_update_check_excludes try { - if (MainApplication.getSharedPreferences("mmm").getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id)) + if (MainApplication.getSharedPreferences().getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id)) continue; } catch ( Exception ignored) { @@ -126,7 +127,7 @@ public class BackgroundUpdateChecker extends Worker { } }); // check for app updates - if (MainApplication.getSharedPreferences("mmm").getBoolean("pref_background_update_check_app", false)) { + if (MainApplication.getSharedPreferences().getBoolean("pref_background_update_check_app", false)) { try { boolean shouldUpdate = AppUpdateManager.getAppUpdateManager().checkUpdate(true); if (shouldUpdate) { @@ -208,7 +209,7 @@ public class BackgroundUpdateChecker extends Worker { public static void onMainActivityCreate(Context context) { // Refuse to run if first_launch pref is not false - if (!Objects.equals(MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", null), "v1")) + if (!Objects.equals(MainApplication.getSharedPreferences().getString("last_shown_setup", null), "v1")) return; // create notification channel group if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 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 32d6db4..21a8937 100644 --- a/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java +++ b/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java @@ -55,7 +55,7 @@ public final class ModuleManager extends SyncManager { protected void scanInternal(@NonNull UpdateListener updateListener) { // if last_shown_setup is not "v1", them=n refuse to continue - if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v1")) { + if (!MainApplication.getSharedPreferences().getString("last_shown_setup", "").equals("v1")) { return; } boolean firstScan = this.bootPrefs.getBoolean("mm_first_scan", true); 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 55ff6a9..f8fb66d 100644 --- a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java +++ b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java @@ -148,7 +148,7 @@ public final class RepoManager extends SyncManager { @SuppressWarnings("StatementWithEmptyBody") private void populateDefaultCache(RepoData repoData) { // if last_shown_setup is not "v1", them=n refuse to continue - if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v1")) { + if (!MainApplication.getSharedPreferences().getString("last_shown_setup", "").equals("v1")) { return; } // make sure repodata is not null 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 6c7e171..eb9775b 100644 --- a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java +++ b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java @@ -194,7 +194,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { @SuppressWarnings("ConstantConditions") public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { PreferenceManager preferenceManager = getPreferenceManager(); - preferenceManager.setPreferenceDataStore(EncryptedPreferenceDataStore.getInstance()); + preferenceManager.setSharedPreferencesName("mmm"); setPreferencesFromResource(R.xml.root_preferences, rootKey); applyMaterial3(getPreferenceScreen()); // add bottom navigation bar to the settings @@ -262,10 +262,6 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { ((ListPreference) findPreference("pref_theme")).setValue("system"); // Refresh activity devModeStep = 0; - UiThreadHandler.handler.postDelayed(() -> { - MainApplication.getINSTANCE().updateTheme(); - FoxActivity.getFoxActivity(this).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId()); - }, 1); }).show(); } else { findPreference("pref_enable_monet").setEnabled(true); @@ -273,11 +269,11 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { findPreference("pref_enable_blur").setEnabled(true); findPreference("pref_enable_blur").setSummary(null); devModeStep = 0; - UiThreadHandler.handler.postDelayed(() -> { - MainApplication.getINSTANCE().updateTheme(); - FoxActivity.getFoxActivity(this).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId()); - }, 1); } + UiThreadHandler.handler.postDelayed(() -> { + MainApplication.getINSTANCE().updateTheme(); + FoxActivity.getFoxActivity(this).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId()); + }, 1); return true; }); // Crash reporting @@ -460,7 +456,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { // set the box to unchecked ((SwitchPreferenceCompat) backgroundUpdateCheck).setChecked(false); // ensure that the preference is false - MainApplication.getSharedPreferences("mmm").edit().putBoolean("pref_background_update_check", false).apply(); + MainApplication.getSharedPreferences().edit().putBoolean("pref_background_update_check", false).apply(); new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.permission_notification_title).setMessage(R.string.permission_notification_message).setPositiveButton(R.string.ok, (dialog, which) -> { // Open the app settings Intent intent = new Intent(); @@ -497,7 +493,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { int i = 0; for (LocalModuleInfo localModuleInfo : localModuleInfos) { moduleNames[i] = localModuleInfo.name; - SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm"); + SharedPreferences sharedPreferences = MainApplication.getSharedPreferences(); // get the stringset pref_background_update_check_excludes Set stringSet = sharedPreferences.getStringSet("pref_background_update_check_excludes", new HashSet<>()); // Stringset uses id, we show name @@ -507,7 +503,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { } new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.background_update_check_excludes).setMultiChoiceItems(moduleNames, checkedItems, (dialog, which, isChecked) -> { // get the stringset pref_background_update_check_excludes - SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm"); + SharedPreferences sharedPreferences = MainApplication.getSharedPreferences(); Set stringSet = new HashSet<>(sharedPreferences.getStringSet("pref_background_update_check_excludes", new HashSet<>())); // get id from name String id; @@ -595,11 +591,11 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { if (devModeStep == 2) { devModeStep = 0; if (MainApplication.isDeveloper() && !BuildConfig.DEBUG) { - MainApplication.getSharedPreferences("mmm").edit().putBoolean("developer", false).apply(); + MainApplication.getSharedPreferences().edit().putBoolean("developer", false).apply(); Toast.makeText(getContext(), // Tell the user something changed R.string.dev_mode_disabled, Toast.LENGTH_SHORT).show(); } else { - MainApplication.getSharedPreferences("mmm").edit().putBoolean("developer", true).apply(); + MainApplication.getSharedPreferences().edit().putBoolean("developer", true).apply(); Toast.makeText(getContext(), // Tell the user something changed R.string.dev_mode_enabled, Toast.LENGTH_SHORT).show(); } @@ -811,7 +807,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { // Use MaterialAlertDialogBuilder new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.warning).setCancelable(false).setMessage(R.string.androidacy_test_mode_warning).setPositiveButton(android.R.string.ok, (dialog, which) -> { // User clicked OK button - MainApplication.getSharedPreferences("mmm").edit().putBoolean("androidacy_test_mode", true).apply(); + MainApplication.getSharedPreferences().edit().putBoolean("androidacy_test_mode", true).apply(); // Check the switch Intent mStartActivity = new Intent(requireContext(), MainActivity.class); mStartActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); @@ -829,10 +825,10 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { SwitchPreferenceCompat switchPreferenceCompat = (SwitchPreferenceCompat) androidacyTestMode; switchPreferenceCompat.setChecked(false); // There's probably a better way to do this than duplicate code but I'm too lazy to figure it out - MainApplication.getSharedPreferences("mmm").edit().putBoolean("androidacy_test_mode", false).apply(); + MainApplication.getSharedPreferences().edit().putBoolean("androidacy_test_mode", false).apply(); }).show(); } else { - MainApplication.getSharedPreferences("mmm").edit().putBoolean("androidacy_test_mode", false).apply(); + MainApplication.getSharedPreferences().edit().putBoolean("androidacy_test_mode", false).apply(); // Show dialog to restart app with ok button new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.warning).setCancelable(false).setMessage(R.string.androidacy_test_mode_disable_warning).setNeutralButton(android.R.string.ok, (dialog, which) -> { // User clicked OK button diff --git a/app/src/main/java/com/fox2code/mmm/utils/sentry/SentryMain.java b/app/src/main/java/com/fox2code/mmm/utils/sentry/SentryMain.java index f8afe9c..5a59610 100644 --- a/app/src/main/java/com/fox2code/mmm/utils/sentry/SentryMain.java +++ b/app/src/main/java/com/fox2code/mmm/utils/sentry/SentryMain.java @@ -28,12 +28,12 @@ public class SentryMain { @SuppressLint({"RestrictedApi", "UnspecifiedImmutableFlag"}) public static void initialize(final MainApplication mainApplication) { // If first_launch pref is not false, refuse to initialize Sentry - SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm"); + SharedPreferences sharedPreferences = MainApplication.getSharedPreferences(); if (!Objects.equals(sharedPreferences.getString("last_shown_setup", null), "v1")) { return; } Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { - SharedPreferences.Editor editor = MainApplication.getSharedPreferences("sentry").edit(); + SharedPreferences.Editor editor = MainApplication.getINSTANCE().getSharedPreferences("sentry", Context.MODE_PRIVATE).edit(); editor.putString("lastExitReason", "crash"); editor.putLong("lastExitTime", System.currentTimeMillis()); editor.apply(); diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b2882e2..435418c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,8 +4,9 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root_container" android:layout_width="match_parent" + android:paddingVertical="0dp" android:layout_height="match_parent" - app:fitsSystemWindowsInsets="left|right" + app:fitsSystemWindowsInsets="start|end|bottom|top" tools:context=".MainActivity"> + android:paddingBottom="84dp"> @color/status_bar_color - @color/system_accent2_200 - @color/system_accent2_100 + @color/system_accent2_10 + @color/system_neutral1_10 @style/Widget.Material3.Chip.Choice.Light + + @color/system_accent2_100 + + - + - - diff --git a/build.gradle b/build.gradle index d555aba..755e465 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ buildscript { project.ext.kotlin_version = "1.8.0" project.ext.sentry_version = "6.14.0" dependencies { - classpath 'com.android.tools.build:gradle:7.4.1' + classpath 'com.android.tools.build:gradle:7.4.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10" classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}" classpath 'io.sentry:sentry-android:6.14.0'