1

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)
2
  • what output do you get? Commented Jan 9, 2014 at 17:58
  • It is a NullPointerException so it seems to me that one of the get("title") is returning null. Check out the maps for title values. Commented Jan 9, 2014 at 18:17

2 Answers 2

4
  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.
Sign up to request clarification or add additional context in comments.

2 Comments

I'm pretty new to android but it seems to be a nice idea, then how could I implement such an Object to fill a listview?
I would only argue that in this case I think how the objects are compared could change. E.g. sorting by title, artist, etc. This is a separate concern to the object itself and should be separated out. And sorting is also a concern of the list and not the song anyway. It would be most appropriate as part of a Song List class.
1

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.

1 Comment

Both you and Simon are right, Simon was faster, but you still get an Up :) Thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.