Question

I am using a simple adapter to fill a listview, I can't find how to order items by a specific attribute of the groupData, here is my code:

 public class LibraryFragment extends Fragment {

    private  Context mContext;
    private  ListView listView1;
    private ListAdapter adapter;
     private List<Map<String, String>> groupData;
     private Map<String, String> group;
     private  String[] from = new String[] {"url", "title", "artist", "duration"};
     private  int[] to = new int[] {R.id.url, R.id.title, R.id.artist, R.id.duration};

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_library, container, false);

        mContext = getActivity();
        listView1 = (ListView) rootView.findViewById(R.id.listView1);
        fillLibrary();

        return rootView;
    }

    public void fillLibrary(){

        ArrayList<Map<String, String>> groupData = new ArrayList<Map<String, String>>();

        File music = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + Environment.DIRECTORY_MUSIC + "/myapp");
        if (music.isDirectory()){
            File tracks[] = music.listFiles();

            MediaMetadataRetriever mmr = new MediaMetadataRetriever();

            for (int i = 0; i < tracks.length; i++) {


                File track = tracks[i];
                String trackPath = track.getAbsolutePath();
                String trackName = track.getName();
                String trackExt = trackName.substring(trackName.lastIndexOf('.') + 1);

                if(trackExt.equals("MP3")||trackExt.equals("mp3"))
                {
                    mmr.setDataSource(trackPath);

                    // -- create record
                    HashMap<String, String> group = new HashMap<String, String>();

                    group.put( "url", trackPath);
                    group.put( "title", mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE));
                    group.put( "artist", mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST));
                    group.put( "duration", getDurationString(Integer.parseInt(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION))/1000));

                    groupData.add(group);
                }


            }

            Collections.sort(groupData, Functions.mapComparator);

            adapter = new SimpleAdapter(mContext , groupData, R.layout.library_item, 
                    from,
                    to );

            listView1.setAdapter( adapter );
        }
    }
 }

And here is my functions Functions.mapComparator

 public static Comparator<Map<String, String>> mapComparator = new Comparator<Map<String, String>>() {
    public int compare(Map<String, String> m1, Map<String, String> m2) {
        return m1.get("title").compareTo(m2.get("title"));
    }
};

Do you know what I m doing wrong?

EDIT: Here is the logcat

01-09 20:06:12.005: D/AndroidRuntime(10685): Shutting down VM
01-09 20:06:12.005: W/dalvikvm(10685): threadid=1: thread exiting with uncaught exception (group=0x40d31930)
01-09 20:06:12.065: E/AndroidRuntime(10685): FATAL EXCEPTION: main
01-09 20:06:12.065: E/AndroidRuntime(10685): java.lang.NullPointerException
01-09 20:06:12.065: E/AndroidRuntime(10685):    at com.myapp.mobile.Functions$1.compare(Functions.java:44)
01-09 20:06:12.065: E/AndroidRuntime(10685):    at com.myapp.mobile.Functions$1.compare(Functions.java:1)
Was it helpful?

Solution

  1. Looks like one of your Maps does not contain a value for "title", or it is null.
  2. Wouldn't it be easier to use an Object instead of a Map to store your data? Like new Song(url, title, artist, duration);. It could implement Comparable, that way you don't need the Comparator anymore.

OTHER TIPS

MediaMetadataRetriever.extractMetadata() can return null, and that's what you're getting. This is probably because some of the music files you are trying to retrieve don't have title information embedded. You should check the return value of extractMetadata() before adding it.

A simple check like:

String title = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
if (title == null) continue;

will ignore any of those entries without titles (though note the other attributes can also be null, even if a title is set) by skipping to the next entry without adding.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top