From e210a152b823670c49c7721859e2668fc6980325 Mon Sep 17 00:00:00 2001 From: Muntashir Al-Islam Date: Wed, 22 Jul 2020 18:37:56 +0600 Subject: [PATCH] [App] Added changelog, prepare for v2.5.9 --- app/src/main/AndroidManifest.xml | 4 + app/src/main/assets/changelog.html | 83 +++++++++++++++++++ .../AppManager/activities/MainActivity.java | 57 +++++++++++-- .../activities/OneClickOpsActivity.java | 39 +++++++++ .../activities/SettingsActivity.java | 13 +++ .../AppManager/utils/AppPref.java | 1 + .../muntashirakon/AppManager/utils/Utils.java | 32 +++++++ .../res/drawable/ic_outline_plus_one_24.xml | 9 ++ .../res/layout/activity_one_click_ops.xml | 19 +++++ app/src/main/res/layout/activity_settings.xml | 22 +++++ .../main/res/menu/activity_main_actions.xml | 5 ++ app/src/main/res/values/strings.xml | 2 + app/version.properties | 2 +- .../metadata/android/en-US/changelogs/315.txt | 26 ++++++ 14 files changed, 307 insertions(+), 7 deletions(-) create mode 100644 app/src/main/assets/changelog.html create mode 100644 app/src/main/java/io/github/muntashirakon/AppManager/activities/OneClickOpsActivity.java create mode 100644 app/src/main/res/drawable/ic_outline_plus_one_24.xml create mode 100644 app/src/main/res/layout/activity_one_click_ops.xml create mode 100644 fastlane/metadata/android/en-US/changelogs/315.txt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7a3297afc86..4816095aa0a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,6 +18,10 @@ android:largeHeap="true" android:roundIcon="@mipmap/ic_launcher_round" android:theme="@style/AppTheme"> + v2.5.9 (315): +
    +
  •  [Feature] Merged App Info as a single tab in App Details
  • +
  •  [Feature] Added option to reset all app ops
  • +
  •  [Feature] Added option to revoke all dangerous app ops/permissions
  • +
  •  [Feature] Highlight trackers in the component tabs
  • +
  •  [Feature] Added option to save manifest and class dump
  • +
  •  [Feature] Added the ability to grant/revoke development permissions
  • +
  •  [Feature] Added sorting options for components, app ops and uses permissions tabs
  • +
  •  [Feature] Added sort by wifi usage in the App Usage window
  • +
  •  [Feature] Added launch button in the App Info tab
  • +
  •  [Feature] Added never ask option to usage status prompt
  • +
  •  [Feature] Added long click to select apps in the main window
  • +
  •  [Feature] Added changelog within the app
  • +
  •  [Fix] Click to select apps during selection mode
  • +
  •  [Fix] Improved component blocker
  • +
  •  [Fix] Improved manifest loading for large apps
  • +
  •  [Fix] Improved tab loading performance
  • +
  •  [Fix] Fixed app ops checking and custom app ops for some devices
  • +
  •  [Fix] Disabled activity opening for disabled activities
  • +
  •  [Fix] Get real activity name for activities that use activity-alias
  • +
  •  [Fix] Fixed background colors
  • +
  •  [Fix] Fixed crashing when loading the services tab for non-root users
  • +
  •  [Fix] Fixed back button for class viewer which was not working
  • +
  •  [Fix] Changed block icon's colour to accent colour
  • +
  •  [Fix] Removed translation until the app is complete
  • +
  •  [Fix] Made links in the credit section clickable
  • +
  •  [Fix] Fixed various memory leaks
  • +

+ +
v2.5.8 (289):
+
    +
  •  [Feature] Added import/export capabilities for blocking rules
  • +
  •  [Feature] Added ability to select themes (night/day)
  • +
  •  [Feature] Added mode, duration, accept time, reject time for app ops
  • +
  •  [Feature] Highlight running services
  • +
  •  [Feature] Highlight disabled components not disabled within App Manager
  • +
  •  [Feature] Added swipe to refresh in the App Usage window
  • +
  •  [Feature] Added screen time percentage with indicator
  • +
  •  [Feature] Separate instructions and about pages with fullscreen dialog for both
  • +
  •  [Feature] Rounded overflow menu (still incomplete)
  • +
  •  [Fix] Fixed various device/SDK specific app ops issues
  • +
  •  [Fix] Stability improvements of the entire apps
  • +
  •  [Fix] Added ACCESS_NETWORK_STATE permission to support older operating systems
  • +
  •  [Fix] Fixed deleting all IFW rules when selecting apply global rules
  • +
  •  [Fix] Fixed various search issues
  • +

