1page.title=Modifying Contacts Using Intents 2trainingnavtop=true 3@jd:body 4<div id="tb-wrapper"> 5<div id="tb"> 6 7<!-- table of contents --> 8<h2>This lesson teaches you to</h2> 9<ol> 10 <li><a href="#InsertContact">Insert a New Contact Using an Intent</a></li> 11 <li><a href="#EditContact">Edit an Existing Contact Using an Intent</a></li> 12 <li><a href="#InsertEdit">Let Users Choose to Insert or Edit Using an Intent</a> 13</ol> 14<h2>You should also read</h2> 15<ul> 16 <li> 17 <a href="{@docRoot}guide/topics/providers/content-provider-basics.html"> 18 Content Provider Basics 19 </a> 20 </li> 21 <li> 22 <a href="{@docRoot}guide/topics/providers/contacts-provider.html"> 23 Contacts Provider 24 </a> 25 </li> 26 <li> 27 <a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a> 28 </li> 29</ul> 30 31<h2>Try it out</h2> 32 33<div class="download-box"> 34 <a href="http://developer.android.com/shareables/training/ContactsList.zip" class="button"> 35 Download the sample 36 </a> 37 <p class="filename">ContactsList.zip</p> 38</div> 39 40</div> 41</div> 42<p> 43 This lesson shows you how to use an {@link android.content.Intent} to insert a new contact or 44 modify a contact's data. Instead of accessing the Contacts Provider directly, an 45 {@link android.content.Intent} starts the contacts app, which runs the appropriate 46 {@link android.app.Activity}. For the modification actions described in this lesson, 47 if you send extended data in the {@link android.content.Intent} it's entered into the UI of the 48 {@link android.app.Activity} that is started. 49</p> 50<p> 51 Using an {@link android.content.Intent} to insert or update a single contact is the preferred 52 way of modifying the Contacts Provider, for the following reasons: 53</p> 54<ul> 55 <li>It saves you the time and and effort of developing your own UI and code.</li> 56 <li> 57 It avoids introducing errors caused by modifications that don't follow the 58 Contacts Provider's rules. 59 </li> 60 <li> 61 It reduces the number of permissions you need to request. Your app doesn't need permission 62 to write to the Contacts Provider, because it delegates modifications to the contacts app, 63 which already has that permission. 64 </li> 65</ul> 66<h2 id="InsertContact">Insert a New Contact Using an Intent</h2> 67<p> 68 You often want to allow the user to insert a new contact when your app receives new data. For 69 example, a restaurant review app can allow users to add the restaurant as a contact as they're 70 reviewing it. To do this using an intent, create the intent using as much data as you have 71 available, and then send the intent to the contacts app. 72</p> 73<p> 74 Inserting a contact using the contacts app inserts a new <em>raw</em> contact into the Contacts 75 Provider's {@link android.provider.ContactsContract.RawContacts} table. If necessary, 76 the contacts app prompts users for the account type and account to use when creating the raw 77 contact. The contacts app also notifies users if the raw contact already exists. Users then have 78 option of canceling the insertion, in which case no contact is created. To learn 79 more about raw contacts, see the 80 <a href="{@docRoot}guide/topics/providers/contacts-provider.html">Contacts Provider</a> 81 API guide. 82</p> 83 84<h3>Create an Intent</h3> 85<p> 86 To start, create a new {@link android.content.Intent} object with the action 87 {@link android.provider.ContactsContract.Intents.Insert#ACTION Intents.Insert.ACTION}. 88 Set the MIME type to {@link android.provider.ContactsContract.RawContacts#CONTENT_TYPE 89 RawContacts.CONTENT_TYPE}. For example: 90</p> 91<pre> 92... 93// Creates a new Intent to insert a contact 94Intent intent = new Intent(Intents.Insert.ACTION); 95// Sets the MIME type to match the Contacts Provider 96intent.setType(ContactsContract.RawContacts.CONTENT_TYPE); 97</pre> 98<p> 99 If you already have details for the contact, such as a phone number or email address, you can 100 insert them into the intent as extended data. For a key value, use the appropriate constant from 101 {@link android.provider.ContactsContract.Intents.Insert Intents.Insert}. The contacts app 102 displays the data in its insert screen, allowing users to make further edits and additions. 103</p> 104<pre> 105/* Assumes EditText fields in your UI contain an email address 106 * and a phone number. 107 * 108 */ 109private EditText mEmailAddress = (EditText) findViewById(R.id.email); 110private EditText mPhoneNumber = (EditText) findViewById(R.id.phone); 111... 112/* 113 * Inserts new data into the Intent. This data is passed to the 114 * contacts app's Insert screen 115 */ 116// Inserts an email address 117intent.putExtra(Intents.Insert.EMAIL, mEmailAddress.getText()) 118/* 119 * In this example, sets the email type to be a work email. 120 * You can set other email types as necessary. 121 */ 122 .putExtra(Intents.Insert.EMAIL_TYPE, CommonDataKinds.Email.TYPE_WORK) 123// Inserts a phone number 124 .putExtra(Intents.Insert.PHONE, mPhoneNumber.getText()) 125/* 126 * In this example, sets the phone type to be a work phone. 127 * You can set other phone types as necessary. 128 */ 129 .putExtra(Intents.Insert.PHONE_TYPE, Phone.TYPE_WORK); 130 131</pre> 132<p> 133 Once you've created the {@link android.content.Intent}, send it by calling 134 {@link android.support.v4.app.Fragment#startActivity startActivity()}. 135</p> 136<pre> 137 /* Sends the Intent 138 */ 139 startActivity(intent); 140</pre> 141<p> 142 This call opens a screen in the contacts app that allows users to enter a new contact. The 143 account type and account name for the contact is listed at the top of the screen. Once users 144 enter the data and click <i>Done</i>, the contacts app's contact list appears. Users return to 145 your app by clicking <i>Back</i>. 146</p> 147<h2 id="EditContact">Edit an Existing Contact Using an Intent</h2> 148<p> 149 Editing an existing contact using an {@link android.content.Intent} is useful if the user 150 has already chosen a contact of interest. For example, an app that finds contacts that have 151 postal addresses but lack a postal code could give users the option of looking up the code and 152 then adding it to the contact. 153</p> 154<p> 155 To edit an existing contact using an intent, use a procedure similar to 156 inserting a contact. Create an intent as described in the section 157 <a href="#InsertContact">Insert a New Contact Using an Intent</a>, but add the contact's 158 {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI 159 Contacts.CONTENT_LOOKUP_URI} and the MIME type 160 {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE 161 Contacts.CONTENT_ITEM_TYPE} to the intent. If you want to edit the contact with details you 162 already have, you can put them in the intent's extended data. Notice that some 163 name columns can't be edited using an intent; these columns are listed in the summary 164 section of the API reference for the class {@link android.provider.ContactsContract.Contacts} 165 under the heading "Update". 166</p> 167<p> 168 Finally, send the intent. In response, the contacts app displays an edit screen. When the user 169 finishes editing and saves the edits, the contacts app displays a contact list. When the user 170 clicks <i>Back</i>, your app is displayed. 171</p> 172<div class="sidebox-wrapper"> 173<div class="sidebox"> 174 <h2>Contacts Lookup Key</h2> 175 <p> 176 A contact's {@link android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} value is 177 the identifier that you should use to retrieve a contact. It remains constant, 178 even if the provider changes the contact's row ID to handle internal operations. 179 </p> 180</div> 181</div> 182<h3>Create the Intent</h3> 183<p> 184 To edit a contact, call {@link android.content.Intent#Intent Intent(action)} to 185 create an intent with the action {@link android.content.Intent#ACTION_EDIT}. Call 186 {@link android.content.Intent#setDataAndType setDataAndType()} to set the data value for the 187 intent to the contact's {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI 188 Contacts.CONTENT_LOOKUP_URI} and the MIME type to 189 {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE 190 Contacts.CONTENT_ITEM_TYPE} MIME type; because a call to 191 {@link android.content.Intent#setType setType()} overwrites the current data value for the 192 {@link android.content.Intent}, you must set the data and the MIME type at the same time. 193</p> 194<p> 195 To get a contact's {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI 196 Contacts.CONTENT_LOOKUP_URI}, call 197 {@link android.provider.ContactsContract.Contacts#getLookupUri 198 Contacts.getLookupUri(id, lookupkey)} with the contact's 199 {@link android.provider.ContactsContract.Contacts#_ID Contacts._ID} and 200 {@link android.provider.ContactsContract.Contacts#LOOKUP_KEY Contacts.LOOKUP_KEY} values as 201 arguments. 202</p> 203<p> 204 The following snippet shows you how to create an intent: 205</p> 206<pre> 207 // The Cursor that contains the Contact row 208 public Cursor mCursor; 209 // The index of the lookup key column in the cursor 210 public int mLookupKeyIndex; 211 // The index of the contact's _ID value 212 public int mIdIndex; 213 // The lookup key from the Cursor 214 public String mCurrentLookupKey; 215 // The _ID value from the Cursor 216 public long mCurrentId; 217 // A content URI pointing to the contact 218 Uri mSelectedContactUri; 219 ... 220 /* 221 * Once the user has selected a contact to edit, 222 * this gets the contact's lookup key and _ID values from the 223 * cursor and creates the necessary URI. 224 */ 225 // Gets the lookup key column index 226 mLookupKeyIndex = mCursor.getColumnIndex(Contacts.LOOKUP_KEY); 227 // Gets the lookup key value 228 mCurrentLookupKey = mCursor.getString(mLookupKeyIndex); 229 // Gets the _ID column index 230 mIdIndex = mCursor.getColumnIndex(Contacts._ID); 231 mCurrentId = mCursor.getLong(mIdIndex); 232 mSelectedContactUri = 233 Contacts.getLookupUri(mCurrentId, mCurrentLookupKey); 234 ... 235 // Creates a new Intent to edit a contact 236 Intent editIntent = new Intent(Intent.ACTION_EDIT); 237 /* 238 * Sets the contact URI to edit, and the data type that the 239 * Intent must match 240 */ 241 editIntent.setDataAndType(mSelectedContactUri,Contacts.CONTENT_ITEM_TYPE); 242</pre> 243<h3>Add the navigation flag</h3> 244<p> 245 In Android 4.0 (API version 14) and later, a problem in the contacts app causes incorrect 246 navigation. When your app sends an edit intent to the contacts app, and users edit and save a 247 contact, when they click <i>Back</i> they see the contacts list screen. To navigate back to 248 your app, they have to click <i>Recents</i> and choose your app. 249</p> 250<p> 251 To work around this problem in Android 4.0.3 (API version 15) and later, add the extended 252 data key {@code finishActivityOnSaveCompleted} to the intent, with a value of {@code true}. 253 Android versions prior to Android 4.0 accept this key, but it has no effect. To set the 254 extended data, do the following: 255</p> 256<pre> 257 // Sets the special extended data for navigation 258 editIntent.putExtra("finishActivityOnSaveCompleted", true); 259</pre> 260<h3>Add other extended data</h3> 261<p> 262 To add additional extended data to the {@link android.content.Intent}, call 263 {@link android.content.Intent#putExtra putExtra()} as desired. 264 You can add extended data for common contact fields by using the key values specified in 265 {@link android.provider.ContactsContract.Intents.Insert Intents.Insert}. Remember that some 266 columns in the {@link android.provider.ContactsContract.Contacts} table can't be modified. 267 These columns are listed in the summary section of the API reference for the class 268 {@link android.provider.ContactsContract.Contacts} under the heading "Update". 269</p> 270 271<h3>Send the Intent</h3> 272<p> 273 Finally, send the intent you've constructed. For example: 274</p> 275<pre> 276 // Sends the Intent 277 startActivity(editIntent); 278</pre> 279<h2 id="InsertEdit">Let Users Choose to Insert or Edit Using an Intent</h2> 280<p> 281 You can allow users to choose whether to insert a contact or edit an existing one by sending 282 an {@link android.content.Intent} with the action 283 {@link android.content.Intent#ACTION_INSERT_OR_EDIT}. For example, an email client app could 284 allow users to add an incoming email address to a new contact, or add it as an additional 285 address for an existing contact. Set the MIME type for this intent to 286 {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE Contacts.CONTENT_ITEM_TYPE}, 287 but don't set the data URI. 288</p> 289<p> 290 When you send this intent, the contacts app displays a list of contacts. 291 Users can either insert a new contact or pick an existing contact and edit it. 292 Any extended data fields you add to the intent populates the screen that appears. You can use 293 any of the key values specified in {@link android.provider.ContactsContract.Intents.Insert 294 Intents.Insert}. The following code snippet shows how to construct and send the intent: 295</p> 296<pre> 297 // Creates a new Intent to insert or edit a contact 298 Intent intentInsertEdit = new Intent(Intent.ACTION_INSERT_OR_EDIT); 299 // Sets the MIME type 300 intentInsertEdit.setType(Contacts.CONTENT_ITEM_TYPE); 301 // Add code here to insert extended data, if desired 302 ... 303 // Sends the Intent with an request ID 304 startActivity(intentInsertEdit); 305</pre> 306