FileDocCategorySizeDatePackage
ConversationList.javaAPI DocAndroid 1.5 API24477Wed May 06 22:42:46 BST 2009com.android.mms.ui

ConversationList

public class ConversationList extends android.app.ListActivity implements DraftCache.OnDraftChangedListener
This activity provides a list view of existing conversations.

Fields Summary
private static final String
TAG
private static final boolean
DEBUG
private static final boolean
LOCAL_LOGV
private static final int
THREAD_LIST_QUERY_TOKEN
private static final int
SEARCH_TOKEN
private static final int
DELETE_CONVERSATION_TOKEN
private static final int
MENU_COMPOSE_NEW
private static final int
MENU_SEARCH
private static final int
MENU_DELETE_ALL
private static final int
MENU_PREFERENCES
public static final int
MENU_DELETE
private static final int
MENU_VIEW
private static final int
MENU_VIEW_CONTACT
private static final int
MENU_ADD_TO_CONTACTS
private ThreadListQueryHandler
mQueryHandler
private ConversationListAdapter
mListAdapter
private CharSequence
mTitle
private android.net.Uri
mBaseUri
private String
mSelection
private String[]
mProjection
private int
mQueryToken
private String
mFilter
private boolean
mSearchFlag
private CachingNameStore
mCachingNameStore
private final android.view.View.OnCreateContextMenuListener
mConvListOnCreateContextMenuListener
private final android.view.View.OnKeyListener
mThreadListKeyListener
Constructors Summary
Methods Summary
private voidconfirmDeleteDialog(android.content.DialogInterface.OnClickListener listener, boolean deleteAll)

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.confirm_dialog_title);
        builder.setIcon(android.R.drawable.ic_dialog_alert);
        builder.setCancelable(true);
        builder.setPositiveButton(R.string.yes, listener);
        builder.setNegativeButton(R.string.no, null);
        builder.setMessage(deleteAll
                ? R.string.confirm_delete_all_conversations
                : R.string.confirm_delete_conversation);

        builder.show();
    
public static android.content.IntentcreateAddContactIntent(java.lang.String address)

        // address must be a single recipient
        Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
        intent.setType(Contacts.People.CONTENT_ITEM_TYPE);
        if (Recipient.isPhoneNumber(address)) {
            intent.putExtra(Insert.PHONE, address);
        } else {
            intent.putExtra(Insert.EMAIL, address);
        }
        
        return intent;
    
private voidcreateNewMessage()

        Intent intent = new Intent(this, ComposeMessageActivity.class);
        startActivity(intent);
    
private java.lang.StringgetAddress(android.database.Cursor cursor)

        
        long threadId = cursor.getLong(ConversationListAdapter.COLUMN_ID);
        String address = null;
        if (mListAdapter.isSimpleMode()) {
            address = MessageUtils.getRecipientsByIds(
                    this,
                    cursor.getString(ConversationListAdapter.COLUMN_RECIPIENTS_IDS),
                    true /* allow query */);
        } else {
            String msgType = cursor.getString(ConversationListAdapter.COLUMN_MESSAGE_TYPE);
            if (msgType.equals("sms")) {
                address = cursor.getString(ConversationListAdapter.COLUMN_SMS_ADDRESS);
            } else {
                address = MessageUtils.getAddressByThreadId(this, threadId);
           }
        }
        return address;
    
protected voidhandleCreationIntent(android.content.Intent intent)

        // Handle intents that occur upon creation of the activity.
        initNormalQueryArgs();
   
private voidinitListAdapter()

        mListAdapter = new ConversationListAdapter(this, null, true, mCachingNameStore);
        setListAdapter(mListAdapter);
    
private voidinitNormalQueryArgs()

        Uri.Builder builder = Threads.CONTENT_URI.buildUpon();
        builder.appendQueryParameter("simple", "true");
        mBaseUri = builder.build();
        mSelection = null;
        mProjection = ConversationListAdapter.PROJECTION;
        mQueryToken = THREAD_LIST_QUERY_TOKEN;
        mTitle = getString(R.string.app_label);
    
