From 5499ab0b4341da700d5ef24cc54d8daa5553dbbc Mon Sep 17 00:00:00 2001 From: androidacy-user Date: Fri, 13 Jan 2023 16:33:55 -0500 Subject: [PATCH] tweaks Signed-off-by: androidacy-user --- app/build.gradle | 6 - .../com/fox2code/mmm/MainApplication.java | 3 + .../com/fox2code/mmm/NotificationType.java | 8 +- .../com/fox2code/mmm/repo/RepoManager.java | 131 +++++++++--------- .../com/fox2code/mmm/repo/RepoUpdater.java | 6 + .../mmm/settings/SettingsActivity.java | 55 +++++++- .../com/fox2code/mmm/utils/ZipFileOpener.java | 8 ++ .../main/res/drawable/baseline_save_24.xml | 5 + .../main/res/drawable/baseline_upgrade_24.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- app/src/main/res/xml/root_preferences.xml | 15 ++ app/src/main/res/xml/shared_file_paths.xml | 4 +- 12 files changed, 169 insertions(+), 76 deletions(-) create mode 100644 app/src/main/res/drawable/baseline_save_24.xml diff --git a/app/build.gradle b/app/build.gradle index 884b651..808ec7b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -298,12 +298,6 @@ dependencies { // Icons // implementation "com.mikepenz:iconics-core:3.2.5" //implementation "androidx.appcompat:appcompat:${versions.appCompat}" - - // db - def room_version = "2.4.3" - - implementation "androidx.room:room-runtime:$room_version" - kapt "androidx.room:room-compiler:$room_version" } if (hasSentryConfig) { diff --git a/app/src/main/java/com/fox2code/mmm/MainApplication.java b/app/src/main/java/com/fox2code/mmm/MainApplication.java index 14f5a10..cdc9f58 100644 --- a/app/src/main/java/com/fox2code/mmm/MainApplication.java +++ b/app/src/main/java/com/fox2code/mmm/MainApplication.java @@ -13,6 +13,7 @@ import android.os.Build; import android.os.SystemClock; import android.text.SpannableStringBuilder; import android.util.Log; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; @@ -328,6 +329,8 @@ public class MainApplication extends FoxApplication implements androidx.work.Con } if (!isOfficial) { Log.w("MainApplication", "This is not an official build of FoxMMM. This warning can be safely ignored if this is expected, otherwise you may be running an untrusted build."); + // Show a toast to warn the user + Toast.makeText(this, R.string.not_official_build, Toast.LENGTH_LONG).show(); } SharedPreferences sharedPreferences = MainApplication.getSharedPreferences(); // We are only one process so it's ok to do this diff --git a/app/src/main/java/com/fox2code/mmm/NotificationType.java b/app/src/main/java/com/fox2code/mmm/NotificationType.java index ee70241..af042a2 100644 --- a/app/src/main/java/com/fox2code/mmm/NotificationType.java +++ b/app/src/main/java/com/fox2code/mmm/NotificationType.java @@ -12,9 +12,9 @@ import com.fox2code.foxcompat.app.FoxActivity; import com.fox2code.mmm.installer.InstallerInitializer; import com.fox2code.mmm.module.ModuleViewListBuilder; import com.fox2code.mmm.repo.RepoManager; +import com.fox2code.mmm.utils.IntentHelper; import com.fox2code.mmm.utils.io.Files; import com.fox2code.mmm.utils.io.Http; -import com.fox2code.mmm.utils.IntentHelper; import java.io.BufferedReader; import java.io.File; @@ -29,7 +29,7 @@ interface NotificationTypeCst { } public enum NotificationType implements NotificationTypeCst { - DEBUG(R.string.debug_build, R.drawable.ic_baseline_bug_report_24) { + DEBUG(R.string.debug_build, R.drawable.ic_baseline_bug_report_24, R.attr.colorSecondary, R.attr.colorOnSecondary) { @Override public boolean shouldRemove() { return !BuildConfig.DEBUG; @@ -154,7 +154,9 @@ public enum NotificationType implements NotificationTypeCst { public static boolean needPatch(File target) throws IOException { try (ZipFile zipFile = new ZipFile(target)) { - boolean validEntries = zipFile.getEntry("module.prop") == null && zipFile.getEntry("anykernel.sh") == null && zipFile.getEntry("META-INF/com/google/android/magisk/module.prop") == null; + boolean validEntries = zipFile.getEntry("module.prop") != null; + // ensure there's no anykernel.sh + validEntries &= zipFile.getEntry("anykernel.sh") == null; if (validEntries) { // Ensure id of module is not empty and matches ^[a-zA-Z][a-zA-Z0-9._-]+$ regex // We need to get the module.prop and parse the id= line 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 a0540e6..8a0b1c8 100644 --- a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java +++ b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java @@ -19,11 +19,11 @@ import com.fox2code.mmm.XHooks; import com.fox2code.mmm.XRepo; import com.fox2code.mmm.androidacy.AndroidacyRepoData; import com.fox2code.mmm.manager.ModuleInfo; +import com.fox2code.mmm.utils.SyncManager; import com.fox2code.mmm.utils.io.Files; import com.fox2code.mmm.utils.io.Hashes; import com.fox2code.mmm.utils.io.Http; import com.fox2code.mmm.utils.io.PropUtils; -import com.fox2code.mmm.utils.SyncManager; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import java.io.File; @@ -36,25 +36,18 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; + public final class RepoManager extends SyncManager { - public static final String MAGISK_REPO = - "https://raw.githubusercontent.com/Magisk-Modules-Repo/submission/modules/modules.json"; + public static final String MAGISK_REPO = "https://raw.githubusercontent.com/Magisk-Modules-Repo/submission/modules/modules.json"; public static final String MAGISK_REPO_HOMEPAGE = "https://github.com/Magisk-Modules-Repo"; - public static final String MAGISK_ALT_REPO = - "https://raw.githubusercontent.com/Magisk-Modules-Alt-Repo/json/main/modules.json"; - public static final String MAGISK_ALT_REPO_HOMEPAGE = - "https://github.com/Magisk-Modules-Alt-Repo"; - public static final String MAGISK_ALT_REPO_JSDELIVR = - "https://cdn.jsdelivr.net/gh/Magisk-Modules-Alt-Repo/json@main/modules.json"; - public static final String ANDROIDACY_MAGISK_REPO_ENDPOINT = - "https://production-api.androidacy.com/magisk/repo"; - public static final String ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT = - "https://staging-api.androidacy.com/magisk/repo"; - public static final String ANDROIDACY_MAGISK_REPO_HOMEPAGE = - "https://www.androidacy.com/modules-repo"; + public static final String MAGISK_ALT_REPO = "https://raw.githubusercontent.com/Magisk-Modules-Alt-Repo/json/main/modules.json"; + public static final String MAGISK_ALT_REPO_HOMEPAGE = "https://github.com/Magisk-Modules-Alt-Repo"; + public static final String MAGISK_ALT_REPO_JSDELIVR = "https://cdn.jsdelivr.net/gh/Magisk-Modules-Alt-Repo/json@main/modules.json"; + public static final String ANDROIDACY_MAGISK_REPO_ENDPOINT = "https://production-api.androidacy.com/magisk/repo"; + public static final String ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT = "https://staging-api.androidacy.com/magisk/repo"; + public static final String ANDROIDACY_MAGISK_REPO_HOMEPAGE = "https://www.androidacy.com/modules-repo"; private static final String TAG = "RepoManager"; - private static final String MAGISK_REPO_MANAGER = - "https://magisk-modules-repo.github.io/submission/modules.json"; + private static final String MAGISK_REPO_MANAGER = "https://magisk-modules-repo.github.io/submission/modules.json"; private static final Object lock = new Object(); private static final double STEP1 = 0.1D; private static final double STEP2 = 0.8D; @@ -78,18 +71,17 @@ public final class RepoManager extends SyncManager { 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"); + 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"; + altRepo.defaultSubmitModule = "https://github.com/Magisk-Modules-Alt-Repo/submission/issues"; this.customRepoManager = new CustomRepoManager(mainApplication, this); XHooks.onRepoManagerInitialize(); // Populate default cache boolean x = false; for (RepoData repoData : this.repoData.values()) { if (repoData == this.androidacyRepoData) { - if (x) return; + if (x) + return; x = true; } this.populateDefaultCache(repoData); @@ -140,8 +132,7 @@ public final class RepoManager extends SyncManager { case ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT: return "androidacy_repo"; default: - return "repo_" + Hashes.hashSha256( - url.getBytes(StandardCharsets.UTF_8)); + return "repo_" + Hashes.hashSha256(url.getBytes(StandardCharsets.UTF_8)); } } @@ -162,8 +153,7 @@ public final class RepoManager extends SyncManager { */ @SuppressWarnings("BooleanMethodIsAlwaysInverted") public static boolean isAndroidacyRepoEnabled() { - return INSTANCE != null && INSTANCE.androidacyRepoData != null && - INSTANCE.androidacyRepoData.isEnabled(); + return INSTANCE != null && INSTANCE.androidacyRepoData != null && INSTANCE.androidacyRepoData.isEnabled(); } @SuppressWarnings("StatementWithEmptyBody") @@ -187,7 +177,8 @@ public final class RepoManager extends SyncManager { } public RepoData get(String url) { - if (url == null) return null; + if (url == null) + return null; if (MAGISK_ALT_REPO_JSDELIVR.equals(url)) { url = MAGISK_ALT_REPO; } @@ -205,8 +196,7 @@ public final class RepoManager extends SyncManager { synchronized (this.syncLock) { repoData = this.repoData.get(url); if (repoData == null) { - if (ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT.equals(url) || - ANDROIDACY_MAGISK_REPO_ENDPOINT.equals(url)) { + if (ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT.equals(url) || ANDROIDACY_MAGISK_REPO_ENDPOINT.equals(url)) { //noinspection ReplaceNullCheck if (this.androidacyRepoData != null) { return this.androidacyRepoData; @@ -233,23 +223,56 @@ public final class RepoManager extends SyncManager { RepoData[] repoDatas = new LinkedHashSet<>(this.repoData.values()).toArray(new RepoData[0]); RepoUpdater[] repoUpdaters = new RepoUpdater[repoDatas.length]; int moduleToUpdate = 0; + this.hasInternet = false; + // Check if we have internet connection + // Attempt to contact connectivitycheck.gstatic.com/generate_204 + // If we can't, we don't have internet connection + try { + if (BuildConfig.DEBUG) { + Log.d(TAG, "Checking internet connection..."); + } + HttpURLConnection urlConnection = (HttpURLConnection) new URL("https://networkcheck.kde.org").openConnection(); + if (BuildConfig.DEBUG) { + Log.d(TAG, "Opened connection to " + urlConnection.getURL()); + } + urlConnection.setInstanceFollowRedirects(false); + urlConnection.setReadTimeout(1000); + urlConnection.setUseCaches(false); + urlConnection.getInputStream().close(); + // should return a 200 and the content should be "OK" + if (urlConnection.getResponseCode() == 200 && urlConnection.getContentLength() == 3) { + if (BuildConfig.DEBUG) + Log.i("RepoManager", "Internet connection detected"); + this.hasInternet = true; + } else { + if (BuildConfig.DEBUG) + Log.w("RepoManager", "Internet connection not detected"); + } + } catch ( + IOException e) { + Log.e(TAG, "Failed to check internet connection", e); + } for (int i = 0; i < repoDatas.length; i++) { - if (BuildConfig.DEBUG) Log.d("RepoManager", "Fetching: " + repoDatas[i].getName()); + if (BuildConfig.DEBUG) + Log.d("RepoManager", "Preparing to fetch: " + repoDatas[i].getName()); moduleToUpdate += (repoUpdaters[i] = new RepoUpdater(repoDatas[i])).fetchIndex(); updateListener.update(STEP1 / repoDatas.length * (i + 1)); } - if (BuildConfig.DEBUG) Log.d("RepoManag3er", "Updating meta-data"); + if (BuildConfig.DEBUG) + Log.d("RepoManager", "Updating meta-data"); int updatedModules = 0; boolean allowLowQualityModules = MainApplication.isDisableLowQualityModuleFilter(); for (int i = 0; i < repoUpdaters.length; i++) { // Check if the repo is enabled if (!repoUpdaters[i].repoData.isEnabled()) { - if (BuildConfig.DEBUG) Log.d("RepoManager", "Skipping disabled repo: " + repoUpdaters[i].repoData.getName()); + if (BuildConfig.DEBUG) + Log.d("RepoManager", "Skipping disabled repo: " + repoUpdaters[i].repoData.getName()); continue; } List repoModules = repoUpdaters[i].toUpdate(); RepoData repoData = repoDatas[i]; - if (BuildConfig.DEBUG) Log.d("RepoManager", "Registering " + repoData.getName()); + if (BuildConfig.DEBUG) + Log.d("RepoManager", "Registering " + repoData.getName()); for (RepoModule repoModule : repoModules) { try { if (repoModule.propUrl != null && !repoModule.propUrl.isEmpty()) { @@ -269,7 +292,8 @@ public final class RepoManager extends SyncManager { this.modules.put(repoModule.id, repoModule); } } - } catch (Exception e) { + } catch ( + Exception e) { Log.e(TAG, "Failed to get \"" + repoModule.id + "\" metadata", e); } updatedModules++; @@ -290,32 +314,18 @@ public final class RepoManager extends SyncManager { } } } - if (BuildConfig.DEBUG) Log.d("RepoManager", "Finishing update"); - this.hasInternet = false; - // Check if we have internet connection - // Attempt to contact connectivitycheck.gstatic.com/generate_204 - // If we can't, we don't have internet connection - try { - HttpURLConnection urlConnection = (HttpURLConnection) new URL( - "https://connectivitycheck.gstatic.com/generate_204").openConnection(); - urlConnection.setInstanceFollowRedirects(false); - urlConnection.setReadTimeout(1000); - urlConnection.setUseCaches(false); - urlConnection.getInputStream().close(); - if (urlConnection.getResponseCode() == 204 && urlConnection.getContentLength() == 0) { - this.hasInternet = true; - } - } catch (IOException e) { - Log.e(TAG, "Failed to check internet connection", e); - } + if (BuildConfig.DEBUG) + Log.d("RepoManager", "Finishing update"); if (hasInternet) { for (int i = 0; i < repoDatas.length; i++) { // If repo is not enabled, skip if (!repoDatas[i].isEnabled()) { - if (BuildConfig.DEBUG) Log.d("RepoManager", "Skipping " + repoDatas[i].getName() + " because it's disabled"); + if (BuildConfig.DEBUG) + Log.d("RepoManager", "Skipping " + repoDatas[i].getName() + " because it's disabled"); continue; } - if (BuildConfig.DEBUG) Log.d("RepoManager", "Finishing: " + repoUpdaters[i].repoData.getName()); + if (BuildConfig.DEBUG) + Log.d("RepoManager", "Finishing: " + repoUpdaters[i].repoData.getName()); this.repoLastSuccess = repoUpdaters[i].finish(); if (!this.repoLastSuccess) { Log.e(TAG, "Failed to update " + repoUpdaters[i].repoData.getName()); @@ -371,11 +381,8 @@ public final class RepoManager extends SyncManager { private RepoData addRepoData(String url, String fallBackName) { String id = internalIdOfUrl(url); File cacheRoot = new File(this.mainApplication.getCacheDir(), id); - SharedPreferences sharedPreferences = this.mainApplication - .getSharedPreferences("mmm_" + id, Context.MODE_PRIVATE); - RepoData repoData = id.startsWith("repo_") ? - new CustomRepoData(url, cacheRoot, sharedPreferences) : - new RepoData(url, cacheRoot, sharedPreferences); + SharedPreferences sharedPreferences = this.mainApplication.getSharedPreferences("mmm_" + id, Context.MODE_PRIVATE); + RepoData repoData = id.startsWith("repo_") ? new CustomRepoData(url, cacheRoot, sharedPreferences) : new RepoData(url, cacheRoot, sharedPreferences); if (fallBackName != null && !fallBackName.isEmpty()) { repoData.defaultName = fallBackName; if (repoData instanceof CustomRepoData) { @@ -399,10 +406,8 @@ public final class RepoManager extends SyncManager { private AndroidacyRepoData addAndroidacyRepoData() { File cacheRoot = new File(this.mainApplication.getCacheDir(), "androidacy_repo"); - SharedPreferences sharedPreferences = this.mainApplication - .getSharedPreferences("mmm_androidacy_repo", Context.MODE_PRIVATE); - AndroidacyRepoData repoData = new AndroidacyRepoData(cacheRoot, - sharedPreferences, MainApplication.isAndroidacyTestMode()); + SharedPreferences sharedPreferences = this.mainApplication.getSharedPreferences("mmm_androidacy_repo", Context.MODE_PRIVATE); + AndroidacyRepoData repoData = new AndroidacyRepoData(cacheRoot, sharedPreferences, MainApplication.isAndroidacyTestMode()); this.repoData.put(ANDROIDACY_MAGISK_REPO_ENDPOINT, repoData); this.repoData.put(ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT, repoData); return repoData; diff --git a/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java b/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java index 77da514..eb644ce 100644 --- a/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java +++ b/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java @@ -27,6 +27,12 @@ public class RepoUpdater { } public int fetchIndex() { + if (!RepoManager.getINSTANCE().hasConnectivity()) { + this.indexRaw = null; + this.toUpdate = Collections.emptyList(); + this.toApply = Collections.emptySet(); + return 0; + } if (!this.repoData.isEnabled()) { this.indexRaw = null; this.toUpdate = Collections.emptyList(); 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 b03d445..ca0e967 100644 --- a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java +++ b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java @@ -29,6 +29,7 @@ import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; +import androidx.core.content.FileProvider; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; import androidx.preference.EditTextPreference; @@ -58,9 +59,9 @@ import com.fox2code.mmm.repo.CustomRepoManager; import com.fox2code.mmm.repo.RepoData; import com.fox2code.mmm.repo.RepoManager; import com.fox2code.mmm.utils.ExternalHelper; -import com.fox2code.mmm.utils.io.Http; import com.fox2code.mmm.utils.IntentHelper; import com.fox2code.mmm.utils.ProcessHelper; +import com.fox2code.mmm.utils.io.Http; import com.fox2code.mmm.utils.sentry.SentryMain; import com.fox2code.rosettax.LanguageActivity; import com.fox2code.rosettax.LanguageSwitcher; @@ -73,7 +74,11 @@ import com.topjohnwu.superuser.internal.UiThreadHandler; import org.json.JSONException; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.security.NoSuchAlgorithmException; import java.util.Locale; @@ -524,6 +529,54 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { Toast.makeText(requireContext(), toastText, Toast.LENGTH_SHORT).show(); return true; }); + // pref_fox2code_thanks should lead to https://github.com/Fox2Code + linkClickable = findPreference("pref_fox2code_thanks"); + linkClickable.setOnPreferenceClickListener(p -> { + IntentHelper.openUrl(p.getContext(), "https://github.com/Fox2Code"); + return true; + }); + linkClickable.setOnPreferenceLongClickListener(p -> { + String toastText = requireContext().getString(R.string.link_copied); + clipboard.setPrimaryClip(ClipData.newPlainText(toastText, "https://github.com/Fox2Code")); + Toast.makeText(requireContext(), toastText, Toast.LENGTH_SHORT).show(); + return true; + }); + // handle pref_save_logs which saves logs to our external storage and shares them + Preference saveLogs = findPreference("pref_save_logs"); + saveLogs.setOnPreferenceClickListener(p -> { + // Save logs to external storage + File logsFile = new File(requireContext().getExternalFilesDir(null), "logs.txt"); + try { + //noinspection ResultOfMethodCallIgnored + logsFile.createNewFile(); + FileOutputStream fileOutputStream = new FileOutputStream(logsFile); + // first, write some info about the device + fileOutputStream.write(("FoxMagiskModuleManager version: " + BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")\n").getBytes()); + fileOutputStream.write(("Android version: " + Build.VERSION.RELEASE + " (" + Build.VERSION.SDK_INT + ")\n").getBytes()); + fileOutputStream.write(("Device: " + Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")\n").getBytes()); + fileOutputStream.write(("Magisk version: " + InstallerInitializer.peekMagiskVersion() + "\n").getBytes()); + fileOutputStream.write(("Has internet: " + (RepoManager.getINSTANCE().hasConnectivity() ? "Yes" : "No") + "\n").getBytes()); + // read our logcat but format the output to be more readable + Process process = Runtime.getRuntime().exec("logcat -d -v tag"); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = bufferedReader.readLine()) != null) { + fileOutputStream.write((line + "\n").getBytes()); + } + fileOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + Toast.makeText(requireContext(), R.string.error_saving_logs, Toast.LENGTH_SHORT).show(); + return true; + } + // Share logs + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(requireContext(), BuildConfig.APPLICATION_ID + ".file-provider", logsFile)); + shareIntent.setType("text/plain"); + startActivity(Intent.createChooser(shareIntent, getString(R.string.share_logs))); + return true; + }); // pref_contributors should lead to the contributors page linkClickable = findPreference("pref_contributors"); linkClickable.setOnPreferenceClickListener(p -> { diff --git a/app/src/main/java/com/fox2code/mmm/utils/ZipFileOpener.java b/app/src/main/java/com/fox2code/mmm/utils/ZipFileOpener.java index 0e4241e..8448435 100644 --- a/app/src/main/java/com/fox2code/mmm/utils/ZipFileOpener.java +++ b/app/src/main/java/com/fox2code/mmm/utils/ZipFileOpener.java @@ -1,6 +1,7 @@ package com.fox2code.mmm.utils; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.util.Log; import android.widget.Toast; @@ -100,6 +101,13 @@ public class ZipFileOpener extends FoxActivity { zip = new ZipFile(zipFile); if ((entry = zip.getEntry("module.prop")) == null) { Log.e("ZipFileOpener", "onCreate: Zip file is not a valid magisk module"); + if (BuildConfig.DEBUG) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Log.d("ZipFileOpener", "onCreate: Zip file contents: " + zip.stream().map(ZipEntry::getName).reduce((a, b) -> a + ", " + b).orElse("empty")); + } else { + Log.d("ZipFileOpener", "onCreate: Zip file contents cannot be listed on this version of android"); + } + } runOnUiThread(() -> { Toast.makeText(this, R.string.invalid_format, Toast.LENGTH_LONG).show(); finishAndRemoveTask(); diff --git a/app/src/main/res/drawable/baseline_save_24.xml b/app/src/main/res/drawable/baseline_save_24.xml new file mode 100644 index 0000000..83c7ec1 --- /dev/null +++ b/app/src/main/res/drawable/baseline_save_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/baseline_upgrade_24.xml b/app/src/main/res/drawable/baseline_upgrade_24.xml index 8d28802..17fe9b7 100644 --- a/app/src/main/res/drawable/baseline_upgrade_24.xml +++ b/app/src/main/res/drawable/baseline_upgrade_24.xml @@ -1,5 +1,5 @@ + android:tint="?attr/colorControlNormal" android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 143cf7a..7012228 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -283,5 +283,5 @@ Choose theme Choose language Setup Wizard - SettingsThe following repos have failed to update:\\n\\n%sReset API keysUpgrade to premiumUpgrading to premium will remove ads, captchas, and downloads for the Androidacy Repository, and support Androidacy and the module authors. + SettingsThe following repos have failed to update:\\n\\n%sReset API keysUpgrade to premiumUpgrading to premium will remove ads, captchas, and downloads for the Androidacy Repository, and support Androidacy and the module authors.ContributorsFox2Code is the original creator of the app. Without him, this would have never been possible.Created by Fox2CodeSave logs to storage and shareCould not save logsShare FoxMMM logsCaution: You are running an unofficial and unsupported FoxMMM build. diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index c36ee96..5d16dd9 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -154,6 +154,12 @@ app:key="pref_update" app:singleLineTitle="false" app:title="@string/app_update" /> + + + + + + - + + + \ No newline at end of file