Home | History | Annotate | Download | only in contacts-provider
      1 page.title=Modifying Contacts Using Intents
      2 trainingnavtop=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
     94 Intent intent = new Intent(Intents.Insert.ACTION);
     95 // Sets the MIME type to match the Contacts Provider
     96 intent.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  */
    109 private EditText mEmailAddress = (EditText) findViewById(R.id.email);
    110 private 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
    117 intent.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