Sabatino
Sabatino

Reputation: 123

(Android) How to browse only folders that contains music

I'm trying to make a Fragment that contains a folder browser which shows only folders where there is at least one song. I've tried to follow several tutorials and to use a Filefilter, but I still see folders that don't contain anything that's useful (eg. Facebook folder), how can I do it? In other words, I'm trying to make a folder browser like this; could anyone help me?

Code: FolderFragment.java

public class FolderFragment extends Fragment {
    private File file;
    private List<String> myList;
    private FolderAdapter mAdapter;
    private Context mContext;
    private LayoutInflater mInflater;
    private ViewGroup mContainer;
    private LinearLayoutManager mLayoutManager;
    View mRootView;
    private RecyclerView mRecyclerView;
    String root_files;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        mContext = container.getContext();
        mInflater = inflater;
        mContainer = container;

        mRootView = inflater.inflate(R.layout.fragment_folders, mContainer, false);
        mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.recycler_view_folders);
        mLayoutManager = new LinearLayoutManager(mContext);
        mRecyclerView.setLayoutManager(mLayoutManager);
        if(getActivity() != null)
            new loadFolders().execute("");
        return mRootView;
    }

    private class loadFolders extends AsyncTask<String, Void, String>{

        @Override
        protected String doInBackground(String... params) {
            Activity activity = getActivity();
            if (activity != null) {

                mAdapter = new FolderAdapter(activity, new File("/storage"));
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String result){
            mRecyclerView.setAdapter(mAdapter);
            mAdapter.notifyDataSetChanged();
        }
    }
}

FolderAdapter.java

public class FolderAdapter extends RecyclerView.Adapter<FolderAdapter.ItemHolder> implements BubbleTextGetter {
    private List<File> mFileSet;
    private List<Song> mSongs;
    private File mRoot;
    private Activity mContext;
    private boolean mBusy = false;

    public FolderAdapter(Activity context, File root){
        mContext = context;
        mSongs = new ArrayList<>();
        updateDataSet(root);
    }

    @Override
    public FolderAdapter.ItemHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_folder_list, viewGroup, false);
        return new ItemHolder(v);
    }

    @Override
    public void onBindViewHolder(final FolderAdapter.ItemHolder itemHolder, int i) {
        File localItem = mFileSet.get(i);
        Song song = mSongs.get(i);
        itemHolder.title.setText(localItem.getName());
        if (localItem.isDirectory()) {
            itemHolder.albumArt.setImageResource("..".equals(localItem.getName()) ? R.drawable.icon_4 : R.drawable.icon_5);
        } else {
            itemHolder.albumArt.setImageResource(R.drawable.icon_folder);
        }
    }

    @Override
    public int getItemCount(){
        Log.d("size fileset: ", ""+mFileSet.size());
        return mFileSet.size();
    }

    @Deprecated
    public void updateDataSet(File newRoot){
        if(mBusy) return;
        if("..".equals(newRoot.getName())){
            goUp();
            return;
        }
        mRoot = newRoot;
        mFileSet = FolderLoader.getMediaFiles(newRoot, true);
        getSongsForFiles(mFileSet);
    }

    @Deprecated
    public boolean goUp(){
        if(mRoot == null || mBusy){
            return false;
        }
        File parent = mRoot.getParentFile();
        if(parent != null && parent.canRead()){
            updateDataSet(parent);
            return true;
        } else {
            return false;
        }
    }

    public boolean goUpAsync(){
        if(mRoot == null || mBusy){
            return false;
        }
        File parent = mRoot.getParentFile();
        if(parent != null && parent.canRead()){
            return updateDataSetAsync(parent);
        } else {
            return false;
        }
    }

    public boolean updateDataSetAsync(File newRoot){
        if(mBusy){
            return false;
        }
        if("..".equals(newRoot.getName())){
            goUpAsync();
            return false;
        }
        mRoot = newRoot;
        new NavigateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mRoot);
        return true;
    }

    @Override
    public String getTextToShowInBubble(int pos){
        if(mBusy || mFileSet.size() == 0) return "";
        try{
            File f = mFileSet.get(pos);
            if(f.isDirectory()){
                return String.valueOf(f.getName().charAt(0));
            } else {
                return Character.toString(f.getName().charAt(0));
            }
        } catch(Exception e){
            return "";
        }
    }

    private void getSongsForFiles(List<File> files){
        mSongs.clear();
        for(File file : files){
            mSongs.add(SongLoader.getSongFromPath(file.getAbsolutePath(), mContext));
        }
    }

    private class NavigateTask extends AsyncTask<File, Void, List<File>>{

        @Override
        protected void onPreExecute(){
            super.onPreExecute();
            mBusy = true;
        }

        @Override
        protected List<File> doInBackground(File... params){
            List<File> files = FolderLoader.getMediaFiles(params[0], true);
            getSongsForFiles(files);
            return files;
        }

        @Override
        protected void onPostExecute(List<File> files){
            super.onPostExecute(files);
            mFileSet = files;
            notifyDataSetChanged();
            mBusy = false;
            //PreferencesUtility.getInstance(mContext).storeLastFolder(mRoot.getPath());

        }
    }

    public class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        protected TextView title;
        protected ImageView albumArt;

        public ItemHolder(View view) {
            super(view);
            this.title = (TextView) view.findViewById(R.id.folder_title);
            this.albumArt = (ImageView) view.findViewById(R.id.folder_album_art);
            view.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if (mBusy) {
                return;
            }
            final File f = mFileSet.get(getAdapterPosition());

            if (f.isDirectory() && updateDataSetAsync(f)) {
                albumArt.setImageResource(R.drawable.ic_menu_send);
            } else if (f.isFile()) {

                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(mContext, "", Toast.LENGTH_LONG).show();
                    }
                }, 100);
            }
        }
    }
}

