From 8376b1a500aaac7db914f99c7c0e3c37d004d341 Mon Sep 17 00:00:00 2001 From: Sean Maas Date: Fri, 26 Jul 2024 17:34:41 -0400 Subject: [PATCH] Android: update material theme and support dark mode --- src/android/AndroidManifest.xml | 8 ++-- src/android/build.gradle | 7 +-- .../java/com/hydra/noods/FileBrowser.java | 48 ++++++++++++------- .../java/com/hydra/noods/SettingsMenu.java | 3 ++ src/android/play-store.patch | 14 +++--- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/android/AndroidManifest.xml b/src/android/AndroidManifest.xml index 639f4342..715b448e 100644 --- a/src/android/AndroidManifest.xml +++ b/src/android/AndroidManifest.xml @@ -16,7 +16,7 @@ android:requestLegacyExternalStorage="true"> @@ -29,18 +29,18 @@ + android:theme="@style/Theme.Material3.DayNight.NoActionBar"> diff --git a/src/android/build.gradle b/src/android/build.gradle index acba5f72..40efe715 100644 --- a/src/android/build.gradle +++ b/src/android/build.gradle @@ -3,7 +3,7 @@ apply plugin: "com.android.application" android { buildDir = "../../build-android" android.ndkVersion "22.1.7171670" - compileSdkVersion 33 + compileSdkVersion 34 sourceSets { main { @@ -15,8 +15,8 @@ android { defaultConfig { applicationId "com.hydra.noods" - minSdkVersion 16 - targetSdkVersion 33 + minSdkVersion 21 + targetSdkVersion 34 versionCode "git rev-list HEAD --count".execute().text.toInteger() versionName "0.1" } @@ -41,4 +41,5 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.preference:preference:1.1.0' implementation 'androidx.documentfile:documentfile:1.0.1' + implementation 'com.google.android.material:material:1.5.0' } diff --git a/src/android/java/com/hydra/noods/FileBrowser.java b/src/android/java/com/hydra/noods/FileBrowser.java index f3907d66..dffc2d64 100644 --- a/src/android/java/com/hydra/noods/FileBrowser.java +++ b/src/android/java/com/hydra/noods/FileBrowser.java @@ -30,10 +30,16 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Environment; @@ -66,7 +72,8 @@ public class FileBrowser extends AppCompatActivity System.loadLibrary("noods-core"); } - private static final boolean PLAY_STORE = false; + public static final boolean PLAY_STORE = false; + public static PorterDuffColorFilter iconFilter; private ArrayList storagePaths; private ArrayList fileInfo; @@ -85,6 +92,11 @@ protected void onCreate(Bundle savedInstanceState) updateStoragePaths(); super.onCreate(savedInstanceState); + // Set the icon filter based on the current system theme + int uiMode = getResources().getConfiguration().uiMode; + boolean darkMode = (uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; + iconFilter = new PorterDuffColorFilter(darkMode ? Color.WHITE : Color.BLACK, PorterDuff.Mode.SRC_IN); + // Load settings and request storage permissions based on environment if (!loadSettings(getExternalFilesDir(null).getPath()) && PLAY_STORE) showInfo(true); @@ -112,10 +124,11 @@ public boolean onCreateOptionsMenu(Menu menu) // Only show the storage switcher if there are multiple storage paths getMenuInflater().inflate(R.menu.file_menu, menu); if (storagePaths.size() > 1 || scoped) - { - MenuItem item = menu.findItem(R.id.storage_action); - item.setVisible(true); - } + menu.findItem(R.id.storage_action).setVisible(true); + + // Apply the theme filter to all icons + for (int i = 0; i < menu.size(); i++) + menu.getItem(i).getIcon().setColorFilter(iconFilter); return true; } @@ -294,17 +307,9 @@ private void requestPermissions() private void updateStoragePaths() { - // Fall back to the default storage directory pre-Lollipop - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) - { - storagePaths = new ArrayList(); - storagePaths.add(Environment.getExternalStorageDirectory().getAbsolutePath()); - return; - } - // There's no way to directly get root storage paths, but media paths contain them storagePaths = new ArrayList(); - File[] mediaDirs = getExternalMediaDirs(); // Added in Lollipop + File[] mediaDirs = getExternalMediaDirs(); String basePath = Environment.getExternalStorageDirectory().getAbsolutePath(); String mediaPath = ""; @@ -559,7 +564,7 @@ private void processFile(FileAdapter.FileInfo info, boolean directory) // Add a directory with icon to the file list if (directory) { - info.icon = BitmapFactory.decodeResource(getResources(), R.drawable.folder); + info.icon = filterBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.folder)); fileInfo.add(info); return; } @@ -575,11 +580,22 @@ private void processFile(FileAdapter.FileInfo info, boolean directory) } else if (ext.equals(".gba")) { - info.icon = BitmapFactory.decodeResource(getResources(), R.drawable.file); + info.icon = filterBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.file)); fileInfo.add(info); } } + private static Bitmap filterBitmap(Bitmap bitmap) + { + // Redraw a bitmap using the theme filter + Bitmap result = bitmap.copy(bitmap.getConfig(), true); + Paint paint = new Paint(); + paint.setColorFilter(iconFilter); + Canvas canvas = new Canvas(result); + canvas.drawBitmap(result, 0, 0, paint); + return result; + } + private int getRomFd(Uri romUri, boolean override) { try diff --git a/src/android/java/com/hydra/noods/SettingsMenu.java b/src/android/java/com/hydra/noods/SettingsMenu.java index 710536ca..9e92b9a8 100644 --- a/src/android/java/com/hydra/noods/SettingsMenu.java +++ b/src/android/java/com/hydra/noods/SettingsMenu.java @@ -116,7 +116,10 @@ protected void onCreate(Bundle savedInstanceState) @Override public boolean onCreateOptionsMenu(Menu menu) { + // Apply the theme filter to all icons getMenuInflater().inflate(R.menu.settings_menu, menu); + for (int i = 0; i < menu.size(); i++) + menu.getItem(i).getIcon().setColorFilter(FileBrowser.iconFilter); return true; } diff --git a/src/android/play-store.patch b/src/android/play-store.patch index e6483aa0..f5dd5b9a 100644 --- a/src/android/play-store.patch +++ b/src/android/play-store.patch @@ -1,5 +1,5 @@ diff --git a/src/android/AndroidManifest.xml b/src/android/AndroidManifest.xml -index 639f434..3ccced9 100644 +index 715b448..ccce88e 100644 --- a/src/android/AndroidManifest.xml +++ b/src/android/AndroidManifest.xml @@ -6,7 +6,6 @@ @@ -11,20 +11,20 @@ index 639f434..3ccced9 100644 diff --git a/src/android/java/com/hydra/noods/FileBrowser.java b/src/android/java/com/hydra/noods/FileBrowser.java -index 404f5dd..841fa39 100644 +index dffc2d6..455e759 100644 --- a/src/android/java/com/hydra/noods/FileBrowser.java +++ b/src/android/java/com/hydra/noods/FileBrowser.java -@@ -61,7 +61,7 @@ public class FileBrowser extends AppCompatActivity +@@ -72,7 +72,7 @@ public class FileBrowser extends AppCompatActivity System.loadLibrary("noods-core"); } -- private static final boolean PLAY_STORE = false; -+ private static final boolean PLAY_STORE = true; +- public static final boolean PLAY_STORE = false; ++ public static final boolean PLAY_STORE = true; + public static PorterDuffColorFilter iconFilter; private ArrayList storagePaths; - private ArrayList fileInfo; diff --git a/src/android/res/menu/file_menu.xml b/src/android/res/menu/file_menu.xml -index 8a21009..e6d55ce 100644 +index 77595be..f8963b8 100644 --- a/src/android/res/menu/file_menu.xml +++ b/src/android/res/menu/file_menu.xml @@ -5,7 +5,6 @@