StErMi
StErMi

Reputation: 5469

Android list music by folders and play them

I'm developing music player for android that is already on the market. Users are asking to add a Folder view to list all folders that has music in their smartphone and I want to develop it.

MediaStore already know which are the correct paths to follow (because it needs to know them to re-scan every times the sdcard) so I was wondering if there is a way to get those paths and use them to show music to the user.

Another options (but I don't like it) to get those paths is to query MediaStore for all the music in the library and loop on them to get the common base paths. But if user have more than 1/2k music it will be a huge and not optimized way.

Do you know how can I solve it?

I was also thingking about listing all folders and files in the sdcard but I'm encountering in some recursive problem because I want to not show:

What do you think about this?

UPDATE: what I want to do is something like this: https://play.google.com/store/apps/details?id=cyberniko.musicFolderPlayer I want to show folders where there are some music and allow the user to start playing music in selected folders.

Upvotes: 2

Views: 6526

Answers (2)

CommonsWare
CommonsWare

Reputation: 1007554

MediaStore already know which are the correct paths to follow (because it needs to know them to re-scan every times the sdcard) so I was wondering if there is a way to get those paths and use them to show music to the user.

MediaStore scans all of external storage, AFAIK, not just some specific root folders.

Upvotes: 1

StErMi
StErMi

Reputation: 5469

One possible solution as I said is to start scanning all directories from the SDCard with this FileFilter that I wrote:

This AudioFilter is applied to a directory that returns all files that is a song (checking extensions) and all directories that contains a song and not contains a .nomedia

This solution, anyway, need to be skipped because it takes too long to load the dir list (because of the recursive 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;
        }
    }

}

Upvotes: 1

Related Questions