【问题标题】:(Android) How to browse only folders that contains music(Android) 如何只浏览包含音乐的文件夹
【发布时间】:2018-01-24 10:53:52
【问题描述】:

我正在尝试制作一个包含文件夹浏览器的Fragment,它只显示至少有一首歌曲的文件夹。 我尝试遵循几个教程并使用Filefilter,但我仍然看到不包含任何有用内容的文件夹(例如 Facebook 文件夹),我该怎么做? 换句话说,我正在尝试制作像this 这样的文件夹浏览器;谁能帮帮我?

代码: 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;
        }
    }
}

【问题讨论】:

  • 向我们展示您目前拥有的代码。
  • 您想查看所有音乐文件吗?我可以帮你。目前
  • @billynomates 检查编辑
  • @RohitSingh 真的吗?非常感谢,我会将您添加到贡献者列表中

标签: java android browser directory filefilter


【解决方案1】:

如果您使用 ContentProviders

,则更简单的方法是

您可以列出所有音乐文件或任何文件(您甚至可以提供排序或更多过滤器来缩小列表范围)。这就像使用数据库一样。

我现在不能发布完整的代码。但我可以告诉你如何解决这个问题,这种方法会更易读、更简洁。

这是您需要做的。

1) 创建一个 Cursor 实例。
2)迭代光标以获取您的媒体 文件

创建实例

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

让我们关注前两个参数

a) URI - 它可以是内部或外部存储。
供外部使用 - MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
供外部使用 - MediaStore.Audio.Media.INTERAL_CONTENT_URI;

b) Projection 是一个数组,您可以使用它来获取文件的元数据,例如 PATH、ARTIST NAME、NO OF SONGS 等等

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

现在您已经创建了光标。所以下一部分是遍历它。

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

【讨论】:

  • 我试着按照你说的去做,但我得到了这个错误:java.lang.NullPointerException:Attempt to write to field 'int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' on a null object reference(没有指定这个错误在哪里,但是如果我把光标放在 cmets 之间,代码可以正常工作)。这是我的新代码:pastebin.com/6trkmaQu
  • @Sabatino 我在没有 RecyclerView 适配器的本地机器上检查了您的代码(粘贴箱)。它工作正常。您似乎对 RecyclerView Adapter 有问题。
  • 好的,我发现我的应用程序崩溃并且工作正常(非常感谢),即使我想按文件夹对所有歌曲进行分组(而不是全部显示并只添加它们的路径),怎么能我管这个?我正在考虑在我的适配器中使用一个控件将所有歌曲与相同的路径分组,如果我点击一个项目,它会显示该文件夹中的所有歌曲,你怎么看?
  • @Sabatino 我不确定 android sdk 中是否有任何提供程序可以为您提供文件夹。但是,如果您想获取文件的父文件夹,此链接可能会对您有所帮助 stackoverflow.com/questions/8197049/… 。不过我不确定。如果您有任何解决方案,请告诉我。
【解决方案2】:

以下代码可能会对您有所帮助。更具体地说,如果以下不起作用或不是您想要的,请显示您使用过的一些代码。

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

在活动结果方法上使用以下

 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();
        }
    }

确保在清单中授予外部存储读取权限,并检查最新 sdk 的运行时权限。

【讨论】:

    猜你喜欢
    • 2011-06-15
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    相关资源
    最近更新 更多