Android Tutorial - Core Class : Contact
Contact Intent and Options Menu
package app.test; import java.io.File; import java.util.ArrayList; import android.app.Activity; import android.app.SearchManager; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.Contacts; import android.view.Menu; public class Test extends Activity { private Intent browserIntent, phoneIntent, mapIntent, mailIntent, contactIntent, marketIntent, smsIntent; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); contactIntent = new Intent(); contactIntent.setAction(Intent.ACTION_PICK); contactIntent.setData(Contacts.People.CONTENT_URI); } @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add("Browser").setIntent(browserIntent); menu.add("Phone").setIntent(phoneIntent); menu.add("Map").setIntent(mapIntent); menu.add("Mail").setIntent(Intent.createChooser(mailIntent, "Mail Client")); menu.add("SMS").setIntent(smsIntent); menu.add("Contacts").setIntent(contactIntent); menu.add("Market").setIntent(marketIntent); return true; } }
Using Contact
package app.test; import android.app.AlertDialog; import android.app.ListActivity; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract; import android.view.View; import android.widget.AdapterView; import android.widget.SimpleCursorAdapter; public class Test extends ListActivity implements AdapterView.OnItemClickListener { Cursor mContacts; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] projection = new String[] { ContactsContract.Contacts._ID,ContactsContract.Contacts.DISPLAY_NAME }; mContacts = managedQuery(ContactsContract.Contacts.CONTENT_URI,projection, null, null, ContactsContract.Contacts.DISPLAY_NAME); SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, mContacts, new String[] { ContactsContract.Contacts.DISPLAY_NAME }, new int[] { android.R.id.text1 }); setListAdapter(mAdapter); getListView().setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { if (mContacts.moveToPosition(position)) { int selectedId = mContacts.getInt(0); Cursor email = getContentResolver().query( ContactsContract.CommonDataKinds.Email.CONTENT_URI, new String[] { ContactsContract.CommonDataKinds.Email.DATA }, ContactsContract.Data.CONTACT_ID + " = " + selectedId, null, null); Cursor phone = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER }, ContactsContract.Data.CONTACT_ID + " = " + selectedId, null, null); Cursor address = getContentResolver().query( ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI, new String[] { ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS }, ContactsContract.Data.CONTACT_ID + " = " + selectedId, null, null); StringBuilder sb = new StringBuilder(); sb.append(email.getCount() + " Emails\n"); if (email.moveToFirst()) { do { sb.append("Email: " + email.getString(0)); } while (email.moveToNext()); } sb.append(phone.getCount() + " Phone Numbers\n"); if (phone.moveToFirst()) { do { sb.append("Phone: " + phone.getString(0)); } while (phone.moveToNext()); } sb.append(address.getCount() + " Addresses\n"); if (address.moveToFirst()) { do { sb.append("Address:\n" + address.getString(0)); } while (address.moveToNext()); } AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(mContacts.getString(1)); builder.setMessage(sb.toString()); builder.setPositiveButton("OK", null); builder.create().show(); email.close(); phone.close(); address.close(); } } }
Contact Intent
package com.commonsware.android.rotation.five; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract.Contacts; import android.view.View; import android.widget.Button; import android.util.Log; public class RotationFiveDemo extends Activity { static final int PICK_REQUEST=1337; Button viewButton=null; Uri contact=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btn=(Button)findViewById(R.id.pick); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent i=new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); startActivityForResult(i, PICK_REQUEST); } }); viewButton=(Button)findViewById(R.id.view); viewButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { startActivity(new Intent(Intent.ACTION_VIEW, contact)); } }); restoreMe(); viewButton.setEnabled(contact!=null); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode==PICK_REQUEST) { if (resultCode==RESULT_OK) { contact=data.getData(); viewButton.setEnabled(true); } } } @Override public Object onRetainNonConfigurationInstance() { return(contact); } private void restoreMe() { contact=null; if (getLastNonConfigurationInstance()!=null) { contact=(Uri)getLastNonConfigurationInstance(); } } } //res\layout\main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/pick" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:text="Pick" android:enabled="true" /> <Button android:id="@+id/view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:text="View" android:enabled="false" /> </LinearLayout> //res\layout-land\main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/pick" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:text="Pick" android:enabled="true" /> <Button android:id="@+id/view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:text="View" android:enabled="false" /> </LinearLayout>
Manage Contacts
package app.test; import android.app.ListActivity; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.util.Log; import android.widget.SimpleCursorAdapter; public class Test extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //Uri allContacts = Uri.parse("content://contacts/people"); //Uri allContacts = Uri.parse("content://contacts/people/1"); Uri allContacts = ContactsContract.Contacts.CONTENT_URI; //Uri allContacts = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, 1); String[] projection = new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER}; Cursor c = managedQuery( allContacts, projection, ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?", new String[] {"%"} , ContactsContract.Contacts.DISPLAY_NAME + " ASC"); String[] columns = new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME,}; int[] views = new int[] {R.id.contactName, R.id.contactID}; SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.main, c, columns, views); this.setListAdapter(adapter); PrintContacts(c); } private void PrintContacts(Cursor c) { if (c.moveToFirst()) { do{ String contactID = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID)); String contactDisplayName = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); Log.v("Content Providers", contactID + ", " + contactDisplayName); int hasPhone = c.getInt(c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); if (hasPhone == 1) { Cursor phoneCursor = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactID, null, null); while (phoneCursor.moveToNext()) { Log.v("Content Providers", phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); } phoneCursor.close(); } } while (c.moveToNext()); } } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/android:list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:stackFromBottom="false" android:transcriptMode="normal" /> <TextView android:id="@+id/contactName" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/contactID" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
List Contact phones
package app.test; import android.app.ListActivity; import android.database.Cursor; import android.os.Bundle; import android.provider.Contacts.Phones; import android.widget.ListAdapter; import android.widget.SimpleCursorAdapter; public class Test extends ListActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Cursor c = getContentResolver().query(Phones.CONTENT_URI, null, null, null, null); startManagingCursor(c); ListAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, c, new String[] { Phones.NAME, Phones.NUMBER }, new int[] { android.R.id.text1, android.R.id.text2 }); setListAdapter(adapter); } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
Contact list demo
package app.test; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.Contacts.People; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class Test extends Activity { public static final int PICK_CONTACT = 1; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); Button button = (Button)findViewById(R.id.pick_contact_button); button.setOnClickListener(new OnClickListener() { public void onClick(View _view) { Intent intent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts/")); startActivityForResult(intent, PICK_CONTACT); } }); } @Override public void onActivityResult(int reqCode, int resCode, Intent data) { super.onActivityResult(reqCode, resCode, data); switch(reqCode) { case (PICK_CONTACT) : { if (resCode == Activity.RESULT_OK) { Cursor c = managedQuery(data.getData(), null, null, null, null); c.moveToFirst(); String name = c.getString(c.getColumnIndexOrThrow(People.NAME)); TextView tv = (TextView)findViewById(R.id.selected_contact_textview); tv.setText(name); } break; } } } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/selected_contact_textview" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/pick_contact_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Pick Contact" /> </LinearLayout>
Contact Manager
package com.example.android.contactmanager; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorDescription; import android.accounts.OnAccountsUpdateListener; import android.app.Activity; import android.content.ContentProviderOperation; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.provider.ContactsContract; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemSelectedListener; import java.util.ArrayList; import java.util.Iterator; public final class ContactAdder extends Activity implements OnAccountsUpdateListener { public static final String TAG = "ContactsAdder"; public static final String ACCOUNT_NAME = "com.example.android.contactmanager.ContactsAdder.ACCOUNT_NAME"; public static final String ACCOUNT_TYPE = "com.example.android.contactmanager.ContactsAdder.ACCOUNT_TYPE"; private ArrayList<AccountData> mAccounts; private AccountAdapter mAccountAdapter; private Spinner mAccountSpinner; private EditText mContactEmailEditText; private ArrayList<Integer> mContactEmailTypes; private Spinner mContactEmailTypeSpinner; private EditText mContactNameEditText; private EditText mContactPhoneEditText; private ArrayList<Integer> mContactPhoneTypes; private Spinner mContactPhoneTypeSpinner; private Button mContactSaveButton; private AccountData mSelectedAccount; /** * Called when the activity is first created. Responsible for initializing the UI. */ @Override public void onCreate(Bundle savedInstanceState) { Log.v(TAG, "Activity State: onCreate()"); super.onCreate(savedInstanceState); setContentView(R.layout.contact_adder); // Obtain handles to UI objects mAccountSpinner = (Spinner) findViewById(R.id.accountSpinner); mContactNameEditText = (EditText) findViewById(R.id.contactNameEditText); mContactPhoneEditText = (EditText) findViewById(R.id.contactPhoneEditText); mContactEmailEditText = (EditText) findViewById(R.id.contactEmailEditText); mContactPhoneTypeSpinner = (Spinner) findViewById(R.id.contactPhoneTypeSpinner); mContactEmailTypeSpinner = (Spinner) findViewById(R.id.contactEmailTypeSpinner); mContactSaveButton = (Button) findViewById(R.id.contactSaveButton); // Prepare list of supported account types // Note: Other types are available in ContactsContract.CommonDataKinds // Also, be aware that type IDs differ between Phone and Email, and MUST be computed // separately. mContactPhoneTypes = new ArrayList<Integer>(); mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_HOME); mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_WORK); mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE); mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_OTHER); mContactEmailTypes = new ArrayList<Integer>(); mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_HOME); mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_WORK); mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_MOBILE); mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_OTHER); // Prepare model for account spinner mAccounts = new ArrayList<AccountData>(); mAccountAdapter = new AccountAdapter(this, mAccounts); mAccountSpinner.setAdapter(mAccountAdapter); // Populate list of account types for phone ArrayAdapter<String> adapter; adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Iterator<Integer> iter; iter = mContactPhoneTypes.iterator(); while (iter.hasNext()) { adapter.add(ContactsContract.CommonDataKinds.Phone.getTypeLabel( this.getResources(), iter.next(), getString(R.string.undefinedTypeLabel)).toString()); } mContactPhoneTypeSpinner.setAdapter(adapter); mContactPhoneTypeSpinner.setPrompt(getString(R.string.selectLabel)); // Populate list of account types for email adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); iter = mContactEmailTypes.iterator(); while (iter.hasNext()) { adapter.add(ContactsContract.CommonDataKinds.Email.getTypeLabel( this.getResources(), iter.next(), getString(R.string.undefinedTypeLabel)).toString()); } mContactEmailTypeSpinner.setAdapter(adapter); mContactEmailTypeSpinner.setPrompt(getString(R.string.selectLabel)); // Prepare the system account manager. On registering the listener below, we also ask for // an initial callback to pre-populate the account list. AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true); // Register handlers for UI elements mAccountSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView<?> parent, View view, int position, long i) { updateAccountSelection(); } public void onNothingSelected(AdapterView<?> parent) { // We don't need to worry about nothing being selected, since Spinners don't allow // this. } }); mContactSaveButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { onSaveButtonClicked(); } }); } /** * Actions for when the Save button is clicked. Creates a contact entry and terminates the * activity. */ private void onSaveButtonClicked() { Log.v(TAG, "Save button clicked"); createContactEntry(); finish(); } /** * Creates a contact entry from the current UI values in the account named by mSelectedAccount. */ protected void createContactEntry() { // Get values from UI String name = mContactNameEditText.getText().toString(); String phone = mContactPhoneEditText.getText().toString(); String email = mContactEmailEditText.getText().toString(); int phoneType = mContactPhoneTypes.get( mContactPhoneTypeSpinner.getSelectedItemPosition()); int emailType = mContactEmailTypes.get( mContactEmailTypeSpinner.getSelectedItemPosition());; // Prepare contact creation request // // Note: We use RawContacts because this data must be associated with a particular account. // The system will aggregate this with any other data for this contact and create a // coresponding entry in the ContactsContract.Contacts provider for us. ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType()) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName()) .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name) .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType) .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Email.DATA, email) .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType) .build()); // Ask the Contact provider to create a new contact Log.i(TAG,"Selected account: " + mSelectedAccount.getName() + " (" + mSelectedAccount.getType() + ")"); Log.i(TAG,"Creating contact: " + name); try { getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { // Display warning Context ctx = getApplicationContext(); CharSequence txt = getString(R.string.contactCreationFailure); int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(ctx, txt, duration); toast.show(); // Log exception Log.e(TAG, "Exceptoin encoutered while inserting contact: " + e); } } /** * Called when this activity is about to be destroyed by the system. */ @Override public void onDestroy() { // Remove AccountManager callback AccountManager.get(this).removeOnAccountsUpdatedListener(this); super.onDestroy(); } /** * Updates account list spinner when the list of Accounts on the system changes. Satisfies * OnAccountsUpdateListener implementation. */ public void onAccountsUpdated(Account[] a) { Log.i(TAG, "Account list update detected"); // Clear out any old data to prevent duplicates mAccounts.clear(); // Get account data from system AuthenticatorDescription[] accountTypes = AccountManager.get(this).getAuthenticatorTypes(); // Populate tables for (int i = 0; i < a.length; i++) { // The user may have multiple accounts with the same name, so we need to construct a // meaningful display name for each. String systemAccountType = a[i].type; AuthenticatorDescription ad = getAuthenticatorDescription(systemAccountType, accountTypes); AccountData data = new AccountData(a[i].name, ad); mAccounts.add(data); } // Update the account spinner mAccountAdapter.notifyDataSetChanged(); } /** * Obtain the AuthenticatorDescription for a given account type. * @param type The account type to locate. * @param dictionary An array of AuthenticatorDescriptions, as returned by AccountManager. * @return The description for the specified account type. */ private static AuthenticatorDescription getAuthenticatorDescription(String type, AuthenticatorDescription[] dictionary) { for (int i = 0; i < dictionary.length; i++) { if (dictionary[i].type.equals(type)) { return dictionary[i]; } } // No match found throw new RuntimeException("Unable to find matching authenticator"); } /** * Update account selection. If NO_ACCOUNT is selected, then we prohibit inserting new contacts. */ private void updateAccountSelection() { // Read current account selection mSelectedAccount = (AccountData) mAccountSpinner.getSelectedItem(); } /** * A container class used to repreresent all known information about an account. */ private class AccountData { private String mName; private String mType; private CharSequence mTypeLabel; private Drawable mIcon; /** * @param name The name of the account. This is usually the user's email address or * username. * @param description The description for this account. This will be dictated by the * type of account returned, and can be obtained from the system AccountManager. */ public AccountData(String name, AuthenticatorDescription description) { mName = name; if (description != null) { mType = description.type; // The type string is stored in a resource, so we need to convert it into something // human readable. String packageName = description.packageName; PackageManager pm = getPackageManager(); if (description.labelId != 0) { mTypeLabel = pm.getText(packageName, description.labelId, null); if (mTypeLabel == null) { throw new IllegalArgumentException("LabelID provided, but label not found"); } } else { mTypeLabel = ""; } if (description.iconId != 0) { mIcon = pm.getDrawable(packageName, description.iconId, null); if (mIcon == null) { throw new IllegalArgumentException("IconID provided, but drawable not " + "found"); } } else { mIcon = getResources().getDrawable(android.R.drawable.sym_def_app_icon); } } } public String getName() { return mName; } public String getType() { return mType; } public CharSequence getTypeLabel() { return mTypeLabel; } public Drawable getIcon() { return mIcon; } public String toString() { return mName; } } /** * Custom adapter used to display account icons and descriptions in the account spinner. */ private class AccountAdapter extends ArrayAdapter<AccountData> { public AccountAdapter(Context context, ArrayList<AccountData> accountData) { super(context, android.R.layout.simple_spinner_item, accountData); setDropDownViewResource(R.layout.account_entry); } public View getDropDownView(int position, View convertView, ViewGroup parent) { // Inflate a view template if (convertView == null) { LayoutInflater layoutInflater = getLayoutInflater(); convertView = layoutInflater.inflate(R.layout.account_entry, parent, false); } TextView firstAccountLine = (TextView) convertView.findViewById(R.id.firstAccountLine); TextView secondAccountLine = (TextView) convertView.findViewById(R.id.secondAccountLine); ImageView accountIcon = (ImageView) convertView.findViewById(R.id.accountIcon); // Populate template AccountData data = getItem(position); firstAccountLine.setText(data.getName()); secondAccountLine.setText(data.getTypeLabel()); Drawable icon = data.getIcon(); if (icon == null) { icon = getResources().getDrawable(android.R.drawable.ic_menu_search); } accountIcon.setImageDrawable(icon); return convertView; } } } //src\com\example\android\contactmanager\ContactManager.java package com.example.android.contactmanager; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ListView; import android.widget.SimpleCursorAdapter; public final class ContactManager extends Activity { public static final String TAG = "ContactManager"; private Button mAddAccountButton; private ListView mContactList; private boolean mShowInvisible; private CheckBox mShowInvisibleControl; /** * Called when the activity is first created. Responsible for initializing the UI. */ @Override public void onCreate(Bundle savedInstanceState) { Log.v(TAG, "Activity State: onCreate()"); super.onCreate(savedInstanceState); setContentView(R.layout.contact_manager); // Obtain handles to UI objects mAddAccountButton = (Button) findViewById(R.id.addContactButton); mContactList = (ListView) findViewById(R.id.contactList); mShowInvisibleControl = (CheckBox) findViewById(R.id.showInvisible); // Initialize class properties mShowInvisible = false; mShowInvisibleControl.setChecked(mShowInvisible); // Register handler for UI elements mAddAccountButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Log.d(TAG, "mAddAccountButton clicked"); launchContactAdder(); } }); mShowInvisibleControl.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { Log.d(TAG, "mShowInvisibleControl changed: " + isChecked); mShowInvisible = isChecked; populateContactList(); } }); // Populate the contact list populateContactList(); } /** * Populate the contact list based on account currently selected in the account spinner. */ private void populateContactList() { // Build adapter with contact entries Cursor cursor = getContacts(); String[] fields = new String[] { ContactsContract.Data.DISPLAY_NAME }; SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, cursor, fields, new int[] {R.id.contactEntryText}); mContactList.setAdapter(adapter); } /** * Obtains the contact list for the currently selected account. * * @return A cursor for for accessing the contact list. */ private Cursor getContacts() { // Run query Uri uri = ContactsContract.Contacts.CONTENT_URI; String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME }; String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + (mShowInvisible ? "0" : "1") + "'"; String[] selectionArgs = null; String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; return managedQuery(uri, projection, selection, selectionArgs, sortOrder); } /** * Launches the ContactAdder activity to add a new contact to the selected accont. */ protected void launchContactAdder() { Intent i = new Intent(this, ContactAdder.class); startActivity(i); } } //res\layout\account_entry.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="6dip"> <ImageView android:id="@+id/accountIcon" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentTop="true" android:layout_alignParentBottom="true" android:layout_marginRight="6dip" /> <TextView android:id="@+id/secondAccountLine" android:layout_width="match_parent" android:layout_height="26dip" android:layout_toRightOf="@id/accountIcon" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:singleLine="true" android:ellipsize="marquee" android:textColor="@android:color/secondary_text_light" /> <TextView android:id="@+id/firstAccountLine" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toRightOf="@id/accountIcon" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_above="@id/secondAccountLine" android:layout_alignWithParentIfMissing="true" android:gravity="center_vertical" android:textColor="@android:color/primary_text_light"/> </RelativeLayout> //res\layout\contact_adder.xml <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TableLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TableRow> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/targetAccountLabel"/> </TableRow> <TableRow> <Spinner android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_weight="1" android:id="@+id/accountSpinner"/> </TableRow> <TableRow> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/contactNameLabel"/> </TableRow> <TableRow> <EditText android:id="@+id/contactNameEditText" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> </TableRow> <TableRow> <TextView android:text="@string/contactPhoneLabel" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </TableRow> <TableRow> <EditText android:id="@+id/contactPhoneEditText" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Spinner android:id="@+id/contactPhoneTypeSpinner" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </TableRow> <TableRow> <TextView android:text="@string/contactEmailLabel" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </TableRow> <TableRow> <EditText android:id="@+id/contactEmailEditText" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Spinner android:id="@+id/contactEmailTypeSpinner" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </TableRow> <TableRow> <Button android:layout_height="wrap_content" android:text="@string/save" android:id="@+id/contactSaveButton" android:layout_width="match_parent" android:layout_weight="1"/> </TableRow> </TableLayout> </ScrollView> //res\layout\contact_entry.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:text="@+id/contactEntryText" android:id="@+id/contactEntryText" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> //res\layout\contact_manager.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:layout_width="match_parent" android:id="@+id/contactList" android:layout_height="wrap_content" android:layout_weight="1"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/showInvisible" android:text="@string/showInvisible"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/addContactButton" android:text="@string/addContactButtonLabel"/> </LinearLayout> //res\values\strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="accountSpinnerLabel">Account</string> <string name="addContactButtonLabel">Add Contact</string> <string name="addContactTitle">Add Contact</string> <string name="allAccounts">All Accounts</string> <string name="app_name">Contact Manager</string> <string name="contactCreationFailure">Contact creation failed, check logs.</string> <string name="contactEmailLabel">Contact Email</string> <string name="contactNameLabel">Contact Name</string> <string name="contactPhoneLabel">Contact Phone</string> <string name="save">Save</string> <string name="selectAccountLabel">Select</string> <string name="selectLabel">Select label</string> <string name="showInvisible">Show Invisible Contacts (Only)</string> <string name="targetAccountLabel">Target Account</string> <string name="undefinedTypeLabel">(Undefined)</string> </resources>
Contacts Demo
package app.test; import android.app.ListActivity; import android.content.Context; import android.database.CharArrayBuffer; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract.Contacts; import android.view.View; import android.view.ViewGroup; import android.widget.QuickContactBadge; import android.widget.ResourceCursorAdapter; import android.widget.TextView; public class Test extends ListActivity { static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, // 0 Contacts.DISPLAY_NAME, // 1 Contacts.STARRED, // 2 Contacts.TIMES_CONTACTED, // 3 Contacts.CONTACT_PRESENCE, // 4 Contacts.PHOTO_ID, // 5 Contacts.LOOKUP_KEY, // 6 Contacts.HAS_PHONE_NUMBER, // 7 }; static final int SUMMARY_ID_COLUMN_INDEX = 0; static final int SUMMARY_NAME_COLUMN_INDEX = 1; static final int SUMMARY_STARRED_COLUMN_INDEX = 2; static final int SUMMARY_TIMES_CONTACTED_COLUMN_INDEX = 3; static final int SUMMARY_PRESENCE_STATUS_COLUMN_INDEX = 4; static final int SUMMARY_PHOTO_ID_COLUMN_INDEX = 5; static final int SUMMARY_LOOKUP_KEY = 6; static final int SUMMARY_HAS_PHONE_COLUMN_INDEX = 7; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + " != '' ))"; Cursor c = getContentResolver().query(Contacts.CONTENT_URI, CONTACTS_SUMMARY_PROJECTION, select, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); startManagingCursor(c); ContactListItemAdapter adapter = new ContactListItemAdapter(this, R.layout.main, c); setListAdapter(adapter); } private final class ContactListItemAdapter extends ResourceCursorAdapter { public ContactListItemAdapter(Context context, int layout, Cursor c) { super(context, layout, c); } @Override public void bindView(View view, Context context, Cursor cursor) { final ContactListItemCache cache = (ContactListItemCache) view.getTag(); // Set the name cursor.copyStringToBuffer(SUMMARY_NAME_COLUMN_INDEX, cache.nameBuffer); int size = cache.nameBuffer.sizeCopied; cache.nameView.setText(cache.nameBuffer.data, 0, size); final long contactId = cursor.getLong(SUMMARY_ID_COLUMN_INDEX); final String lookupKey = cursor.getString(SUMMARY_LOOKUP_KEY); cache.photoView.assignContactUri(Contacts.getLookupUri(contactId, lookupKey)); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = super.newView(context, cursor, parent); ContactListItemCache cache = new ContactListItemCache(); cache.nameView = (TextView) view.findViewById(R.id.name); cache.photoView = (QuickContactBadge) view.findViewById(R.id.badge); view.setTag(cache); return view; } } final static class ContactListItemCache { public TextView nameView; public QuickContactBadge photoView; public CharArrayBuffer nameBuffer = new CharArrayBuffer(128); } } //main.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:paddingLeft="0dip" android:paddingRight="9dip" android:layout_height= "wrap_content" android:minHeight="48dip"> <QuickContactBadge android:id="@+id/badge" android:layout_marginLeft="2dip" android:layout_marginRight="14dip" android:layout_marginTop="4dip" android:layout_marginBottom="3dip" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_height= "wrap_content" android:layout_width= "wrap_content" android:src="@drawable/icon" style="?android:attr/quickContactBadgeStyleWindowSmall" /> <TextView android:id="@+id/name" android:textAppearance="?android:attr/textAppearanceMedium" android:paddingLeft="2dip" android:layout_centerVertical="true" android:layout_toRightOf="@id/badge" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout>
Demonstrates launching the contacts app to pick a contact.
package app.test; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.SystemClock; import android.os.Bundle; import android.provider.BaseColumns; import android.provider.ContactsContract; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import java.util.Calendar; public class PickContact extends Activity { Toast mToast; ResultDisplayer mPendingResult; class ResultDisplayer implements OnClickListener { String mMsg; String mMimeType; ResultDisplayer(String msg, String mimeType) { mMsg = msg; mMimeType = mimeType; } public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType(mMimeType); mPendingResult = this; startActivityForResult(intent, 1); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Watch for button clicks. ((Button)findViewById(R.id.pick_contact)).setOnClickListener( new ResultDisplayer("Selected contact", ContactsContract.Contacts.CONTENT_ITEM_TYPE)); ((Button)findViewById(R.id.pick_person)).setOnClickListener( new ResultDisplayer("Selected person", "vnd.android.cursor.item/person")); ((Button)findViewById(R.id.pick_phone)).setOnClickListener( new ResultDisplayer("Selected phone", ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)); ((Button)findViewById(R.id.pick_address)).setOnClickListener( new ResultDisplayer("Selected address", ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { Uri uri = data.getData(); if (uri != null) { Cursor c = null; try { c = getContentResolver().query(uri, new String[] { BaseColumns._ID }, null, null, null); if (c != null && c.moveToFirst()) { int id = c.getInt(0); if (mToast != null) { mToast.cancel(); } String txt = mPendingResult.mMsg + ":\n" + uri + "\nid: " + id; mToast = Toast.makeText(this, txt, Toast.LENGTH_LONG); mToast.show(); } } finally { if (c != null) { c.close(); } } } } } } //main.xml <?xml version="1.0" encoding="utf-8"?> <!-- Demonstrates selecting various types of contact data. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip" android:gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0" android:paddingBottom="4dip" android:text="pick_contact_msg"/> <Button android:id="@+id/pick_contact" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="pick_contact"> <requestFocus /> </Button> <Button android:id="@+id/pick_person" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="pick_person"> </Button> <Button android:id="@+id/pick_phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="pick_phone"> </Button> <Button android:id="@+id/pick_address" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="pick_address"> </Button> </LinearLayout>