使用MediaStore列出所有带有路径的音乐。

32

好的,我已经在这个项目上工作了几天,大部分时间都在研究如何以列表视图或其他方式列出设备上的所有音乐,我已经搜索了几天,这让我感到很沮丧。曾经有一次我几乎把所有音乐都放到一个文件夹里了,但是由于大多数人会为艺术家和专辑等事物创建子文件夹,所以我需要一种方法来搜索子文件夹中的MP3或音乐文件。

这是我目前拥有的音乐收藏:

package com.androidhive.musicplayer;

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;

import android.provider.MediaStore;

public class SongsManager {
// SDCard Path
final String MEDIA_PATH = new String(MediaStore.Audio.Media.getContentUri("external").toString());
private ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();

// Constructor
public SongsManager(){

}

/**
 * Function to read all mp3 files from sdcard
 * and store the details in ArrayList
 * */
public ArrayList<HashMap<String, String>> getPlayList(){
    File home = new File(MEDIA_PATH);

    if (home.listFiles(new FileExtensionFilter()).length > 0) {
        for (File file : home.listFiles(new FileExtensionFilter())) {
            HashMap<String, String> song = new HashMap<String, String>();
            song.put("songTitle", file.getName().substring(0, (file.getName().length() - 4)));
            song.put("songPath", file.getPath());

            // Adding each song to SongList
            songsList.add(song);
        }
    }
    // return songs list array
    return songsList;
}

/**
 * Class to filter files which are having .mp3 extension
 * */
class FileExtensionFilter implements FilenameFilter {
    public boolean accept(File dir, String name) {
        return (name.endsWith(".mp3") || name.endsWith(".MP3"));
    }
}

}

感谢任何能够提供帮助的人。:)


为什么不从MediaStore获取该列表? - Vincent Mimoun-Prat
我该怎么做呢?虽然我已经尝试了媒体存储.. - user1853951
4个回答

30
尽管这篇文章已经比较老了,但像我这样的其他人想要创建包含歌曲文件路径的音乐列表时,我在这里提供了解决方案。 MediaStore.Audio.Media.DATA列实际上包含媒体文件的路径。您可以使用以下代码片段获取必要的信息:
ContentResolver cr = getActivity().getContentResolver();

Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cur = cr.query(uri, null, selection, null, sortOrder);
int count = 0;

if(cur != null)
{
    count = cur.getCount();

    if(count > 0)
    {
        while(cur.moveToNext())
        {
            String data = cur.getString(cur.getColumnIndex(MediaStore.Audio.Media.DATA));
            // Add code to get more column here

            // Save to your list here
        }

    }

    cur.close();
}

@AshishSahu,您能否解释一下您的评论?我已经读了好几遍,但不明白您想说什么 :) - Amos Bordowitz
也许在Ashish的评论后代码已经被更正了,现在这条评论似乎不合适 :) - Sara
在Android Pie API 28中,光标返回null。 - Ibrahim Gharyali
@Ibrahim Gharyali:不知道发生了什么变化。我已经很久没有使用光标了。 - MARK002-MAB

21

您可以使用这段代码列出所有音乐文件。

//Some audio may be explicitly marked as not being music
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";

String[] projection = {
        MediaStore.Audio.Media._ID,
        MediaStore.Audio.Media.ARTIST,
        MediaStore.Audio.Media.TITLE,
        MediaStore.Audio.Media.DATA,
        MediaStore.Audio.Media.DISPLAY_NAME,
        MediaStore.Audio.Media.DURATION
};

cursor = this.managedQuery(
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
        projection,
        selection,
        null,
        null);

private List<String> songs = new ArrayList<String>();
while(cursor.moveToNext()) {
        songs.add(cursor.getString(0) + "||" 
                    + cursor.getString(1) + "||" 
                    + cursor.getString(2) + "||"
                    + cursor.getString(3) + "||"
                    + cursor.getString(4) + "||" 
                    + cursor.getString(5));
}

