1

I'm sorry but I'm a newbie who's having some problems when trying to retrieve all the mp3 files from the phone's internal storage. Not sure why but I'm not able to retrieve any files, ie ArrayList is getting null value

Here's my code from the PlaylistActivity, here's where I'm retrieving the mp3 files:

private static final int RC_READ = 1;
private RecyclerView mRecycler;
private ArrayList<File> mSongs;
private String[] mSongNames;
private MyAdapter mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_playlist);

    mRecycler=(RecyclerView) findViewById(R.id.recyclerView);
    mRecycler.setLayoutManager(new LinearLayoutManager(this));
    mRecycler.setHasFixedSize(true);

    mSongs=new ArrayList<>();

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, RC_READ );
    }

    else {
        getSongsPlayList(); }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if(requestCode== RC_READ && grantResults[0]== PackageManager.PERMISSION_GRANTED){
        getSongsPlayList();
    }
}

private void getSongsPlayList(){
    Log.d("Music","getSongsPlayList()");
    mSongs = findSongs(Environment.getExternalStorageDirectory().getAbsolutePath());
    if (mSongs != null) {
        mSongNames = new String[mSongs.size()];
        for (int i = 0; i < mSongs.size(); i++) {
            mSongNames[i] = mSongs.get(i).getName().replace(".mp3", "").replace(".wav", "");
            Log.d("Music","Song name:"+mSongNames[i]);
        }
    } else {
        Log.d("Music", "Null");
        mSongNames = new String[1];
        mSongNames[0] = "Star Boy";
    }
    mAdapter = new MyAdapter(mSongNames, getApplicationContext());
    mRecycler.setAdapter(mAdapter);
}

private ArrayList<File> findSongs(String absolutePath) {
    ArrayList<File> mList=new ArrayList<>();

    try{
        File rootFolder=new File(absolutePath);
        File[] files=rootFolder.listFiles();

        for(File file: files){
            if(file.isDirectory()) {
                if (findSongs(file.getAbsolutePath()) != null) {
                    mList.addAll((findSongs(file.getAbsolutePath())));
                } else {
                    break;
                }
            } else if(file.getName().endsWith(".mp3") || file.getName().endsWith(".wav")){
                mList.add(file);
            }
        }
        return mList;
    }catch (Exception e){
        return null;
    }
}

Here's my MyAdapter class code for the recyclerview:

private String[] mSongs;
private Context mContext;

public MyAdapter(String[] mSongs, Context mContext) {
    this.mSongs = mSongs;
    this.mContext=mContext;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View v= LayoutInflater.from(mContext).inflate(R.layout.custom_row,parent,false);
    return new ViewHolder(v);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    holder.mSong.setText(mSongs[position]);

}

@Override
public int getItemCount() {
    return mSongs.length;

}

public class ViewHolder extends RecyclerView.ViewHolder {
    TextView mSong;
    public ViewHolder(View itemView) {
        super(itemView);
        mSong=(TextView) itemView.findViewById(R.id.songName);
    }
}

The recyclerView is displaying only one song, ie Starboy, which I'm using to check if the mSongs is null or not and apparently, it is null after the execution of findSongs method. I'm not sure what's wrong. Thanks in advance!

PS: I have added the necessary permissions for the manifest.xml as follows:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE"/>
  • You are looping findSongs() from within findSongs(). Just scan the directory (once) for files(mp3/wav) and then add them to the list. – Vesper Sep 17 '18 at 14:31

1 Answers1

1

I'm not 100% sure, but to me it looks like you're not asking for external storage Permissions.

Since Android 6.0 (API Level 23), it is no longer enough to write the rights in AndroidManifest.xml. You must now also request the permissions during the runtime. For example, in the onCreate method of your activity

Please check the following links:
Storage permission error in Marshmallow
https://developer.android.com/training/permissions/requesting

If that does not help, you'll need to check the LogCat for an exception or other information

rjdev
  • 56
  • 6
  • I made the changes to the code as you told me to (see the post again). Now what's happening is, the app is becoming very laggy and is taking a good 2-3 minutes of time to load all the files (I have exactly 150 songs on my phone), so is there something I can do to perform the song retrieval only once and just use the mSongnames array directly the next time I open my app? – Pratyush Sahu Sep 17 '18 at 15:18
  • @Sashu use sqlite and add a scan filesystem feature. When filesystem is being scanned you populate the db, for later usage in array. Hope it helps. – Curious Mind Sep 17 '18 at 15:38