public static booleanisFailedToDeliver(android.content.Intent intent)

        return (intent != null) && intent.getBooleanExtra("undelivered_flag", false);
    
public voidonConfigurationChanged(android.content.res.Configuration newConfig)

        // We override this method to avoid restarting the entire
        // activity when the keyboard is opened (declared in
        // AndroidManifest.xml).  Because the only translatable text
        // in this activity is "New Message", which has the full width
        // of phone to work with, localization shouldn't be a problem:
        // no abbreviated alternate words should be needed even in
        // 'wide' languages like German or Russian.

        super.onConfigurationChanged(newConfig);
        if (DEBUG) Log.v(TAG, "onConfigurationChanged: " + newConfig);
    
public booleanonContextItemSelected(android.view.MenuItem item)


    
        
        Cursor cursor = mListAdapter.getCursor();
        long threadId = cursor.getLong(ConversationListAdapter.COLUMN_ID);
        switch (item.getItemId()) {
            case MENU_DELETE: {
                DeleteThreadListener l = new DeleteThreadListener(threadId);
                confirmDeleteDialog(l, false);
                break;
            }
            case MENU_VIEW: {
                String address = getAddress(cursor);
                openThread(threadId, address);
                break;
            }
            case MENU_VIEW_CONTACT: {
                String address = getAddress(cursor);
                viewContact(address);
                break;
            }
            case MENU_ADD_TO_CONTACTS: {
                String address = getAddress(cursor);
                startActivity(createAddContactIntent(address));
                break;
            }
            default:
                break;
        }

        return super.onContextItemSelected(item);
    
protected voidonCreate(android.os.Bundle savedInstanceState)


                          
        
        // Returns comma-separated list of contact's display names
        // given a semicolon-delimited string of canonical phone
        // numbers.
           
    

    
        
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.conversation_list_screen);

        mQueryHandler = new ThreadListQueryHandler(getContentResolver());

        ListView listView = getListView();
        LayoutInflater inflater = LayoutInflater.from(this);
        ConversationHeaderView headerView = (ConversationHeaderView)
                inflater.inflate(R.layout.conversation_header, listView, false);
        headerView.bind(getString(R.string.new_message),
                getString(R.string.create_new_message));
        listView.addHeaderView(headerView, null, true);

        listView.setOnCreateContextMenuListener(mConvListOnCreateContextMenuListener);
        listView.setOnKeyListener(mThreadListKeyListener);

        mCachingNameStore = new CachingNameStoreImpl(this);

        initListAdapter();
        
        if (savedInstanceState != null) {
            mBaseUri = (Uri) savedInstanceState.getParcelable("base_uri");
            mSearchFlag = savedInstanceState.getBoolean("search_flag");
            mFilter = savedInstanceState.getString("filter");
            mQueryToken = savedInstanceState.getInt("query_token");
        }
        
        handleCreationIntent(getIntent());
    
public voidonDraftChanged(long threadId, boolean hasDraft)

        // Run notifyDataSetChanged() on the main thread.
        mQueryHandler.post(new Runnable() {
            public void run() {
                mListAdapter.notifyDataSetChanged();
            }
        });
    
protected voidonListItemClick(android.widget.ListView l, android.view.View v, int position, long id)

        if (LOCAL_LOGV) {
            Log.v(TAG, "onListItemClick: position=" + position + ", id=" + id);
        }

        if (position == 0) {
            createNewMessage();
        } else if (v instanceof ConversationHeaderView) {
            ConversationHeaderView headerView = (ConversationHeaderView) v;
            ConversationHeader ch = headerView.getConversationHeader();

            // TODO: The 'from' view of the ConversationHeader was
            // repurposed to be the cached display value, rather than
            // the old raw value, which openThread() wanted.  But it
            // turns out openThread() doesn't need it:
            // ComposeMessageActivity will load it.  That's not ideal,
            // though, as it's an SQLite query.  So fix this later to
            // save some latency on starting ComposeMessageActivity.
            String somethingDelimitedAddresses = null;
            openThread(ch.getThreadId(), somethingDelimitedAddresses);
        }
    
protected voidonNewIntent(android.content.Intent intent)

        // Handle intents that occur after the activity has already been created.
        handleCreationIntent(intent);
    
