Android 按文件夹列出音乐并播放

Posted

技术标签:

【中文标题】Android 按文件夹列出音乐并播放【英文标题】:Android list music by folders and play them 【发布时间】:2012-06-09 07:25:45 【问题描述】:

我正在开发已经上市的安卓音乐播放器。 用户要求添加一个文件夹视图来列出他们智能手机中所有包含音乐的文件夹,我想开发它。

MediaStore 已经知道要遵循的正确路径(因为它需要知道它们才能在每次 sdcard 时重新扫描)所以我想知道是否有办法获取这些路径并使用它们向用户。

获取这些路径的另一个选项(但我不喜欢它)是在 MediaStore 中查询库中的所有音乐并循环它们以获取公共基本路径。但如果用户拥有超过 1/2k 的音乐,这将是一种巨大且未优化的方式。

你知道我该如何解决吗?

我也在考虑列出 sdcard 中的所有文件夹和文件,但我遇到了一些递归问题,因为我不想显示:

不是音频文件(已使用 FileFilter 完成) 不显示空文件夹(已经完成但有递归问题) 不显示带有 .nomedia 文件的文件夹(这告诉我没有任何媒体文件,但存在递归问题)。其他应用程序创建的许多文件夹也没有放置 .nomedia 文件,所以我必须向它们展示

您对此有何看法?

更新:我想做的是这样的:https://play.google.com/store/apps/details?id=cyberniko.musicFolderPlayer 我想显示有音乐的文件夹,并允许用户开始在选定的文件夹中播放音乐。

【问题讨论】:

【参考方案1】:

我所说的一种可能的解决方案是使用我编写的 FileFilter 开始扫描 SDCard 中的所有目录:

此 AudioFilter 应用于返回所有歌曲文件的目录(检查扩展名)以及包含歌曲但不包含 .nomedia 的所有目录

这个解决方案,无论如何,需要跳过,因为加载dir列表需要太长时间(因为递归alg)

package com.designfuture.music.util;

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

import com.designfuture.framework.util.LogHelper;

public class AudioFileFilter implements FileFilter 

    protected static final String TAG = "AudioFileFilter";
    /**
     * allows Directories
     */
    private final boolean allowDirectories;

    public AudioFileFilter( boolean allowDirectories) 
        this.allowDirectories = allowDirectories;
    

    public AudioFileFilter() 
        this(true);
    

    @Override
    public boolean accept(File f) 
        if ( f.isHidden() || !f.canRead() ) 
            return false;
        

        if ( f.isDirectory() ) 
            return checkDirectory( f );
        
        return checkFileExtension( f );
    

    private boolean checkFileExtension( File f ) 
        String ext = getFileExtension(f);
        if ( ext == null) return false;
        try 
            if ( SupportedFileFormat.valueOf(ext.toUpperCase()) != null ) 
                return true;
            
         catch(IllegalArgumentException e) 
            //Not known enum value
            return false;    
        
        return false; 
    

    private boolean checkDirectory( File dir ) 
        if ( !allowDirectories ) 
            return false;
         else 
            final ArrayList<File> subDirs = new ArrayList<File>();
            int songNumb = dir.listFiles( new FileFilter() 

                @Override
                public boolean accept(File file) 
                    if ( file.isFile() ) 
                        if ( file.getName().equals( ".nomedia" ) )
                            return false;

                        return checkFileExtension( file );
                     else if ( file.isDirectory() )
                        subDirs.add( file );
                        return false;
                     else
                        return false;
                
             ).length;

            if ( songNumb > 0 ) 
                LogHelper.i(TAG, "checkDirectory: dir " + dir.toString() + " return true con songNumb -> " + songNumb );
                return true;
            

            for( File subDir: subDirs ) 
                if ( checkDirectory( subDir ) ) 
                    LogHelper.i(TAG, "checkDirectory [for]: subDir " + subDir.toString() + " return true" );
                    return true;
                
            
            return false;
               
    

    private boolean checkFileExtension( String fileName ) 
        String ext = getFileExtension(fileName);
        if ( ext == null) return false;
        try 
            if ( SupportedFileFormat.valueOf(ext.toUpperCase()) != null ) 
                return true;
            
         catch(IllegalArgumentException e) 
            //Not known enum value
            return false;    
        
        return false; 
    

    public String getFileExtension( File f ) 
        return getFileExtension( f.getName() );
    

    public String getFileExtension( String fileName ) 
        int i = fileName.lastIndexOf('.');
        if (i > 0) 
            return fileName.substring(i+1);
         else 
            return null;
    

    /**
     * Files formats currently supported by Library
     */
    public enum SupportedFileFormat
    
        _3GP("3gp"),
        MP4("mp4"),
        M4A("m4a"),
        AAC("aac"),
        TS("ts"),
        FLAC("flac"),
        MP3("mp3"),
        MID("mid"),
        XMF("xmf"),
        MXMF("mxmf"),
        RTTTL("rtttl"),
        RTX("rtx"),
        OTA("ota"),
        IMY("imy"),
        OGG("ogg"),
        MKV("mkv"),
        WAV("wav");

        private String filesuffix;

        SupportedFileFormat( String filesuffix ) 
            this.filesuffix = filesuffix;
        

        public String getFilesuffix() 
            return filesuffix;
        
    


【讨论】:

【参考方案2】:

MediaStore 已经知道要遵循的正确路径(因为它需要知道它们才能在每次 sdcard 时重新扫描)所以我想知道是否有办法获取这些路径并使用它们向用户。

MediaStore 扫描所有外部存储、AFAIK,而不仅仅是某些特定的根文件夹。

【讨论】:

以上是关于Android 按文件夹列出音乐并播放的主要内容,如果未能解决你的问题,请参考以下文章

Android列出所有音乐文件的代码

Android:如何为我的应用播放的任何音乐文件创建淡入/淡出音效?

MediaPlayer 仅在调试模式下播放音乐文件(Android)

android - 如何在我的音乐播放器中从文件管理器播放 mp3 文件?

上传音乐到Android模拟器的SD卡,并在Android模拟器上播放

在android中播放两个音频文件