如何通过文件路径从MediaStore获取Uri?

7
在我的程序中,我想通过文件路径保存所选铃声,然后稍后将其设置为当前铃声。
我从RingtonePreference获取了铃声uri,并从MediaStore数据库中获取了它的文件路径。
例如:
Uri - content://media/internal/audio/media/29 Path - /system/media/audio/notifications/Ascend.mp3
现在,我该如何从我保存的文件路径中获取铃声Uri?
由于铃声已经存在于MediaStore中,我尝试了以下函数,但它不起作用。 uriRingtone = MediaStore.Audio.Media.getContentUriForPath(szRingtonePath);
这个Uri与我从RingtonePreference得到的不同。 uriRingtone - content://media/internal/audio/media
我该如何查询MediaStore以获取我需要的Uri?
顺便说一下,我不直接存储铃声Uri的原因是我发现在某些设备上,相同铃声的Uri有时会更改。
4个回答

5

据我所知,从RingtonePreference中恢复存储的铃声URI的方法是通过知道歌曲的标题。然后,您可以使用游标查询存储的铃声_id,并使用它构建URI:

String ringtoneTitle = "<The desired ringtone title>";
Uri parcialUri = Uri.parse("content://media/external/audio/media"); // also can be "content://media/internal/audio/media", depends on your needs
Uri finalSuccessfulUri;

RingtoneManager rm = new RingtoneManager(getApplicationContext()); 
Cursor cursor = rm.getCursor();
cursor.moveToFirst();

while(!cursor.isAfterLast()) {
    if(ringtoneTitle.compareToIgnoreCase(cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.TITLE))) == 0) {
    int ringtoneID = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
        finalSuccessfulUri = Uri.withAppendedPath(parcialUri, "" + ringtoneID );
        break;
    }
    cursor.moveToNext();
}

finalSuccessful uri是指向RingtonePreference中铃声的URI。


1
最好使用MediaStore.Audio.Media.EXTERNAL_CONTENT_URIMediaStore.Audio.Media.INTERNAL_CONTENT_URI来访问根URI。 - Rob Rose

5
你也可以以更通用的方式针对MediaStore中的任何内容执行此操作。我需要从URI中获取路径并从路径中获取URI。前者:
/**
 * Gets the corresponding path to a file from the given content:// URI
 * @param selectedVideoUri The content:// URI to find the file path from
 * @param contentResolver The content resolver to use to perform the query.
 * @return the file path as a string
 */
private String getFilePathFromContentUri(Uri selectedVideoUri,
        ContentResolver contentResolver) {
    String filePath;
    String[] filePathColumn = {MediaColumns.DATA};

    Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    filePath = cursor.getString(columnIndex);
    cursor.close();
    return filePath;
}

我通常用这种方法来处理视频,但是也可以通过将MediaStore.Video替换为MediaStore.Audio(等等)来处理音频、文件或其他类型的存储内容:

/**
 * Gets the MediaStore video ID of a given file on external storage
 * @param filePath The path (on external storage) of the file to resolve the ID of
 * @param contentResolver The content resolver to use to perform the query.
 * @return the video ID as a long
 */
private long getVideoIdFromFilePath(String filePath,
        ContentResolver contentResolver) {


    long videoId;
    Log.d(TAG,"Loading file " + filePath);

            // This returns us content://media/external/videos/media (or something like that)
            // I pass in "external" because that's the MediaStore's name for the external
            // storage on my device (the other possibility is "internal")
    Uri videosUri = MediaStore.Video.Media.getContentUri("external");

    Log.d(TAG,"videosUri = " + videosUri.toString());

    String[] projection = {MediaStore.Video.VideoColumns._ID};

    // TODO This will break if we have no matching item in the MediaStore.
    Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(projection[0]);
    videoId = cursor.getLong(columnIndex);

    Log.d(TAG,"Video ID is " + videoId);
    cursor.close();
    return videoId;
}

基本上,MediaStoreDATA列(或者你正在查询的任何子部分)存储了文件路径,所以你可以使用这些信息来查找它。


2
DATA 列已被弃用。 - user924

4
以下代码将返回音频、视频和图像内容Uri的绝对路径。
public static String getRealPathFromURI(Context context, Uri contentUri) {
        Cursor cursor = context.getContentResolver().query(contentUri, null, null, null, null);

        int idx;
        if(contentUri.getPath().startsWith("/external/image") || contentUri.getPath().startsWith("/internal/image")) {
            idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        }
        else if(contentUri.getPath().startsWith("/external/video") || contentUri.getPath().startsWith("/internal/video")) {
            idx = cursor.getColumnIndex(MediaStore.Video.VideoColumns.DATA);
        }
        else if(contentUri.getPath().startsWith("/external/audio") || contentUri.getPath().startsWith("/internal/audio")) {
            idx = cursor.getColumnIndex(MediaStore.Audio.AudioColumns.DATA);
        }
        else{
            return contentUri.getPath();
        }
        if(cursor != null && cursor.moveToFirst()) {
            return cursor.getString(idx);
        }
        return null;
    }

此答案可以通过在try-finally中添加close()方法并在finally块中调用游标来改善。另外,cursor.getColumnIndex()调用可能会抛出NullPointerException异常。 - jk7

1
使用内部URI作为MediaStore.Audio.Media.INTERNAL_CONTENT_URI。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接