public booleanonOptionsItemSelected(android.view.MenuItem item)

        switch(item.getItemId()) {
            case MENU_COMPOSE_NEW:
                createNewMessage();
                break;
            case MENU_SEARCH:
                onSearchRequested();
                break;
            case MENU_DELETE_ALL:
                confirmDeleteDialog(new DeleteThreadListener(-1L), true);
                break;
            case MENU_PREFERENCES: {
                Intent intent = new Intent(this, MessagingPreferenceActivity.class);
                startActivityIfNeeded(intent, -1);
                break;
            }
            default:
                return true;
        }
        return false;
    
protected voidonPause()

        super.onPause();

        DraftCache.getInstance().removeOnDraftChangedListener(this);
    
public booleanonPrepareOptionsMenu(android.view.Menu menu)

        menu.clear();

        menu.add(0, MENU_COMPOSE_NEW, 0, R.string.menu_compose_new).setIcon(
                com.android.internal.R.drawable.ic_menu_compose);
        // Removed search as part of b/1205708
        //menu.add(0, MENU_SEARCH, 0, R.string.menu_search).setIcon(
        //        R.drawable.ic_menu_search).setAlphabeticShortcut(SearchManager.MENU_KEY);
        if (mListAdapter.getCount() > 0 && !mSearchFlag) {
            menu.add(0, MENU_DELETE_ALL, 0, R.string.menu_delete_all).setIcon(
                    android.R.drawable.ic_menu_delete);
        }

        menu.add(0, MENU_PREFERENCES, 0, R.string.menu_preferences).setIcon(
                android.R.drawable.ic_menu_preferences);

        return true;
    
protected voidonResume()

        super.onResume();

        DraftCache.getInstance().addOnDraftChangedListener(this);

        getContentResolver().delete(Threads.OBSOLETE_THREADS_URI, null, null);

        // Make sure the draft cache is up to date.
        DraftCache.getInstance().refresh();

        startAsyncQuery();

        // force invalidate the contact info cache, so we will query for fresh info again.
        // This is so we can get fresh presence info again on the screen, since the presence
        // info changes pretty quickly, and we can't get change notifications when presence is
        // updated in the ContactsProvider.
        ContactInfoCache.getInstance().invalidateCache();
    
protected voidonSaveInstanceState(android.os.Bundle outState)

        super.onSaveInstanceState(outState);

        outState.putParcelable("base_uri", mBaseUri);
        outState.putInt("query_token", mQueryToken);
        outState.putBoolean("search_flag", mSearchFlag);
        if (mSearchFlag) {
            outState.putString("filter", mFilter);
        }
    
protected voidonStop()

        super.onStop();

        mListAdapter.changeCursor(null);
    
private voidopenThread(long threadId, java.lang.String address)

        Intent intent = new Intent(this, ComposeMessageActivity.class);
        intent.putExtra("thread_id", threadId);
        if (!TextUtils.isEmpty(address)) {
            intent.putExtra("address", address);
        }
        startActivity(intent);
    
private voidstartAsyncQuery()

        try {
            setTitle(getString(R.string.refreshing));
            setProgressBarIndeterminateVisibility(true);

            mQueryHandler.cancelOperation(THREAD_LIST_QUERY_TOKEN);
            mQueryHandler.startQuery(THREAD_LIST_QUERY_TOKEN, null, mBaseUri,
                    mProjection, mSelection, null, Conversations.DEFAULT_SORT_ORDER);
        } catch (SQLiteException e) {
            SqliteWrapper.checkSQLiteException(this, e);
        }
    
private voidviewContact(java.lang.String address)

        // address must be a single recipient
        ContactInfoCache cache = ContactInfoCache.getInstance();
        ContactInfoCache.CacheEntry info;
        if (Mms.isEmailAddress(address)) {
            info = cache.getContactInfoForEmailAddress(getApplicationContext(), address,
                    true /* allow query */);
        } else {
            info = cache.getContactInfo(this, address);
        }
        if (info != null && info.person_id > 0) {
            Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, info.person_id);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);            
        }