diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d2bbd995d..7e9edfd35 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -118,6 +118,7 @@
+
{
+ SAFUtil.openTreePicker(this)
+ }
+ SAFUtil.REQUEST_SAF_PICK_TREE -> {
+ if (resultCode == RESULT_OK) {
+ SAFUtil.saveTreeUri(this, intent)
+ }
+ finish()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/github/muntashirakon/music/util/MusicUtil.kt b/app/src/main/java/io/github/muntashirakon/music/util/MusicUtil.kt
index f49427e07..a44baae4c 100644
--- a/app/src/main/java/io/github/muntashirakon/music/util/MusicUtil.kt
+++ b/app/src/main/java/io/github/muntashirakon/music/util/MusicUtil.kt
@@ -477,8 +477,7 @@ object MusicUtil : KoinComponent {
val id: Int = cursor.getInt(0)
val name: String = cursor.getString(1)
try { // File.delete can throw a security exception
- val f = File(name)
- if (f.delete()) {
+ if (SAFUtil.delete(context, name, null)) {
// Step 3: Remove selected track from the database
context.contentResolver.delete(
ContentUris.withAppendedId(
@@ -488,8 +487,6 @@ object MusicUtil : KoinComponent {
)
deletedCount++
} else {
- // I'm not sure if we'd ever get here (deletion would
- // have to fail, but no exception thrown)
Log.e("MusicUtils", "Failed to delete file $name")
}
cursor.moveToNext()
diff --git a/app/src/main/java/io/github/muntashirakon/music/util/SAFUtil.java b/app/src/main/java/io/github/muntashirakon/music/util/SAFUtil.java
index f885e1311..58cfdb6de 100644
--- a/app/src/main/java/io/github/muntashirakon/music/util/SAFUtil.java
+++ b/app/src/main/java/io/github/muntashirakon/music/util/SAFUtil.java
@@ -14,6 +14,7 @@
package io.github.muntashirakon.music.util;
+import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
@@ -30,6 +31,7 @@ import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
import androidx.fragment.app.Fragment;
import io.github.muntashirakon.music.R;
+import io.github.muntashirakon.music.activities.saf.SAFRequestActivity;
import io.github.muntashirakon.music.model.Song;
import java.io.File;
import java.io.FileInputStream;
@@ -50,7 +52,7 @@ public class SAFUtil {
public static final int REQUEST_SAF_PICK_TREE = 43;
public static boolean isSAFRequired(File file) {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && !file.canWrite();
+ return !file.canWrite();
}
public static boolean isSAFRequired(String path) {
@@ -114,21 +116,21 @@ public class SAFUtil {
@TargetApi(Build.VERSION_CODES.KITKAT)
public static void saveTreeUri(Context context, Intent data) {
Uri uri = data.getData();
- context
- .getContentResolver()
- .takePersistableUriPermission(
- uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
- PreferenceUtil.INSTANCE.setSafSdCardUri(uri.toString());
+ if (uri != null) {
+ context.getContentResolver().takePersistableUriPermission(
+ uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ PreferenceUtil.INSTANCE.setSafSdCardUri(uri.toString());
+ }
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public static boolean isTreeUriSaved(Context context) {
+ public static boolean isTreeUriSaved() {
return !TextUtils.isEmpty(PreferenceUtil.INSTANCE.getSafSdCardUri());
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static boolean isSDCardAccessGranted(Context context) {
- if (!isTreeUriSaved(context)) return false;
+ if (!isTreeUriSaved()) return false;
String sdcardUri = PreferenceUtil.INSTANCE.getSafSdCardUri();
@@ -152,6 +154,10 @@ public class SAFUtil {
*/
@Nullable
public static Uri findDocument(DocumentFile dir, List segments) {
+ if (dir == null) {
+ return null;
+ }
+
for (DocumentFile file : dir.listFiles()) {
int index = segments.indexOf(file.getName());
if (index == -1) {
@@ -196,7 +202,7 @@ public class SAFUtil {
return;
}
- if (isTreeUriSaved(context)) {
+ if (isTreeUriSaved()) {
List pathSegments =
new ArrayList<>(Arrays.asList(audio.getFile().getAbsolutePath().split("/")));
Uri sdcard = Uri.parse(PreferenceUtil.INSTANCE.getSafSdCardUri());
@@ -235,6 +241,7 @@ public class SAFUtil {
fos.write(audioContent);
fos.close();
+ //noinspection ResultOfMethodCallIgnored
temp.delete();
} catch (final Exception e) {
Log.e(TAG, "writeSAF: Failed to write to file descriptor provided by SAF", e);
@@ -245,58 +252,57 @@ public class SAFUtil {
}
}
- public static void delete(Context context, String path, Uri safUri) {
+ public static boolean delete(Context context, String path, Uri safUri) {
if (isSAFRequired(path)) {
- deleteSAF(context, path, safUri);
+ return deleteUsingSAF(context, path, safUri);
} else {
try {
- deleteFile(path);
+ return new File(path).delete();
} catch (NullPointerException e) {
Log.e("MusicUtils", "Failed to find file " + path);
} catch (Exception e) {
e.printStackTrace();
}
}
+ return false;
}
- public static void deleteFile(String path) {
- new File(path).delete();
- }
-
+ @SuppressLint("StringFormatInvalid")
@TargetApi(Build.VERSION_CODES.KITKAT)
- public static void deleteSAF(Context context, String path, Uri safUri) {
- Uri uri = null;
-
+ private static boolean deleteUsingSAF(Context context, String path, Uri safUri) {
if (context == null) {
Log.e(TAG, "deleteSAF: context == null");
- return;
+ return false;
}
- if (isTreeUriSaved(context)) {
+ if (safUri == null && isTreeUriSaved()) {
List pathSegments = new ArrayList<>(Arrays.asList(path.split("/")));
Uri sdcard = Uri.parse(PreferenceUtil.INSTANCE.getSafSdCardUri());
- uri = findDocument(DocumentFile.fromTreeUri(context, sdcard), pathSegments);
+ safUri = findDocument(DocumentFile.fromTreeUri(context, sdcard), pathSegments);
}
- if (uri == null) {
- uri = safUri;
- }
-
- if (uri == null) {
- Log.e(TAG, "deleteSAF: Can't get SAF URI");
+ if (safUri == null) {
+ requestSAF(context);
toast(context, context.getString(R.string.saf_error_uri));
- return;
+ return false;
}
try {
- DocumentsContract.deleteDocument(context.getContentResolver(), uri);
+ DocumentsContract.deleteDocument(context.getContentResolver(), safUri);
} catch (final Exception e) {
Log.e(TAG, "deleteSAF: Failed to delete a file descriptor provided by SAF", e);
toast(
context,
String.format(context.getString(R.string.saf_delete_failed), e.getLocalizedMessage()));
+ return false;
}
+ return true;
+ }
+
+ private static void requestSAF(Context context) {
+ Intent intent = new Intent(context, SAFRequestActivity.class);
+ context.startActivity(intent);
}
private static void toast(final Context context, final String message) {