我有Uri指出的资源(音乐文件).在尝试使用MediaPlayer播放之前,如何检查它是否可用?
它的Uri存储在数据库中,所以当删除文件或卸载的外部存储时,我只是在调用MediaPlayer.prepare()时遇到异常.
在上面的情况我想播放系统默认铃声.在我遇到上述异常后,我当然可以这样做,但也许有一些更优雅的解决方案?
编辑:我忘了提到音乐文件Uri实际上是通过使用RingtonePreference获得的.这意味着我可以让Uri指向内部存储,外部存储或默认系统铃声的铃声.
Uri的例子是:
我对提议的"新文件(路径).exists()方法很满意,因为它将我从提到的异常中保存下来,但过了一段时间后我注意到它为我的所有铃声选择返回false ...还有其他想法吗?
Dee*_*eeV 23
提出的方法不起作用的原因是因为您使用的是ContentProviderURI而不是实际的文件路径.要获取实际文件路径,必须使用游标来获取文件.
假设String contentUri等于内容URI,例如content://media/external/audio/media/192
ContentResolver cr = getContentResolver();
String[] projection = {MediaStore.MediaColumns.DATA}
Cursor cur = cr.query(Uri.parse(contentUri), projection, null, null, null);
if (cur != null) {
if (cur.moveToFirst()) {
String filePath = cur.getString(0);
if (new File(filePath).exists()) {
// do something if it exists
} else {
// File was not found
}
} else {
// Uri was ok but no entry found.
}
cur.close();
} else {
// content Uri was invalid or some other error occurred
}
Run Code Online (Sandbox Code Playgroud)
我没有将此方法用于声音文件或内部存储,但它应该可以工作.查询应该将单行直接返回到您的文件.
尝试使用如下函数:
public static boolean checkURIResource(Context context, Uri uri) {
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
boolean doesExist= (cursor != null && cursor.moveToFirst());
if (cursor != null) {
cursor.close();
}
return doesExist;
}
Run Code Online (Sandbox Code Playgroud)
我也有这个问题 - 我真的想在尝试加载之前检查 Uri 是否可用,因为不必要的失败最终会挤满我的 Crashlytics 日志。
由于StorageAccessFramework(SAF)、DocumentProviders等的到来,处理Uris变得更加复杂。这是我最终使用的:
fun yourFunction() {
val uriToLoad = ...
val validUris = contentResolver.persistedUriPermissions.map { uri }
if (isLoadable(uriToLoad, validUris) != UriLoadable.NO) {
// Attempt to load the uri
}
}
enum class UriLoadable {
YES, NO, MAYBE
}
fun isLoadable(uri: Uri, granted: List<Uri>): UriLoadable {
return when(uri.scheme) {
"content" -> {
if (DocumentsContract.isDocumentUri(this, uri))
if (documentUriExists(uri) && granted.contains(uri))
UriLoadable.YES
else
UriLoadable.NO
else // Content URI is not from a document provider
if (contentUriExists(uri))
UriLoadable.YES
else
UriLoadable.NO
}
"file" -> if (File(uri.path).exists()) UriLoadable.YES else UriLoadable.NO
// http, https, etc. No inexpensive way to test existence.
else -> UriLoadable.MAYBE
}
}
// All DocumentProviders should support the COLUMN_DOCUMENT_ID column
fun documentUriExists(uri: Uri): Boolean =
resolveUri(uri, DocumentsContract.Document.COLUMN_DOCUMENT_ID)
// All ContentProviders should support the BaseColumns._ID column
fun contentUriExists(uri: Uri): Boolean =
resolveUri(uri, BaseColumns._ID)
fun resolveUri(uri: Uri, column: String): Boolean {
val cursor = contentResolver.query(uri,
arrayOf(column), // Empty projections are bad for performance
null,
null,
null)
val result = cursor?.moveToFirst() ?: false
cursor?.close()
return result
}
Run Code Online (Sandbox Code Playgroud)
如果有人有更优雅或正确的替代方案,请发表评论。
对于那些仍在寻找解决方案的人[截至 2020 年 12 月,工作完美]并且在所有边缘情况下都按预期运行,解决方案如下:
boolean bool = false;
if(null != uri) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
inputStream.close();
bool = true;
} catch (Exception e) {
Log.w(MY_TAG, "File corresponding to the uri does not exist " + uri.toString());
}
}
Run Code Online (Sandbox Code Playgroud)
如果与 URI 对应的文件存在,那么您将有一个可以使用的输入流对象,否则将引发异常。
如果文件确实存在,请不要忘记关闭输入流。
笔记:
DocumentFile sourceFile = DocumentFile.fromSingleUri(context, uri);
boolean bool = sourceFile.exists();
Run Code Online (Sandbox Code Playgroud)
上面的 DocumentFile 代码行确实处理了大多数边缘情况,但我发现,如果以编程方式创建文件并将其存储在某个文件夹中,则用户然后访问该文件夹并手动删除该文件(在应用程序运行时) ),DocumentFile.fromSingleUri 错误地表示该文件存在。
| 归档时间: |
|
| 查看次数: |
21231 次 |
| 最近记录: |