Reputation: 123
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
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
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