Android Q - 删除媒体(音频)文件
Android Q - Delete Media (Audio) File
我一直在尝试让我的应用能够删除音频文件。然而,在尝试了许多可能的解决方案之后,我找不到真正有效的方案。
到目前为止,这是我的解决方案:
public static void deleteFiles(List<Track> tracks, Context context,
final MutableLiveData<IntentSender> deletionIntentSenderLD){
final Uri AUDIO_URI = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
for(Track t : tracks){
try {
context.getContentResolver().delete(ContentUris
.withAppendedId(AUDIO_URI, t.getUriId()), null, null);
}catch (SecurityException securityException) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (securityException instanceof RecoverableSecurityException) {
deletionIntentSenderLD
.postValue(((RecoverableSecurityException) securityException)
.getUserAction().getActionIntent().getIntentSender());
} else
throw securityException;
} else
throw securityException;
}
}
}
当 try 块失败时,将捕获 SecurityException,然后将 IntentSender 传递给在片段中观察到的实时数据:
audioViewModel.getDeletionIntentSenderLD().observe(getViewLifecycleOwner(),
intentSender -> {
try {
startIntentSenderForResult(intentSender, DELETE_PERMISSION_REQUEST,
null, 0 ,0, 0,
null);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
});
我已经尝试实施 onRequestPermissionResult() 方法,但它没有任何作用。我也尝试过使用 File file = new File()
删除文件,但是,由于对 Android 10 所做的更改,我没想到它会起作用。
所以在多次 Google 搜索之后,我得出的结论是,最好的方法(据我所知)是简单地关闭 Android Q (10) 的分区存储。
在这里,我将提供两种解决方案。第一个是我关闭它的那个,第二个是仍然启用范围存储的那个。但是,您应该注意的是,第二种解决方案存在一些问题,有时它实际上会删除实际的媒体文件并更新媒体商店,但大多数时候它只是简单地从媒体商店中删除。显然,这不是一个很好的解决方案,因为在重新启动时您的应用程序会重新加载这些文件,因为媒体商店会扫描它们。
解决方案 1 - 关闭分区存储
对于此解决方案,您仍然可以针对 Android11。您所要做的就是转到模块级别的 build.gradle
文件并设置 compileSdkVersion
和 targetSdkVersion
到 30
.
之后,您进入 AndroidManifest.xml
并像这样设置使用权限和应用程序标签:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29"
tools:ignore="ScopedStorage"/>
<application
android:requestLegacyExternalStorage="true"
...
完成后,您可以使用内容解析器删除媒体文件(并更新媒体商店),您不必担心像 Android 中所说的那样捕获安全异常文档。您对 Android 11 秒删除操作的实施不应受到影响。
解决方案 2 - 打开分区存储
首先,在您的清单中确保 WRITE_EXTERNAL_STORAGE
权限 maxSdkVersion
设置为 28
。还要确保 requestLegacyExternalStorage
设置为 false
(不要认为这是必需的)。然后干脆复制我原来post中的代码。如果您从 activity/fragment 执行删除操作,则不需要实时数据。但是你应该注意 startIntentSenderForResult()
需要一个 activity.
但是正如我之前提到的,我确实遇到了一些错误。不过,此解决方案最令人沮丧的是它不会删除实际文件,而是从媒体商店中删除条目。也许这与@blackapps 提到的事实有关,即您不能批量删除,我可能实施得有点错误。然而,如果在 Android 10.
中无法批量删除,这对用户体验来说是可怕的
我遵循的教程是:
https://developer.android.com/training/data-storage/shared/media#remove-item
https://www.raywenderlich.com/9577211-scoped-storage-in-android-10-getting-started#toc-anchor-007
https://www.solutionanalysts.com/blog/scoped-storage-in-android-10/
旁注 - 在 Android 11
上删除
要在 Android 11 上删除,您只需调用 createDeleteRequest()
即可 return 和 PendingIntent
。从此 PendingIntent
您可以使用 getIntentSender
获得 IntentSender
。将此意图发送者传递给 activity/fragment,然后在您的 activity/fragment 中调用 startIntentSenderForResult()
。这会向用户弹出一个对话框,询问他们应用程序是否可以删除文件。如果用户授予权限,系统会继续删除文件并更新媒体存储。
旁注 - 分区存储,Android 10 和 Future
从我所看到的一切来看,似乎表明范围存储仅在 Android 11 中强制执行,但我不完全确定遗留选项是否仍可用于 Android 10无限期。但我必须对此做更多研究...
我一直在尝试让我的应用能够删除音频文件。然而,在尝试了许多可能的解决方案之后,我找不到真正有效的方案。
到目前为止,这是我的解决方案:
public static void deleteFiles(List<Track> tracks, Context context,
final MutableLiveData<IntentSender> deletionIntentSenderLD){
final Uri AUDIO_URI = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
for(Track t : tracks){
try {
context.getContentResolver().delete(ContentUris
.withAppendedId(AUDIO_URI, t.getUriId()), null, null);
}catch (SecurityException securityException) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (securityException instanceof RecoverableSecurityException) {
deletionIntentSenderLD
.postValue(((RecoverableSecurityException) securityException)
.getUserAction().getActionIntent().getIntentSender());
} else
throw securityException;
} else
throw securityException;
}
}
}
当 try 块失败时,将捕获 SecurityException,然后将 IntentSender 传递给在片段中观察到的实时数据:
audioViewModel.getDeletionIntentSenderLD().observe(getViewLifecycleOwner(),
intentSender -> {
try {
startIntentSenderForResult(intentSender, DELETE_PERMISSION_REQUEST,
null, 0 ,0, 0,
null);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
});
我已经尝试实施 onRequestPermissionResult() 方法,但它没有任何作用。我也尝试过使用 File file = new File()
删除文件,但是,由于对 Android 10 所做的更改,我没想到它会起作用。
所以在多次 Google 搜索之后,我得出的结论是,最好的方法(据我所知)是简单地关闭 Android Q (10) 的分区存储。
在这里,我将提供两种解决方案。第一个是我关闭它的那个,第二个是仍然启用范围存储的那个。但是,您应该注意的是,第二种解决方案存在一些问题,有时它实际上会删除实际的媒体文件并更新媒体商店,但大多数时候它只是简单地从媒体商店中删除。显然,这不是一个很好的解决方案,因为在重新启动时您的应用程序会重新加载这些文件,因为媒体商店会扫描它们。
解决方案 1 - 关闭分区存储
对于此解决方案,您仍然可以针对 Android11。您所要做的就是转到模块级别的 build.gradle
文件并设置 compileSdkVersion
和 targetSdkVersion
到 30
.
之后,您进入 AndroidManifest.xml
并像这样设置使用权限和应用程序标签:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29"
tools:ignore="ScopedStorage"/>
<application
android:requestLegacyExternalStorage="true"
...
完成后,您可以使用内容解析器删除媒体文件(并更新媒体商店),您不必担心像 Android 中所说的那样捕获安全异常文档。您对 Android 11 秒删除操作的实施不应受到影响。
解决方案 2 - 打开分区存储
首先,在您的清单中确保 WRITE_EXTERNAL_STORAGE
权限 maxSdkVersion
设置为 28
。还要确保 requestLegacyExternalStorage
设置为 false
(不要认为这是必需的)。然后干脆复制我原来post中的代码。如果您从 activity/fragment 执行删除操作,则不需要实时数据。但是你应该注意 startIntentSenderForResult()
需要一个 activity.
但是正如我之前提到的,我确实遇到了一些错误。不过,此解决方案最令人沮丧的是它不会删除实际文件,而是从媒体商店中删除条目。也许这与@blackapps 提到的事实有关,即您不能批量删除,我可能实施得有点错误。然而,如果在 Android 10.
中无法批量删除,这对用户体验来说是可怕的我遵循的教程是:
https://developer.android.com/training/data-storage/shared/media#remove-item
https://www.raywenderlich.com/9577211-scoped-storage-in-android-10-getting-started#toc-anchor-007
https://www.solutionanalysts.com/blog/scoped-storage-in-android-10/
旁注 - 在 Android 11
上删除要在 Android 11 上删除,您只需调用 createDeleteRequest()
即可 return 和 PendingIntent
。从此 PendingIntent
您可以使用 getIntentSender
获得 IntentSender
。将此意图发送者传递给 activity/fragment,然后在您的 activity/fragment 中调用 startIntentSenderForResult()
。这会向用户弹出一个对话框,询问他们应用程序是否可以删除文件。如果用户授予权限,系统会继续删除文件并更新媒体存储。
旁注 - 分区存储,Android 10 和 Future
从我所看到的一切来看,似乎表明范围存储仅在 Android 11 中强制执行,但我不完全确定遗留选项是否仍可用于 Android 10无限期。但我必须对此做更多研究...