(chore) final bugfixes

Signed-off-by: androidacy-user <opensource@androidacy.com>
master
androidacy-user 1 year ago
parent 37c22ee35b
commit 0aa4abca53

@ -37,13 +37,13 @@ android {
applicationId = "com.fox2code.mmm" applicationId = "com.fox2code.mmm"
minSdk = 24 minSdk = 24
targetSdk = 33 targetSdk = 33
versionCode = 65 versionCode = 66
versionName = "2.0.0" versionName = "2.0.0"
vectorDrawables { vectorDrawables {
useSupportLibrary = true useSupportLibrary = true
} }
multiDexEnabled = true multiDexEnabled = true
resourceConfigurations += setOf() resourceConfigurations.addAll(listOf("ar", "bs", "de", "es-rMX", "fr", "hu", "id", "ja", "nl", "pl", "pt", "pt-rBR", "ro", "ru", "tr", "uk", "zh-rCN", "zh-rTW", "en"))
} }
splits { splits {
@ -94,6 +94,7 @@ android {
flavorDimensions.add("type") flavorDimensions.add("type")
productFlavors { productFlavors {
create("default") { create("default") {
dimension = "type"
// debug http requests. do not set this to true if you care about performance!!!!! // debug http requests. do not set this to true if you care about performance!!!!!
buildConfigField("boolean", "DEBUG_HTTP", "false") buildConfigField("boolean", "DEBUG_HTTP", "false")
// Latest commit hash as BuildConfig.COMMIT_HASH // Latest commit hash as BuildConfig.COMMIT_HASH
@ -102,18 +103,18 @@ android {
buildConfigField("String", "BRANCH_NAME", "\"$gitBranch\"") buildConfigField("String", "BRANCH_NAME", "\"$gitBranch\"")
// Get remote url as BuildConfig.REMOTE_URL // Get remote url as BuildConfig.REMOTE_URL
buildConfigField("String", "REMOTE_URL", "\"$gitRemote\"") buildConfigField("String", "REMOTE_URL", "\"$gitRemote\"")
dimension = "type"
buildConfigField("boolean", "ENABLE_AUTO_UPDATER", "true") buildConfigField("boolean", "ENABLE_AUTO_UPDATER", "true")
buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "true") buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "true")
buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING_PII", "true") buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING_PII", "true")
buildConfigField("boolean", "DEFAULT_ENABLE_ANALYTICS", "true") buildConfigField("boolean", "DEFAULT_ENABLE_ANALYTICS", "true")
val properties = Properties() val properties = Properties()
if (project.rootProject.file("local.properties").exists()) { if (project.rootProject.file("local.properties").exists()) {
properties.load(project.rootProject.file("local.properties").reader())
// grab matomo.url // grab matomo.url
buildConfigField( buildConfigField(
"String", "ANALYTICS_ENDPOINT", "\"" + properties.getProperty( "String", "ANALYTICS_ENDPOINT", "\"" + properties.getProperty(
"matomo.url", "https://s-api.androidacy.com/matomo.php" + "\"" "matomo.url", "https://s-api.androidacy.com/matomo.php"
) ) + "\""
) )
} else { } else {
buildConfigField( buildConfigField(
@ -127,7 +128,7 @@ android {
// If androidacy.properties doesn"t exist, use the default client ID which is heavily // If androidacy.properties doesn"t exist, use the default client ID which is heavily
// rate limited to 30 requests per minute // rate limited to 30 requests per minute
if (project.rootProject.file("androidacy.properties").exists()) { if (project.rootProject.file("androidacy.properties").exists()) {
propertiesA.load(project.rootProject.file("androidacy.properties").inputStream()) propertiesA.load(project.rootProject.file("androidacy.properties").reader())
properties.setProperty( properties.setProperty(
"client_id", "\"" + propertiesA.getProperty( "client_id", "\"" + propertiesA.getProperty(
"client_id", "client_id",
@ -153,6 +154,8 @@ android {
// play variant. pretty similiar to default, but with an empty inital online repo list, and use play_client_id instead of client_id // play variant. pretty similiar to default, but with an empty inital online repo list, and use play_client_id instead of client_id
create("play") { create("play") {
dimension = "type"
applicationIdSuffix = ".play"
// debug http requests. do not set this to true if you care about performance!!!!! // debug http requests. do not set this to true if you care about performance!!!!!
buildConfigField("boolean", "DEBUG_HTTP", "false") buildConfigField("boolean", "DEBUG_HTTP", "false")
// Latest commit hash as BuildConfig.COMMIT_HASH // Latest commit hash as BuildConfig.COMMIT_HASH
@ -161,18 +164,18 @@ android {
buildConfigField("String", "BRANCH_NAME", "\"$gitBranch\"") buildConfigField("String", "BRANCH_NAME", "\"$gitBranch\"")
// Get remote url as BuildConfig.REMOTE_URL // Get remote url as BuildConfig.REMOTE_URL
buildConfigField("String", "REMOTE_URL", "\"$gitRemote\"") buildConfigField("String", "REMOTE_URL", "\"$gitRemote\"")
dimension = "type"
buildConfigField("boolean", "ENABLE_AUTO_UPDATER", "false") buildConfigField("boolean", "ENABLE_AUTO_UPDATER", "false")
buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "true") buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "true")
buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING_PII", "true") buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING_PII", "true")
buildConfigField("boolean", "DEFAULT_ENABLE_ANALYTICS", "true") buildConfigField("boolean", "DEFAULT_ENABLE_ANALYTICS", "true")
val properties = Properties() val properties = Properties()
if (project.rootProject.file("local.properties").exists()) { if (project.rootProject.file("local.properties").exists()) {
properties.load(project.rootProject.file("local.properties").reader())
// grab matomo.url // grab matomo.url
buildConfigField( buildConfigField(
"String", "ANALYTICS_ENDPOINT", "\"" + properties.getProperty( "String", "ANALYTICS_ENDPOINT", "\"" + properties.getProperty(
"matomo.url", "https://s-api.androidacy.com/matomo.php" + "\"" "matomo.url", "https://s-api.androidacy.com/matomo.php"
) ) + "\""
) )
} else { } else {
buildConfigField( buildConfigField(
@ -186,7 +189,7 @@ android {
// If androidacy.properties doesn"t exist, use the default client ID which is heavily // If androidacy.properties doesn"t exist, use the default client ID which is heavily
// rate limited to 30 requests per minute // rate limited to 30 requests per minute
if (project.rootProject.file("androidacy.properties").exists()) { if (project.rootProject.file("androidacy.properties").exists()) {
propertiesA.load(project.rootProject.file("androidacy.properties").inputStream()) propertiesA.load(project.rootProject.file("androidacy.properties").reader())
properties.setProperty( properties.setProperty(
"client_id", "\"" + propertiesA.getProperty( "client_id", "\"" + propertiesA.getProperty(
"play_client_id", "play_client_id",
@ -234,6 +237,7 @@ android {
buildConfigField("boolean", "DEFAULT_ENABLE_ANALYTICS", "false") buildConfigField("boolean", "DEFAULT_ENABLE_ANALYTICS", "false")
val properties = Properties() val properties = Properties()
if (project.rootProject.file("local.properties").exists()) { if (project.rootProject.file("local.properties").exists()) {
properties.load(project.rootProject.file("local.properties").reader())
// grab matomo.url // grab matomo.url
buildConfigField( buildConfigField(
"String", "ANALYTICS_ENDPOINT", "\"" + properties.getProperty( "String", "ANALYTICS_ENDPOINT", "\"" + properties.getProperty(
@ -463,8 +467,7 @@ android {
} }
//noinspection GrDeprecatedAPIUsage //noinspection GrDeprecatedAPIUsage
buildToolsVersion = "34.0.0 rc3" buildToolsVersion = "34.0.0 rc3"
@Suppress("DEPRECATION") @Suppress("DEPRECATION") packagingOptions {
packagingOptions {
jniLibs { jniLibs {
useLegacyPackaging = true useLegacyPackaging = true
} }

@ -83,7 +83,6 @@ import io.noties.markwon.image.network.OkHttpNetworkSchemeHandler;
import io.realm.Realm; import io.realm.Realm;
import timber.log.Timber; import timber.log.Timber;
@SuppressWarnings("CommentedOutCode")
public class MainApplication extends FoxApplication implements androidx.work.Configuration.Provider { public class MainApplication extends FoxApplication implements androidx.work.Configuration.Provider {
// Warning! Locales that don't exist will crash the app // Warning! Locales that don't exist will crash the app
// Anything that is commented out is supported but the translation is not complete to at least 60% // Anything that is commented out is supported but the translation is not complete to at least 60%
@ -380,51 +379,12 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
@Override @Override
public void onCreate() { public void onCreate() {
supportedLocales.add("ar"); supportedLocales.addAll(Arrays.asList("ar", "bs", "de", "es-rMX", "fr", "hu", "id", "ja", "nl", "pl", "pt", "pt-rBR", "ro", "ru", "tr", "uk", "zh-rCN", "zh-rTW", "en"));
// supportedLocales.add("ar_SA");
supportedLocales.add("bs");
supportedLocales.add("cs");
supportedLocales.add("de");
// supportedLocales.add("el");
// supportedLocales.add("es");
supportedLocales.add("es-rMX");
// supportedLocales.add("et");
supportedLocales.add("fr");
supportedLocales.add("hu");
// supportedLocales.add("hi");
supportedLocales.add("id");
supportedLocales.add("it");
supportedLocales.add("ja");
// supportedLocales.add("ko");
// supportedLocales.add("nb-rNO");
// supportedLocales.add("ne");
supportedLocales.add("pl");
supportedLocales.add("pt-rBR");
// supportedLocales.add("pt-rPT");
supportedLocales.add("ro");
supportedLocales.add("ru");
supportedLocales.add("sk");
supportedLocales.add("tr");
// supportedLocales.add("th");
supportedLocales.add("uk");
// supportedLocales.add("vi");
supportedLocales.add("zh-rCN");
supportedLocales.add("zh-rTW");
supportedLocales.add("en");
if (INSTANCE == null) INSTANCE = this; if (INSTANCE == null) INSTANCE = this;
relPackageName = this.getPackageName(); relPackageName = this.getPackageName();
super.onCreate(); super.onCreate();
SentryMain.initialize(this); SentryMain.initialize(this);
// Initialize Timber // Initialize Timber
/*if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
} else {
if (isCrashReportingEnabled()) {
Timber.plant(new SentryTimberTree(Sentry.getCurrentHub(), SentryLevel.ERROR, SentryLevel.ERROR));
} else {
Timber.plant(new ReleaseTree());
}
}*/
TimberUtils.configTimber(); TimberUtils.configTimber();
Timber.i("Starting FoxMMM version %s (%d) - commit %s", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, BuildConfig.COMMIT_HASH); Timber.i("Starting FoxMMM version %s (%d) - commit %s", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, BuildConfig.COMMIT_HASH);
// Update SSL Ciphers if update is possible // Update SSL Ciphers if update is possible
@ -500,6 +460,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
Timber.w("Androidacy client id is empty! Please set it in androidacy.properties. Will not enable Androidacy."); Timber.w("Androidacy client id is empty! Please set it in androidacy.properties. Will not enable Androidacy.");
SharedPreferences.Editor editor = sharedPreferences.edit(); SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("pref_androidacy_repo_enabled", false); editor.putBoolean("pref_androidacy_repo_enabled", false);
Timber.w("ANDROIDACY_CLIENT_ID is empty, disabling AndroidacyRepoData 1");
editor.apply(); editor.apply();
} }
} }

@ -190,6 +190,7 @@ public final class AndroidacyRepoData extends RepoData {
SharedPreferences.Editor editor = MainApplication.getPreferences("mmm").edit(); SharedPreferences.Editor editor = MainApplication.getPreferences("mmm").edit();
editor.putBoolean("pref_androidacy_repo_enabled", false); editor.putBoolean("pref_androidacy_repo_enabled", false);
editor.apply(); editor.apply();
Timber.w("ANDROIDACY_CLIENT_ID is empty, disabling AndroidacyRepoData 2");
return false; return false;
} }
if (Http.needCaptchaAndroidacy()) return false; if (Http.needCaptchaAndroidacy()) return false;

@ -1014,7 +1014,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
}); });
// Disable toggling the pref_androidacy_repo_enabled on builds without an // Disable toggling the pref_androidacy_repo_enabled on builds without an
// ANDROIDACY_CLIENT_ID or where the ANDROIDACY_CLIENT_ID is empty // ANDROIDACY_CLIENT_ID or where the ANDROIDACY_CLIENT_ID is empty
Preference androidacyRepoEnabled = Objects.requireNonNull(findPreference("pref_androidacy_repo_enabled")); SwitchPreferenceCompat androidacyRepoEnabled = Objects.requireNonNull(findPreference("pref_androidacy_repo_enabled"));
if (Objects.equals(BuildConfig.ANDROIDACY_CLIENT_ID, "")) { if (Objects.equals(BuildConfig.ANDROIDACY_CLIENT_ID, "")) {
androidacyRepoEnabled.setOnPreferenceClickListener(preference -> { androidacyRepoEnabled.setOnPreferenceClickListener(preference -> {
new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.androidacy_repo_disabled).setCancelable(false).setMessage(R.string.androidacy_repo_disabled_message).setPositiveButton(R.string.download_full_app, (dialog, which) -> { new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.androidacy_repo_disabled).setCancelable(false).setMessage(R.string.androidacy_repo_disabled_message).setPositiveButton(R.string.download_full_app, (dialog, which) -> {
@ -1023,8 +1023,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
startActivity(browserIntent); startActivity(browserIntent);
}).show(); }).show();
// Revert the switch to off // Revert the switch to off
SwitchPreferenceCompat switchPreferenceCompat = (SwitchPreferenceCompat) androidacyRepoEnabled; androidacyRepoEnabled.setChecked(false);
switchPreferenceCompat.setChecked(false);
// Disable in realm db // Disable in realm db
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(MainApplication.getINSTANCE().getKey()).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build(); RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(MainApplication.getINSTANCE().getKey()).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build();
Realm realm = Realm.getInstance(realmConfiguration); Realm realm = Realm.getInstance(realmConfiguration);
@ -1037,165 +1036,173 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
}); });
return false; return false;
}); });
} } else {
// get if androidacy repo is enabled from realm db // get if androidacy repo is enabled from realm db
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(MainApplication.getINSTANCE().getKey()).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build(); RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(MainApplication.getINSTANCE().getKey()).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build();
Realm realm = Realm.getInstance(realmConfiguration); Realm realm = Realm.getInstance(realmConfiguration);
ReposList repoRealmResults = realm.where(ReposList.class).equalTo("id", "androidacy_repo").findFirst(); ReposList repoRealmResults = realm.where(ReposList.class).equalTo("id", "androidacy_repo").findFirst();
if (repoRealmResults == null) { if (repoRealmResults == null) {
// log the entries in the realm db and throw an illegal state exception throw new IllegalStateException("Androidacy repo not found in realm db");
RealmResults<ReposList> reposListRealmResults = realm.where(ReposList.class).findAll();
if (reposListRealmResults.isEmpty()) {
throw new IllegalStateException("Realm db is empty");
}
throw new IllegalStateException("Androidacy repo not found in realm db");
}
boolean androidacyRepoEnabledPref = repoRealmResults.isEnabled();
if (androidacyRepoEnabledPref) {
// get user role from AndroidacyRepoData.userInfo
String[][] userInfo = AndroidacyRepoData.getInstance().userInfo;
if (userInfo != null) {
String userRole = userInfo[0][1];
if (Objects.nonNull(userRole) && !Objects.equals(userRole, "Guest")) {
// Disable the pref_androidacy_repo_api_donate preference
LongClickablePreference prefAndroidacyRepoApiD = Objects.requireNonNull(findPreference("pref_androidacy_repo_donate"));
prefAndroidacyRepoApiD.setEnabled(false);
prefAndroidacyRepoApiD.setSummary(R.string.upgraded_summary);
prefAndroidacyRepoApiD.setTitle(R.string.upgraded);
prefAndroidacyRepoApiD.setIcon(R.drawable.baseline_check_24);
} else if (BuildConfig.FLAVOR.equals("play")) {
// Disable the pref_androidacy_repo_api_token preference and hide the donate button
LongClickablePreference prefAndroidacyRepoApiD = Objects.requireNonNull(findPreference("pref_androidacy_repo_donate"));
prefAndroidacyRepoApiD.setEnabled(false);
prefAndroidacyRepoApiD.setVisible(false);
}
} }
String[] originalApiKeyRef = new String[]{MainApplication.getPreferences("androidacy").getString("pref_androidacy_api_token", "")}; boolean androidacyRepoEnabledPref = repoRealmResults.isEnabled();
// Get the dummy pref_androidacy_repo_api_token preference with id pref_androidacy_repo_api_token // set the switch to the current state
// we have to use the id because the key is different androidacyRepoEnabled.setChecked(androidacyRepoEnabledPref);
EditTextPreference prefAndroidacyRepoApiKey = Objects.requireNonNull(findPreference("pref_androidacy_repo_api_token")); // add a click listener to the switch
// add validation to the EditTextPreference androidacyRepoEnabled.setOnPreferenceClickListener(preference -> {
// string must be 64 characters long, and only allows alphanumeric characters boolean enabled = androidacyRepoEnabled.isChecked();
prefAndroidacyRepoApiKey.setTitle(R.string.api_key); // save the new state
prefAndroidacyRepoApiKey.setSummary(R.string.api_key_summary); realm.executeTransaction(realm2 -> {
prefAndroidacyRepoApiKey.setDialogTitle(R.string.api_key); ReposList repoRealmResults1 = realm2.where(ReposList.class).equalTo("id", "androidacy_repo").findFirst();
prefAndroidacyRepoApiKey.setDefaultValue(originalApiKeyRef[0]); repoRealmResults1.setEnabled(enabled);
// Set the value to the current value });
prefAndroidacyRepoApiKey.setText(originalApiKeyRef[0]); return true;
prefAndroidacyRepoApiKey.setVisible(true);
prefAndroidacyRepoApiKey.setOnBindEditTextListener(editText -> {
editText.setSingleLine();
// Make the single line wrap
editText.setHorizontallyScrolling(false);
// Set the height to the maximum required to fit the text
editText.setMaxLines(Integer.MAX_VALUE);
// Make ok button say "Save"
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
}); });
prefAndroidacyRepoApiKey.setPositiveButtonText(R.string.save_api_key); if (androidacyRepoEnabledPref) {
prefAndroidacyRepoApiKey.setOnPreferenceChangeListener((preference, newValue) -> { // get user role from AndroidacyRepoData.userInfo
// validate the api key client side first. should be 64 characters long, and only allow alphanumeric characters String[][] userInfo = AndroidacyRepoData.getInstance().userInfo;
if (!newValue.toString().matches("[a-zA-Z0-9]{64}")) { if (userInfo != null) {
// Show snack bar with error String userRole = userInfo[0][1];
Snackbar.make(requireView(), R.string.api_key_mismatch, BaseTransientBottomBar.LENGTH_LONG).show(); if (Objects.nonNull(userRole) && !Objects.equals(userRole, "Guest")) {
// Restore the original api key // Disable the pref_androidacy_repo_api_donate preference
prefAndroidacyRepoApiKey.setText(originalApiKeyRef[0]); LongClickablePreference prefAndroidacyRepoApiD = Objects.requireNonNull(findPreference("pref_androidacy_repo_donate"));
prefAndroidacyRepoApiKey.performClick(); prefAndroidacyRepoApiD.setEnabled(false);
return false; prefAndroidacyRepoApiD.setSummary(R.string.upgraded_summary);
prefAndroidacyRepoApiD.setTitle(R.string.upgraded);
prefAndroidacyRepoApiD.setIcon(R.drawable.baseline_check_24);
} else if (BuildConfig.FLAVOR.equals("play")) {
// Disable the pref_androidacy_repo_api_token preference and hide the donate button
LongClickablePreference prefAndroidacyRepoApiD = Objects.requireNonNull(findPreference("pref_androidacy_repo_donate"));
prefAndroidacyRepoApiD.setEnabled(false);
prefAndroidacyRepoApiD.setVisible(false);
}
} }
// Make sure originalApiKeyRef is not null String[] originalApiKeyRef = new String[]{MainApplication.getPreferences("androidacy").getString("pref_androidacy_api_token", "")};
if (originalApiKeyRef[0].equals(newValue)) return true; // Get the dummy pref_androidacy_repo_api_token preference with id pref_androidacy_repo_api_token
// get original api key // we have to use the id because the key is different
String apiKey = String.valueOf(newValue); EditTextPreference prefAndroidacyRepoApiKey = Objects.requireNonNull(findPreference("pref_androidacy_repo_api_token"));
// Show snack bar with indeterminate progress // add validation to the EditTextPreference
Snackbar.make(requireView(), R.string.checking_api_key, BaseTransientBottomBar.LENGTH_INDEFINITE).setAction(R.string.cancel, v -> { // string must be 64 characters long, and only allows alphanumeric characters
// Restore the original api key prefAndroidacyRepoApiKey.setTitle(R.string.api_key);
prefAndroidacyRepoApiKey.setText(originalApiKeyRef[0]); prefAndroidacyRepoApiKey.setSummary(R.string.api_key_summary);
}).show(); prefAndroidacyRepoApiKey.setDialogTitle(R.string.api_key);
// Check the API key on a background thread prefAndroidacyRepoApiKey.setDefaultValue(originalApiKeyRef[0]);
new Thread(() -> { // Set the value to the current value
// If key is empty, just remove it and change the text of the snack bar prefAndroidacyRepoApiKey.setText(originalApiKeyRef[0]);
if (apiKey.isEmpty()) { prefAndroidacyRepoApiKey.setVisible(true);
MainApplication.getPreferences("androidacy").edit().remove("pref_androidacy_api_token").apply(); prefAndroidacyRepoApiKey.setOnBindEditTextListener(editText -> {
new Handler(Looper.getMainLooper()).post(() -> { editText.setSingleLine();
Snackbar.make(requireView(), R.string.api_key_removed, BaseTransientBottomBar.LENGTH_SHORT).show(); // Make the single line wrap
// Show dialog to restart app with ok button editText.setHorizontallyScrolling(false);
new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.restart).setCancelable(false).setMessage(R.string.api_key_restart).setNeutralButton(android.R.string.ok, (dialog, which) -> { // Set the height to the maximum required to fit the text
// User clicked OK button editText.setMaxLines(Integer.MAX_VALUE);
Intent mStartActivity = new Intent(requireContext(), MainActivity.class); // Make ok button say "Save"
mStartActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
int mPendingIntentId = 123456; });
// If < 23, FLAG_IMMUTABLE is not available prefAndroidacyRepoApiKey.setPositiveButtonText(R.string.save_api_key);
PendingIntent mPendingIntent; prefAndroidacyRepoApiKey.setOnPreferenceChangeListener((preference, newValue) -> {
mPendingIntent = PendingIntent.getActivity(requireContext(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); // validate the api key client side first. should be 64 characters long, and only allow alphanumeric characters
AlarmManager mgr = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE); if (!newValue.toString().matches("[a-zA-Z0-9]{64}")) {
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent); // Show snack bar with error
Timber.d("Restarting app to save token preference: %s", newValue); Snackbar.make(requireView(), R.string.api_key_mismatch, BaseTransientBottomBar.LENGTH_LONG).show();
System.exit(0); // Exit app process // Restore the original api key
}).show(); prefAndroidacyRepoApiKey.setText(originalApiKeyRef[0]);
}); prefAndroidacyRepoApiKey.performClick();
} else { return false;
// If key < 64 chars, it's not valid }
if (apiKey.length() < 64) { // Make sure originalApiKeyRef is not null
if (originalApiKeyRef[0].equals(newValue)) return true;
// get original api key
String apiKey = String.valueOf(newValue);
// Show snack bar with indeterminate progress
Snackbar.make(requireView(), R.string.checking_api_key, BaseTransientBottomBar.LENGTH_INDEFINITE).setAction(R.string.cancel, v -> {
// Restore the original api key
prefAndroidacyRepoApiKey.setText(originalApiKeyRef[0]);
}).show();
// Check the API key on a background thread
new Thread(() -> {
// If key is empty, just remove it and change the text of the snack bar
if (apiKey.isEmpty()) {
MainApplication.getPreferences("androidacy").edit().remove("pref_androidacy_api_token").apply();
new Handler(Looper.getMainLooper()).post(() -> { new Handler(Looper.getMainLooper()).post(() -> {
Snackbar.make(requireView(), R.string.api_key_invalid, BaseTransientBottomBar.LENGTH_SHORT).show(); Snackbar.make(requireView(), R.string.api_key_removed, BaseTransientBottomBar.LENGTH_SHORT).show();
// Save the original key // Show dialog to restart app with ok button
MainApplication.getPreferences("androidacy").edit().putString("pref_androidacy_api_token", originalApiKeyRef[0]).apply(); new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.restart).setCancelable(false).setMessage(R.string.api_key_restart).setNeutralButton(android.R.string.ok, (dialog, which) -> {
// Re-show the dialog with an error // User clicked OK button
prefAndroidacyRepoApiKey.performClick(); Intent mStartActivity = new Intent(requireContext(), MainActivity.class);
// Show error mStartActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
prefAndroidacyRepoApiKey.setDialogMessage(getString(R.string.api_key_invalid)); int mPendingIntentId = 123456;
// If < 23, FLAG_IMMUTABLE is not available
PendingIntent mPendingIntent;
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);
Timber.d("Restarting app to save token preference: %s", newValue);
System.exit(0); // Exit app process
}).show();
}); });
} else { } else {
// If the key is the same as the original, just show a snack bar // If key < 64 chars, it's not valid
if (apiKey.equals(originalApiKeyRef[0])) { if (apiKey.length() < 64) {
new Handler(Looper.getMainLooper()).post(() -> Snackbar.make(requireView(), R.string.api_key_unchanged, BaseTransientBottomBar.LENGTH_SHORT).show());
return;
}
boolean valid = false;
try {
valid = AndroidacyRepoData.getInstance().isValidToken(apiKey);
} catch (IOException ignored) {
}
// If the key is valid, save it
if (valid) {
originalApiKeyRef[0] = apiKey;
RepoManager.getINSTANCE().getAndroidacyRepoData().setToken(apiKey);
MainApplication.getPreferences("androidacy").edit().putString("pref_androidacy_api_token", apiKey).apply();
// Snackbar with success and restart button
new Handler(Looper.getMainLooper()).post(() -> {
Snackbar.make(requireView(), R.string.api_key_valid, BaseTransientBottomBar.LENGTH_SHORT).show();
// Show dialog to restart app with ok button
new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.restart).setCancelable(false).setMessage(R.string.api_key_restart).setNeutralButton(android.R.string.ok, (dialog, which) -> {
// User clicked OK button
Intent mStartActivity = new Intent(requireContext(), MainActivity.class);
mStartActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
int mPendingIntentId = 123456;
// If < 23, FLAG_IMMUTABLE is not available
PendingIntent mPendingIntent;
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);
Timber.d("Restarting app to save token preference: %s", newValue);
System.exit(0); // Exit app process
}).show();
});
} else {
new Handler(Looper.getMainLooper()).post(() -> { new Handler(Looper.getMainLooper()).post(() -> {
Snackbar.make(requireView(), R.string.api_key_invalid, BaseTransientBottomBar.LENGTH_SHORT).show(); Snackbar.make(requireView(), R.string.api_key_invalid, BaseTransientBottomBar.LENGTH_SHORT).show();
// Save the original key // Save the original key
MainApplication.getINSTANCE().getSharedPreferences("androidacy", 0).edit().putString("pref_androidacy_api_token", originalApiKeyRef[0]).apply(); MainApplication.getPreferences("androidacy").edit().putString("pref_androidacy_api_token", originalApiKeyRef[0]).apply();
// Re-show the dialog with an error // Re-show the dialog with an error
prefAndroidacyRepoApiKey.performClick(); prefAndroidacyRepoApiKey.performClick();
// Show error // Show error
prefAndroidacyRepoApiKey.setDialogMessage(getString(R.string.api_key_invalid)); prefAndroidacyRepoApiKey.setDialogMessage(getString(R.string.api_key_invalid));
}); });
} else {
// If the key is the same as the original, just show a snack bar
if (apiKey.equals(originalApiKeyRef[0])) {
new Handler(Looper.getMainLooper()).post(() -> Snackbar.make(requireView(), R.string.api_key_unchanged, BaseTransientBottomBar.LENGTH_SHORT).show());
return;
}
boolean valid = false;
try {
valid = AndroidacyRepoData.getInstance().isValidToken(apiKey);
} catch (IOException ignored) {
}
// If the key is valid, save it
if (valid) {
originalApiKeyRef[0] = apiKey;
RepoManager.getINSTANCE().getAndroidacyRepoData().setToken(apiKey);
MainApplication.getPreferences("androidacy").edit().putString("pref_androidacy_api_token", apiKey).apply();
// Snackbar with success and restart button
new Handler(Looper.getMainLooper()).post(() -> {
Snackbar.make(requireView(), R.string.api_key_valid, BaseTransientBottomBar.LENGTH_SHORT).show();
// Show dialog to restart app with ok button
new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.restart).setCancelable(false).setMessage(R.string.api_key_restart).setNeutralButton(android.R.string.ok, (dialog, which) -> {
// User clicked OK button
Intent mStartActivity = new Intent(requireContext(), MainActivity.class);
mStartActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
int mPendingIntentId = 123456;
// If < 23, FLAG_IMMUTABLE is not available
PendingIntent mPendingIntent;
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);
Timber.d("Restarting app to save token preference: %s", newValue);
System.exit(0); // Exit app process
}).show();
});
} else {
new Handler(Looper.getMainLooper()).post(() -> {
Snackbar.make(requireView(), R.string.api_key_invalid, BaseTransientBottomBar.LENGTH_SHORT).show();
// Save the original key
MainApplication.getINSTANCE().getSharedPreferences("androidacy", 0).edit().putString("pref_androidacy_api_token", originalApiKeyRef[0]).apply();
// Re-show the dialog with an error
prefAndroidacyRepoApiKey.performClick();
// Show error
prefAndroidacyRepoApiKey.setDialogMessage(getString(R.string.api_key_invalid));
});
}
} }
} }
} }).start();
}).start(); return true;
return true; });
}); }
} }
} }

Loading…
Cancel
Save