+ +
v2.5.7 (265):
+
    +
  •  [Feature] Initial support for ADB over TCP (port 5555) for non-root users
  • +
  •  [Fix] Fixed importing rules from Watt and Blocker
  • +
  •  [Fix] Display Aurora Droid in App Info window as a first priority over F-Droid
  • +
  •  [Fix] Improved performance for component blocking
  • +
  •  [Fix] Fixed app op mode detection issue
  • +
+

+ For root users: If you've skipped v2.5.6, you may need to apply all rules globally in Settings in order for them to work. +


+ +
v2.5.6 (233):
+
    +
  •  [Feature] Batch operations in the main window: clear app data, disable run in background, disable/kill/uninstall apps (click on the app icon to select)
  • +
  •  [Feature] Full support of Blocker's exported files which was broken due to a bug on Blocker app
  • +
  •  [Feature] Reimplementation of blocking activities, receivers, services and providers
  • +
  •  [Fix] Removed ConstraintLayout dependency therefore a potential decrease in app size
  • +
  •  [Fix] Fixed duplicate app usage warning in the App Info window
  • +
  •  [Fix] Fixed crash when an app icon is not found in App Details window
  • +
+

+ Note for root users: In order to ensure that the previous blocking rules are preserved with the new blocking implementation, this update reads from the previous rules consequently increasing the loading time in the main window. This feature will be removed in the next release but can still be simulated by applying global rules in settings. +


+ +
v2.5.5 (215):
+
    +
  •  [Feature] Added running apps/process viewer (requires root)
  • +
  •  [Feature] Added usage details viewer
  • +
  •  [Feature] Added apk updater and aurora store support
  • +
  •  [Feature] Save modified values of app ops and permissions to the disk (on progress)
  • +
  •  [Fix] Uninstall support for non-root users
  • +
  •  [Fix] Restructure app usage
  • +
  •  [Fix] Added more clarity as well as improve performance in the app details window
  • +
diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/activities/MainActivity.java b/app/src/main/java/io/github/muntashirakon/AppManager/activities/MainActivity.java index 164a867dba7..c1495345e96 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/activities/MainActivity.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/activities/MainActivity.java @@ -17,6 +17,7 @@ import android.os.Bundle; import android.text.Spannable; import android.text.SpannableString; +import android.text.Spanned; import android.text.TextUtils; import android.text.format.Formatter; import android.text.style.RelativeSizeSpan; @@ -68,10 +69,12 @@ import androidx.appcompat.widget.SearchView; import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.core.content.ContextCompat; +import androidx.core.text.HtmlCompat; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import io.github.muntashirakon.AppManager.BuildConfig; import io.github.muntashirakon.AppManager.MainLoader; import io.github.muntashirakon.AppManager.R; import io.github.muntashirakon.AppManager.adb.AdbShell; @@ -214,6 +217,9 @@ protected void onCreate(Bundle savedInstanceState) { recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(mAdapter); + checkFirstRun(); + checkAppUpdate(); + mBatchOpsManager = new BatchOpsManager(this); Menu menu = mBottomAppBar.getMenu(); @@ -396,6 +402,10 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) { Intent usageIntent = new Intent(this, AppUsageActivity.class); startActivity(usageIntent); return true; + case R.id.action_one_click_ops: + Intent onClickOpsIntent = new Intent(this, OneClickOpsActivity.class); + startActivity(onClickOpsIntent); + return true; case R.id.action_apk_updater: try { if(!getPackageManager().getApplicationInfo(PACKAGE_NAME_APK_UPDATER, 0).enabled) @@ -503,6 +513,38 @@ protected void onStart() { } } + private void checkFirstRun() { + if (Utils.isAppInstalled()) { + new MaterialAlertDialogBuilder(this, R.style.AppTheme_AlertDialog) + .setTitle(R.string.instructions) + .setView(R.layout.dialog_instructions) + .setNegativeButton(android.R.string.ok, null) + .show(); + AppPref.getInstance().setPref(AppPref.PrefKey.PREF_LAST_VERSION_CODE_LONG, (long) BuildConfig.VERSION_CODE); + } + } + + private void checkAppUpdate() { + if (Utils.isAppUpdated()) { + new Thread(() -> { + final Spanned spannedChangelog = HtmlCompat.fromHtml(Utils.getContentFromAssets(this, "changelog.html"), HtmlCompat.FROM_HTML_MODE_COMPACT); + runOnUiThread(() -> + new MaterialAlertDialogBuilder(this, R.style.AppTheme_AlertDialog) + .setTitle(R.string.changelog) + .setMessage(spannedChangelog) + .setNegativeButton(android.R.string.ok, null) + .setNeutralButton(R.string.instructions, (dialog, which) -> { + new FullscreenDialog(this) + .setTitle(R.string.instructions) + .setView(R.layout.dialog_instructions) + .show(); + }) + .show()); + }).start(); + AppPref.getInstance().setPref(AppPref.PrefKey.PREF_LAST_VERSION_CODE_LONG, (long) BuildConfig.VERSION_CODE); + } + } + private void handleSelection() { if (mPackageNames.size() == 0) { mBottomAppBar.setVisibility(View.GONE); @@ -657,6 +699,8 @@ static class MainRecyclerAdapter extends RecyclerView.Adapter disabled > regular if (mPackageNames.contains(info.packageName)) holder.mainView.setBackgroundColor(mColorHighlight); - else if (!info.enabled) - holder.mainView.setBackgroundColor(ContextCompat.getColor(mActivity, R.color.disabled_user)); + else if (!info.enabled) holder.mainView.setBackgroundColor(mColorDisabled); else holder.mainView.setBackgroundColor(position % 2 == 0 ? mColorSemiTransparent : mColorTransparent); // Add yellow star if the app is in debug mode holder.favorite_icon.setVisibility(item.star ? View.VISIBLE : View.INVISIBLE); @@ -824,9 +869,9 @@ else if (!info.enabled) // Highlight searched query holder.packageName.setText(Utils.getHighlightedText(info.packageName, mConstraint, mColorRed)); } else holder.packageName.setText(info.packageName); - // Set package name color to blue if the app is in stopped/force closed state + // Set package name color to dark cyan if the app is in stopped/force closed state if ((info.flags & ApplicationInfo.FLAG_STOPPED) != 0) - holder.packageName.setTextColor(ContextCompat.getColor(mActivity, R.color.stopped)); + holder.packageName.setTextColor(mColorStopped); else holder.packageName.setTextColor(mColorSecondary); // Set version (along with HW accelerated, debug and test only flags) CharSequence version = holder.version.getText(); @@ -834,12 +879,12 @@ else if (!info.enabled) if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) version = "debug" + version; if ((info.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0) version = "~" + version; holder.version.setText(version); - // Set version color to green if the app is inactive + // Set version color to dark cyan if the app is inactive if (Build.VERSION.SDK_INT >= 23) { UsageStatsManager mUsageStats; mUsageStats = mActivity.getSystemService(UsageStatsManager.class); if (mUsageStats != null && mUsageStats.isAppInactive(info.packageName)) - holder.version.setTextColor(ContextCompat.getColor(mActivity, R.color.stopped)); + holder.version.setTextColor(mColorStopped); else holder.version.setTextColor(mColorSecondary); } // Set app type: system or user app (along with large heap, suspended, multi-arch, diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/activities/OneClickOpsActivity.java b/app/src/main/java/io/github/muntashirakon/AppManager/activities/OneClickOpsActivity.java new file mode 100644 index 00000000000..c9087873a72 --- /dev/null +++ b/app/src/main/java/io/github/muntashirakon/AppManager/activities/OneClickOpsActivity.java @@ -0,0 +1,39 @@ +package io.github.muntashirakon.AppManager.activities; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import io.github.muntashirakon.AppManager.R; +import io.github.muntashirakon.AppManager.utils.ListItemCreator; + +import android.os.Bundle; +import android.view.MenuItem; + +import com.google.android.material.progressindicator.ProgressIndicator; + +public class OneClickOpsActivity extends AppCompatActivity { + private ListItemCreator mItemCreator; + private ProgressIndicator mProgressIndicator; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_one_click_ops); + setSupportActionBar(findViewById(R.id.toolbar)); + mItemCreator = new ListItemCreator(this, R.id.container); + mProgressIndicator = findViewById(R.id.progress_linear); + setItems(); + } + + private void setItems() { + mItemCreator.addItemWithTitle("Not yet implemented"); + mProgressIndicator.hide(); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/activities/SettingsActivity.java b/app/src/main/java/io/github/muntashirakon/AppManager/activities/SettingsActivity.java index e1a5d0c0838..5b7b1104473 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/activities/SettingsActivity.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/activities/SettingsActivity.java @@ -4,6 +4,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; +import android.text.Spanned; import android.view.MenuItem; import android.view.View; import android.widget.TextView; @@ -18,12 +19,14 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatDelegate; +import androidx.core.text.HtmlCompat; import io.github.muntashirakon.AppManager.BuildConfig; import io.github.muntashirakon.AppManager.R; import io.github.muntashirakon.AppManager.storage.compontents.ComponentsBlocker; import io.github.muntashirakon.AppManager.fragments.ImportExportDialogFragment; import io.github.muntashirakon.AppManager.types.FullscreenDialog; import io.github.muntashirakon.AppManager.utils.AppPref; +import io.github.muntashirakon.AppManager.utils.Utils; public class SettingsActivity extends AppCompatActivity { private static List themeConst = Arrays.asList(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY, AppCompatDelegate.MODE_NIGHT_NO, AppCompatDelegate.MODE_NIGHT_YES); @@ -104,6 +107,16 @@ protected void onCreate(Bundle savedInstanceState) { "%s (%d)", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)); new FullscreenDialog(this).setTitle(R.string.about).setView(view).show(); }); + + findViewById(R.id.changelog_view).setOnClickListener(v -> new Thread(() -> { + final Spanned spannedChangelog = HtmlCompat.fromHtml(Utils.getContentFromAssets(this, "changelog.html"), HtmlCompat.FROM_HTML_MODE_COMPACT); + runOnUiThread(() -> + new MaterialAlertDialogBuilder(this, R.style.AppTheme_AlertDialog) + .setTitle(R.string.changelog) + .setMessage(spannedChangelog) + .setNegativeButton(android.R.string.ok, null) + .show()); + }).start()); } @Override diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/utils/AppPref.java b/app/src/main/java/io/github/muntashirakon/AppManager/utils/AppPref.java index 408e8752c2b..570cd21b756 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/utils/AppPref.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/utils/AppPref.java @@ -21,6 +21,7 @@ public class AppPref { private static final int PREF_SKIP = 5; public enum PrefKey { + // Keep this in sync with getDefaultValue(PrefKey) PREF_ADB_MODE_ENABLED_BOOL, PREF_APP_THEME_INT, PREF_ENABLE_KILL_FOR_SYSTEM_BOOL, diff --git a/app/src/main/java/io/github/muntashirakon/AppManager/utils/Utils.java b/app/src/main/java/io/github/muntashirakon/AppManager/utils/Utils.java index 40508dee15f..07144a70a94 100644 --- a/app/src/main/java/io/github/muntashirakon/AppManager/utils/Utils.java +++ b/app/src/main/java/io/github/muntashirakon/AppManager/utils/Utils.java @@ -31,10 +31,13 @@ import org.xml.sax.InputSource; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -58,6 +61,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import io.github.muntashirakon.AppManager.BuildConfig; import io.github.muntashirakon.AppManager.R; import io.github.muntashirakon.AppManager.runner.RootShellRunner; @@ -192,6 +196,24 @@ public static String getFileContent(@NonNull File file, @NonNull String emptyVal } } + @NonNull + public static String getContentFromAssets(@NonNull Context context, String fileName) { + try { + InputStream inputStream = context.getResources().getAssets().open(fileName); + byte[] buffer = new byte[1024]; + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + for (int length = inputStream.read(buffer); length != -1; length = inputStream.read(buffer)) { + outputStream.write(buffer, 0, length); + } + inputStream.close(); + outputStream.close(); + return new String(outputStream.toByteArray()); + } catch (IOException e) { + e.printStackTrace(); + } + return ""; + } + @NonNull public static String getFileContent(@NonNull ContentResolver contentResolver, @NonNull Uri file) throws FileNotFoundException { @@ -651,4 +673,14 @@ private static boolean isRootAvailable() { } return false; } + + public static boolean isAppUpdated() { + long newVersionCode = BuildConfig.VERSION_CODE; + long oldVersionCode = (long) AppPref.get(AppPref.PrefKey.PREF_LAST_VERSION_CODE_LONG); + return oldVersionCode != 0 && oldVersionCode < newVersionCode; + } + + public static boolean isAppInstalled() { // or data cleared + return (long) AppPref.get(AppPref.PrefKey.PREF_LAST_VERSION_CODE_LONG) == 0; + } } diff --git a/app/src/main/res/drawable/ic_outline_plus_one_24.xml b/app/src/main/res/drawable/ic_outline_plus_one_24.xml new file mode 100644 index 00000000000..cb307d44ae4 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_plus_one_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_one_click_ops.xml b/app/src/main/res/layout/activity_one_click_ops.xml new file mode 100644 index 00000000000..e91deaace72 --- /dev/null +++ b/app/src/main/res/layout/activity_one_click_ops.xml @@ -0,0 +1,19 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index fbe9a2cf130..7959b4c9059 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -231,6 +231,28 @@ android:layout_height="1dp" android:background="@color/ten_percent_black" /> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/activity_main_actions.xml b/app/src/main/res/menu/activity_main_actions.xml index 203b56b6e88..dc7bf9010be 100644 --- a/app/src/main/res/menu/activity_main_actions.xml +++ b/app/src/main/res/menu/activity_main_actions.xml @@ -62,6 +62,11 @@ android:title="@string/refresh" app:showAsAction="never" /> + + Failed to deny all dangerous app ops Launch Never ask + 1-Click Ops + Changelog diff --git a/app/version.properties b/app/version.properties index d47cfbe23e9..a4991a39a9e 100644 --- a/app/version.properties +++ b/app/version.properties @@ -1,2 +1,2 @@ VERSION_NAME=2.5.9 -VERSION_CODE=314 +VERSION_CODE=315 diff --git a/fastlane/metadata/android/en-US/changelogs/315.txt b/fastlane/metadata/android/en-US/changelogs/315.txt new file mode 100644 index 00000000000..a0707372830 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/315.txt @@ -0,0 +1,26 @@ +- [Feature] Merged App Info as a single tab in App Details +- [Feature] Added option to reset all app ops +- [Feature] Added option to revoke all dangerous app ops/permissions +- [Feature] Highlight trackers in the component tabs +- [Feature] Added option to save manifest and class dump +- [Feature] Added the ability to grant/revoke development permissions +- [Feature] Added sorting options for components, app ops and uses permissions tabs +- [Feature] Added sort by wifi usage in the App Usage window +- [Feature] Added launch button in the App Info tab +- [Feature] Added never ask option to usage status prompt +- [Feature] Added long click to select apps in the main window +- [Feature] Added changelog within the app +- [Fix] Click to select apps during selection mode +- [Fix] Improved component blocker +- [Fix] Improved manifest loading for large apps +- [Fix] Improved tab loading performance +- [Fix] Fixed app ops checking and custom app ops for some devices +- [Fix] Disabled activity opening for disabled activities +- [Fix] Get real activity name for activities that use activity-alias +- [Fix] Fixed background colors +- [Fix] Fixed crashing when loading the services tab for non-root users +- [Fix] Fixed back button for class viewer which was not working +- [Fix] Changed block icon's colour to accent colour +- [Fix] Removed translation until the app is complete +- [Fix] Made links in the credit section clickable +- [Fix] Fixed various memory leaks