From 06391aeb0757d9edfd75b860db9d1d81f04a61da Mon Sep 17 00:00:00 2001 From: Johannes Witzig Date: Thu, 5 Mar 2026 22:43:51 +0100 Subject: [PATCH 1/5] Add preference for directory picker's initial path --- .../audioanchor/activities/DirectoryActivity.java | 8 +++++++- app/src/main/res/values/donttranslate.xml | 2 ++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml-v26/settings.xml | 7 +++++++ app/src/main/res/xml/settings.xml | 6 ++++++ 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/prangesoftwaresolutions/audioanchor/activities/DirectoryActivity.java b/app/src/main/java/com/prangesoftwaresolutions/audioanchor/activities/DirectoryActivity.java index da2f57c..12b3a63 100644 --- a/app/src/main/java/com/prangesoftwaresolutions/audioanchor/activities/DirectoryActivity.java +++ b/app/src/main/java/com/prangesoftwaresolutions/audioanchor/activities/DirectoryActivity.java @@ -19,6 +19,7 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import androidx.preference.PreferenceManager; import com.nambimobile.widgets.efab.FabOption; import com.prangesoftwaresolutions.audioanchor.R; @@ -135,7 +136,12 @@ public void onDestroyActionMode(ActionMode actionMode) { } private void addDirectory(boolean isParentDirectory) { - File baseDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); + String baseDirectoryPref = PreferenceManager.getDefaultSharedPreferences(this).getString( + getString(R.string.settings_directory_picker_initial_path_key), getString(R.string.settings_directory_picker_initial_path_default)); + File baseDirectory = baseDirectoryPref.isBlank() + ? Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + : new File(baseDirectoryPref); + FileDialog fileDialog = new FileDialog(this, baseDirectory, true, null, this); fileDialog.addDirectoryListener(directory -> { Directory.Type directoryType = isParentDirectory ? Directory.Type.PARENT_DIR : Directory.Type.SUB_DIR; diff --git a/app/src/main/res/values/donttranslate.xml b/app/src/main/res/values/donttranslate.xml index 26a380c..a931e5e 100644 --- a/app/src/main/res/values/donttranslate.xml +++ b/app/src/main/res/values/donttranslate.xml @@ -73,6 +73,8 @@ notification_backward_button notification_forward_button %d s + directory_picker_initial_path + album_id diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6c2923a..213bef0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -100,6 +100,7 @@ Notification backward button Notification forward button Skip interval for %s + Initial directory picker path Title diff --git a/app/src/main/res/xml-v26/settings.xml b/app/src/main/res/xml-v26/settings.xml index d53f027..561add7 100644 --- a/app/src/main/res/xml-v26/settings.xml +++ b/app/src/main/res/xml-v26/settings.xml @@ -178,6 +178,13 @@ android:key="@string/settings_keep_deleted_key" android:title="@string/settings_keep_deleted_label" android:singleLineTitle="false" /> + + diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index aa6d92c..d285ddd 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -154,6 +154,12 @@ android:defaultValue="@string/settings_keep_deleted_default" android:key="@string/settings_keep_deleted_key" android:title="@string/settings_keep_deleted_label" /> + + From 2e959d2305e9c564900bc34f3d3a17400d6bed2b Mon Sep 17 00:00:00 2001 From: Johannes Witzig Date: Thu, 5 Mar 2026 21:29:32 +0100 Subject: [PATCH 2/5] Allow to set the initial path from dir picker dialog --- .../activities/DirectoryActivity.java | 7 +++++++ .../audioanchor/dialogs/FileDialog.java | 17 +++++++++++++++++ app/src/main/res/values/strings.xml | 3 ++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/prangesoftwaresolutions/audioanchor/activities/DirectoryActivity.java b/app/src/main/java/com/prangesoftwaresolutions/audioanchor/activities/DirectoryActivity.java index 12b3a63..6b5ba81 100644 --- a/app/src/main/java/com/prangesoftwaresolutions/audioanchor/activities/DirectoryActivity.java +++ b/app/src/main/java/com/prangesoftwaresolutions/audioanchor/activities/DirectoryActivity.java @@ -4,6 +4,7 @@ import android.content.ContentUris; import android.content.CursorLoader; import android.content.Loader; +import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.Environment; @@ -150,6 +151,12 @@ private void addDirectory(boolean isParentDirectory) { mSynchronizer.addDirectory(newDirectory); } }); + fileDialog.addDefaultDirectoryListener(directory -> { + SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit(); + editor.putString(getString(R.string.settings_directory_picker_initial_path_key), directory.getAbsolutePath()); + editor.apply(); + fileDialog.showDialog(); + }); fileDialog.showDialog(); } diff --git a/app/src/main/java/com/prangesoftwaresolutions/audioanchor/dialogs/FileDialog.java b/app/src/main/java/com/prangesoftwaresolutions/audioanchor/dialogs/FileDialog.java index a1ba1ca..5c4e4ad 100644 --- a/app/src/main/java/com/prangesoftwaresolutions/audioanchor/dialogs/FileDialog.java +++ b/app/src/main/java/com/prangesoftwaresolutions/audioanchor/dialogs/FileDialog.java @@ -47,6 +47,7 @@ public interface DirectorySelectedListener { private final ListenerList fileListenerList = new ListenerList<>(); private final ListenerList dirListenerList = new ListenerList<>(); + private final ListenerList defaultDirListenerList = new ListenerList<>(); private final Activity activity; private final boolean mSelectDirectory; private String fileEndsWith; @@ -86,6 +87,10 @@ public View getView(int position, View convertView, @NonNull ViewGroup parent) { Log.d(TAG, currentPath.getPath()); fireDirectorySelectedEvent(currentPath); }); + builder.setNeutralButton(R.string.dialog_msg_set_default_dir, (dialog1, which) -> { + Log.d(TAG, currentPath.getPath()); + fireDefaultDirectorySelectedEvent(currentPath); + }); } builder.setNegativeButton(R.string.dialog_msg_cancel, (dialog1, which) -> { if (dialog1 != null) { @@ -131,6 +136,14 @@ public void removeDirectoryListener(DirectorySelectedListener listener) { dirListenerList.remove(listener); } + public void addDefaultDirectoryListener(DirectorySelectedListener listener) { + defaultDirListenerList.add(listener); + } + + public void removeDefaultDirectoryListener(DirectorySelectedListener listener) { + defaultDirListenerList.remove(listener); + } + /** * Show file dialog */ @@ -146,6 +159,10 @@ private void fireDirectorySelectedEvent(final File directory) { dirListenerList.fireEvent(listener -> listener.directorySelected(directory)); } + private void fireDefaultDirectorySelectedEvent(final File directory) { + defaultDirListenerList.fireEvent(listener -> listener.directorySelected(directory)); + } + private void loadFileList(File path) { this.currentPath = path; List fileList = new ArrayList<>(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 213bef0..7d45f4f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -142,7 +142,8 @@ You can select a single directory that contains audio files or a parent directory that contains several directories containing audio files. - Select directory + Select + Set default Enter the number of minutes for which the player should keep playing OK Cancel From 7229f2eaa8e6e8101e9489b01e20c5058a2a9873 Mon Sep 17 00:00:00 2001 From: Johannes Witzig Date: Thu, 5 Mar 2026 22:43:51 +0100 Subject: [PATCH 3/5] Add preference field to request MANAGE_EXTERNAL_STORAGE --- app/build.gradle.kts | 4 + app/src/main/AndroidManifest.xml | 1 + app/src/main/res/values/donttranslate.xml | 1 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml-v30/settings.xml | 197 ++++++++++++++++++++++ 5 files changed, 205 insertions(+) create mode 100644 app/src/main/res/xml-v30/settings.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 67e8d56..61493a8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,12 +15,16 @@ android { release { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + resValue("string", "app_package_uri", + "package:" + android.defaultConfig.applicationId) } debug { applicationIdSuffix = ".debug" versionNameSuffix = "-DEBUG" isDebuggable = true + resValue("string", "app_package_uri", + "package:" + android.defaultConfig.applicationId + applicationIdSuffix) } } compileOptions { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d141796..8484820 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ android:maxSdkVersion="32" /> + diff --git a/app/src/main/res/values/donttranslate.xml b/app/src/main/res/values/donttranslate.xml index a931e5e..82e25b0 100644 --- a/app/src/main/res/values/donttranslate.xml +++ b/app/src/main/res/values/donttranslate.xml @@ -73,6 +73,7 @@ notification_backward_button notification_forward_button %d s + manage_external_storage directory_picker_initial_path diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7d45f4f..265f8ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -100,8 +100,10 @@ Notification backward button Notification forward button Skip interval for %s + Request \"All files access\" Initial directory picker path + Title Album diff --git a/app/src/main/res/xml-v30/settings.xml b/app/src/main/res/xml-v30/settings.xml new file mode 100644 index 0000000..e386898 --- /dev/null +++ b/app/src/main/res/xml-v30/settings.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b504f417f332ac53543034700a5c73d07528a8de Mon Sep 17 00:00:00 2001 From: Johannes Witzig Date: Thu, 5 Mar 2026 23:30:48 +0100 Subject: [PATCH 4/5] Allow directory picker to find paths in /storage --- .../audioanchor/dialogs/FileDialog.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/prangesoftwaresolutions/audioanchor/dialogs/FileDialog.java b/app/src/main/java/com/prangesoftwaresolutions/audioanchor/dialogs/FileDialog.java index 5c4e4ad..8b92384 100644 --- a/app/src/main/java/com/prangesoftwaresolutions/audioanchor/dialogs/FileDialog.java +++ b/app/src/main/java/com/prangesoftwaresolutions/audioanchor/dialogs/FileDialog.java @@ -4,7 +4,10 @@ import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; +import android.os.Build; import android.os.Environment; +import android.os.storage.StorageManager; +import android.os.storage.StorageVolume; import androidx.annotation.NonNull; import android.util.Log; import android.view.View; @@ -57,9 +60,22 @@ public FileDialog(Activity activity, File initialPath, boolean selectDirectory, this.activity = activity; setFileEndsWith(fileEndsWith); mSelectDirectory = selectDirectory; + mContext = context; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + StorageManager storageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); + for (StorageVolume v: storageManager.getStorageVolumes()) { + File volumePath = v.getDirectory(); + if (volumePath != null && volumePath.canRead()) { + ensureReachabilityOfPath(volumePath); + } + } + } else { + ensureReachabilityOfPath(Environment.getExternalStorageDirectory()); + } + if (!initialPath.exists()) initialPath = Environment.getExternalStorageDirectory(); loadFileList(initialPath); - mContext = context; } /** @@ -217,6 +233,20 @@ private File getChosenFile(String fileChosen) { private void setFileEndsWith(String fileEndsWith) { this.fileEndsWith = fileEndsWith != null ? fileEndsWith.toLowerCase() : null; } + + private void ensureReachabilityOfPath(File path) { + Log.i("FileDialog.java", "Ensure reachability of " + path); + String filename = path.getName(); + File parent = path.getParentFile(); + while (parent != null) { + HashSet childDirs = childDirectories.get(parent.getAbsolutePath()); + if (childDirs == null) childDirs = new HashSet<>(); + childDirs.add(filename); + childDirectories.put(parent.getAbsolutePath(), childDirs); + filename = parent.getName(); + parent = parent.getParentFile(); + } + } } class ListenerList { From 68ea6f0bb5be9c6b059727466b935e51df836840 Mon Sep 17 00:00:00 2001 From: Johannes Witzig Date: Thu, 5 Mar 2026 22:43:51 +0100 Subject: [PATCH 5/5] Update version --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 61493a8..0684340 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -8,8 +8,8 @@ android { applicationId = "com.prangesoftwaresolutions.audioanchor" minSdk = 21 targetSdk = 35 - versionCode = 31 - versionName = "2.4.0" + versionCode = 32 + versionName = "2.5.0" } buildTypes { release {