我没有尝试过这段代码,但它看起来是正确的。你用它应该会朝着正确的方向前进。


1
嗯,我尝试了你的代码,但似乎无法使其工作。你能修改我的代码并展示给我看吗?:) 我本来想自己做的,但我实在理解不了它。 - user1853951
@MarvinLabs,你知道从Mediastore获取特定歌曲文件路径的可能方法吗? - Ankit Srivastava
优秀的代码。我已经搜索了将近8个小时来寻找解决方案。谢谢。 - App Dev Guy
1
ManagedQuery已经被弃用了。请使用cursor.query方法代替。 - CyprUS
当文件夹以编程方式创建时,MediaStore无法工作。 - Sagar

4

我正在做同一个项目,已经解决了这个问题。

您需要一个自定义类来存储您的歌曲数据:

package YOUR_PACKAGE;

public class Songs
{
    private long mSongID;
    private String mSongTitle;

    public Songs(long id, String title){
        mSongID = id;
        mSongTitle = title;
    }

    public long getSongID(){
        return mSongID;
    }

    public String getSongTitle(){
        return mSongTitle;
    }
}

接下来,您需要在活动中定义 ArrayList,并使用 List View 来填充数据:

private ArrayList<Songs> arrayList;

在onCreate方法中:

arrayList = new ArrayList<Songs>();

接下来,您需要从设备中检索数据:

public void YOUR_METHOD_NAME(){
    ContentResolver contentResolver = getContentResolver();
    Uri songUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    Cursor songCursor = contentResolver.query(songUri, null, null, null, null);

    if(songCursor != null && songCursor.moveToFirst())
    {
        int songId = songCursor.getColumnIndex(MediaStore.Audio.Media._ID);
        int songTitle = songCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);

        do {
            long currentId = songCursor.getLong(songId);
            String currentTitle = songCursor.getString(songTitle);
            arrayList.add(new Songs(currentId, currentTitle, currentArtist));
        } while(songCursor.moveToNext());
    }
}

然后从onCreate方法中调用此方法:

YOUR_METHOD_NAME();

最后,您需要创建自定义适配器类,在带有ListView的活动的onCreate中定义此适配器,并将此适配器设置为您的ListView对象。

我看到这个问题是3年前被提出的,我认为问题已经解决了,但也许对某些人有用。谢谢。


0
这是一个简单的函数,它可以给你返回 File Object 中的所有音频文件。
 public static List<File> getAllAudios(Context c) {
    List<File> files = new ArrayList<>();
    String[] projection = { MediaStore.Audio.AudioColumns.DATA ,MediaStore.Audio.Media.DISPLAY_NAME};
    Cursor cursor = c.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
    try {
        cursor.moveToFirst();
        do{
            files.add((new File(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)))));
        }while(cursor.moveToNext());

        cursor.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return files;
}

在Android Pie API 28中,游标返回null。 - Ibrahim Gharyali
1
MediaStore.Audio.Media.DATA已经被弃用,在较新的API中其值为0,因此会导致崩溃。 - Otieno Rowland
@RowlandMtetezi:“MediaStore.Audio.Media.DATA已经被弃用”,这是事实。但“值为0”并不正确。仅仅因为它被弃用了,并不意味着它不能再使用了。 - HB.
@HB 我已经使用它运行了自己的代码,所以我非常清楚我在说什么。这也取决于使用哪个API。因此,在API被弃用的情况下,这两个陈述都是正确的。这就是我所说的。 - Otieno Rowland
@RowlandMtetezi “所以两个陈述都是正确的” - “具有0值”不是正确的。我们仍然可以使用数据列来检索设备上文件的文件路径。一些本地库需要一个文件对象,这就是为什么Google在Android R中重新引入了文件路径访问的原因。 - HB.
我正在使用API,其中返回了0,因此无法使用DATA列检索路径。因此,这很可能是非常API特定的。 - Otieno Rowland

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