Question

I'm trying to figure out how to create an SMS inbox list like the SMS list from the native SMS messenger app that comes with Android. I have the following code, but it seems extremely slow if you have a lot of SMS messages. I was hoping for some guidance on a better method.

I'm hoping to get the address, snippet (or last message in the conversation) and the person (Contact Display Name) and display them in a ListView.

The following code works with retrieving the data, but when I run this on a phone with a lot of messages, the Activity hangs for a few seconds while all the queries are being performed.

The following code snippets are the chained methods that I use to retrieve the information I mentioned. Additionally, should I be using threads in the Activity or something? A thread to perform the queries, then update the ListView?

Thanks for any help in advance!

private void getConversations(ArrayList<Conversation> conversationList){
    Uri uri = Uri.parse("content://sms/conversations");
    String[] selection = {"thread_id", "snippet"};
    Cursor cur = context.getContentResolver().query(uri, selection, null, null, "date DESC");

    if(cur.getCount() != 0){

        while(cur.moveToNext()) {
            String thread_id = cur.getString(cur.getColumnIndex("thread_id"));
            String snippet = cur.getString(cur.getColumnIndex("snippet"));

            Conversation conversation = new Conversation(thread_id, snippet);
            conversationList.add(conversation);
        }
    }
    cur.close();
}

private void getAddresses(ArrayList<Conversation> conversationList){
    Uri uri = Uri.parse("content://sms");
    String[] selection = {"address"};


    for(Conversation conversation : conversationList){

        Cursor cur = context.getContentResolver().query(uri, selection , "thread_id=?", new String[] {conversation.getThread_id()}, null);
        if(cur.getCount() != 0){
            cur.moveToFirst();
            conversation.setAddress(cur.getString(cur.getColumnIndex("address")));
        }
        cur.close();
    }

}

private void getDisplayName(ArrayList<Conversation> conversationList){
    Log.d(TAG, "Adding display names");
    for(Conversation conversation: conversationList) {
        Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, conversation.getAddress());
        Cursor cur = context.getContentResolver().query(uri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null);

        if(cur.moveToFirst()){
            conversation.setPerson(cur.getString(cur.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME)));
        }
        cur.close();
    }
}
Was it helpful?

Solution

Yes, you are on the right path. You could use an AsyncTask to perform what you are doing right now in its doInBackground method, and when it finishes its work, you just have to use the onPostExecute method to publish the results to the UI.

As you are grouping the messages by conversation, you can even try to update the UI using onProgressUpdate. This way you can populate the UI as the fetching goes on (in theory could work well... it all comes down to your needs really :-) )

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