FolderLoader.java

public class FolderLoader {

    private static final String[] SUPPORTED_EXT = new String[] {
            "mp3",
            "m4a",
            "aac",
            "flac",
            "wav"
    };

    public static List<File> getMediaFiles(File dir, final boolean acceptDirs) {
        ArrayList<File> list = new ArrayList<>();
        list.add(new File(dir, "/storage"));
        if (dir.isDirectory()) {
            List<File> files = Arrays.asList(dir.listFiles(new FileFilter() {

                @Override
                public boolean accept(File file) {
                    if (file.isFile()) {
                        String name = file.getName();
                        return !".nomedia".equals(name) && checkFileExt(name);
                    } else if (file.isDirectory()) {
                        return acceptDirs && checkDir(file);
                    } else
                        return false;
                }
            }));
            Collections.sort(files, new FilenameComparator());
            Collections.sort(files, new DirFirstComparator());
            list.addAll(files);
        }

        return list;
    }

    public static boolean isMediaFile(File file) {
        return file.exists() && file.canRead() && checkFileExt(file.getName());
    }

    private static boolean checkDir(File dir) {
        return dir.exists() && dir.canRead() && !".".equals(dir.getName()) && dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                String name = pathname.getName();
                return !".".equals(name) && !"..".equals(name) && pathname.canRead() && (pathname.isDirectory()  || (pathname.isFile() && checkFileExt(name)));
            }

        }).length != 0;
    }

    private static boolean checkFileExt(String name) {
        if (TextUtils.isEmpty(name)) {
            return false;
        }
        int p = name.lastIndexOf(".") + 1;
        if (p < 1) {
            return false;
        }
        String ext = name.substring(p).toLowerCase();
        for (String o : SUPPORTED_EXT) {
            if (o.equals(ext)) {
                return true;
            }
        }
        return false;
    }

    private static class FilenameComparator implements Comparator<File> {
        @Override
        public int compare(File f1, File f2) {
            return f1.getName().compareTo(f2.getName());
        }
    }

    private static class DirFirstComparator implements Comparator<File> {
        @Override
        public int compare(File f1, File f2) {
            if (f1.isDirectory() == f2.isDirectory())
                return 0;
            else if (f1.isDirectory() && !f2.isDirectory())
                return -1;
            else
                return 1;
        }
    }
}

Upvotes: 1

Views: 2238

Answers (2)

Rohit Singh
Rohit Singh

Reputation: 18202

A much simpler approach would be if you use ContentProviders

You can list down all the music files or any file as such(You can even provide sorting or more filters to narrow down your list). It is just like using a database.

I can not post the full code right now. But I can give you the idea of how to work out this problem and this approach would be more readable and concise.

Here what you need to do.

1) Create an instance of Cursor.
2) Iterate Cursor to get your media files

Creating an instance

Cursor cursor = getContentResolver().query(URI uri ,String[] projection, null,null,null);

Let's focus on the first two parameters

a) URI - It could be either Internal or External Storage.
For External Use - MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
For External Use - MediaStore.Audio.Media.INTERAL_CONTENT_URI;

b) Projection is an array which you use to get metadata of your file such as PATH, ARTIST NAME, NO OF SONGS and many more

String[] proj = new String[]{MediaStore.Audio.Media.DISPLAY_NAME,MediaStore.Audio.Media.DATA};

Now you have created Cursor. So the next part is to iterate through it.

while (cursor.moveToNext())
  {
     name = cursor.getString(cursor.getColumnIndex(modelConst.get_Proj()[0]));
     path =  cursor.getString(cursor.getColumnIndex(modelConst.get_Proj()[1]));
  }

Upvotes: 2

SARATH V
SARATH V

Reputation: 500

Following code may help you. Be more specific, show some codes you have used if following doesn't work or it is not what you want.

Intent intent;
            intent = new Intent();
            intent.setAction(Intent.ACTION_GET_CONTENT);
            intent.setType("audio/*");
            startActivityForResult(Intent.createChooser(intent, "Title"), 89);

on activty result method use following

 if (requestCode == 89 && resultCode == Activity.RESULT_OK){
        if ((data != null) && (data.getData() != null)){
            Uri audioFileUri = data.getData();
           // use uri to get path

            String path= audioFileUri.getPath();
        }
    }

Make sure given external storage read permission in manifest and run time permission check for latest sdk.

Upvotes: 0

Related Questions