שינוי אנשי קשר באמצעות כוונות

בשיעור הזה נסביר איך להשתמש ב-Intent כדי להוסיף איש קשר חדש או לשנות את הנתונים של איש קשר קיים. במקום לגשת ישירות לניהול אנשי הקשר, Intent מפעילה את אפליקציית "אנשי קשר", שמריצה את ה-Activity המתאים. בפעולות השינוי שמתוארות בשיעור הזה, אם שולחים נתונים מורחבים ב-Intent, הם מוזנים בממשק המשתמש של ה-Activity שמופעל.

השימוש ב-Intent כדי להוסיף או לעדכן איש קשר יחיד הוא הדרך המועדפת לשינוי של ניהול אנשי הקשר, מהסיבות הבאות:

  • הוא חוסך לכם את הזמן והמאמץ הכרוכים בפיתוח ממשק משתמש וקוד משלכם.
  • כך נמנעות שגיאות שנגרמות כתוצאה משינויים שלא תואמים לכללים של ספק אנשי הקשר.
  • הוא מצמצם את מספר ההרשאות שצריך לבקש. לאפליקציה לא נדרשת הרשאה לכתוב לניהול אנשי הקשר, כי היא מקצה שינויים לאפליקציית אנשי הקשר, שכבר יש לה את ההרשאה הזו.

הוספת איש קשר חדש באמצעות Intent

במקרים רבים, כשהאפליקציה מקבלת נתונים חדשים, אתם רוצים לאפשר למשתמש להוסיף איש קשר חדש. לדוגמה, אפליקציה לביקורת על מסעדות יכולה לאפשר למשתמשים להוסיף את המסעדה כאיש קשר בזמן שהם כותבים עליה ביקורת. כדי לעשות את זה באמצעות Intent, יוצרים את ה-Intent עם כמה שיותר נתונים זמינים, ואז שולחים את ה-Intent לאפליקציית אנשי הקשר.

כשמוסיפים איש קשר באמצעות אפליקציית אנשי הקשר, נוספים נתונים גולמיים של איש קשר חדש לטבלה ContactsContract.RawContacts של ספק אנשי הקשר. אם צריך, אפליקציית אנשי הקשר מבקשת מהמשתמשים לבחור את סוג החשבון ואת החשבון שבו הם רוצים להשתמש כדי ליצור את הנתונים הגולמיים של איש הקשר. אפליקציית "אנשי קשר" גם מודיעה למשתמשים אם הנתונים הגולמיים של איש הקשר כבר קיימים. למשתמשים יש אפשרות לבטל את ההוספה, ובמקרה כזה לא נוצר איש קשר. מידע נוסף על נתונים גולמיים של אנשי קשר זמין במדריך ל-API של ניהול אנשי הקשר.

יצירת כוונה

כדי להתחיל, יוצרים אובייקט Intent חדש עם הפעולה Intents.Insert.ACTION. מגדירים את סוג ה-MIME בתור RawContacts.CONTENT_TYPE. לדוגמה:

Kotlin

...
// Creates a new Intent to insert a contact
val intent = Intent(ContactsContract.Intents.Insert.ACTION).apply {
    // Sets the MIME type to match the Contacts Provider
    type = ContactsContract.RawContacts.CONTENT_TYPE
}

Java

...
// Creates a new Intent to insert a contact
Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
// Sets the MIME type to match the Contacts Provider
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);

אם כבר יש לכם פרטים של איש הקשר, כמו מספר טלפון או כתובת אימייל, אתם יכולים להוסיף אותם ל-Intent כנתונים מורחבים. כדי להגדיר ערך מפתח, משתמשים בקבוע המתאים מ-Intents.Insert. אפליקציית אנשי הקשר מציגה את הנתונים במסך ההוספה שלה, והמשתמשים יכולים לבצע עריכות ותוספות נוספות.

Kotlin

private var emailAddress: EditText? = null
private var phoneNumber: EditText? = null
...
/* Assumes EditText fields in your UI contain an email address
 * and a phone number.
 *
 */
emailAddress = findViewById(R.id.email)
phoneNumber = findViewById(R.id.phone)
...
/*
 * Inserts new data into the Intent. This data is passed to the
 * contacts app's Insert screen
 */
intent.apply {
    // Inserts an email address
    putExtra(ContactsContract.Intents.Insert.EMAIL, emailAddress?.text)
    /*
     * In this example, sets the email type to be a work email.
     * You can set other email types as necessary.
     */
    putExtra(
            ContactsContract.Intents.Insert.EMAIL_TYPE,
            ContactsContract.CommonDataKinds.Email.TYPE_WORK
    )
    // Inserts a phone number
    putExtra(ContactsContract.Intents.Insert.PHONE, phoneNumber?.text)
    /*
     * In this example, sets the phone type to be a work phone.
     * You can set other phone types as necessary.
     */
    putExtra(
            ContactsContract.Intents.Insert.PHONE_TYPE,
            ContactsContract.CommonDataKinds.Phone.TYPE_WORK
    )
}

Java

private EditText emailAddress = null;
private EditText phoneNumber = null;
...
/* Assumes EditText fields in your UI contain an email address
 * and a phone number.
 *
 */
emailAddress = (EditText) findViewById(R.id.email);
phoneNumber = (EditText) findViewById(R.id.phone);
...
/*
 * Inserts new data into the Intent. This data is passed to the
 * contacts app's Insert screen
 */
// Inserts an email address
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, emailAddress.getText())
/*
 * In this example, sets the email type to be a work email.
 * You can set other email types as necessary.
 */
      .putExtra(ContactsContract.Intents.Insert.EMAIL_TYPE,
            ContactsContract.CommonDataKinds.Email.TYPE_WORK)
// Inserts a phone number
      .putExtra(ContactsContract.Intents.Insert.PHONE, phoneNumber.getText())
/*
 * In this example, sets the phone type to be a work phone.
 * You can set other phone types as necessary.
 */
      .putExtra(ContactsContract.Intents.Insert.PHONE_TYPE,
            ContactsContract.CommonDataKinds.Phone.TYPE_WORK);

אחרי שיוצרים את ה-Intent, שולחים אותו באמצעות קריאה ל-startActivity().

Kotlin

    /* Sends the Intent
     */
    startActivity(intent)

Java

    /* Sends the Intent
     */
    startActivity(intent);

הקריאה הזו פותחת מסך באפליקציית אנשי הקשר שמאפשר למשתמשים להזין איש קשר חדש. סוג החשבון ושם החשבון של איש הקשר מופיעים בחלק העליון של המסך. אחרי שהמשתמשים מזינים את הנתונים ולוחצים על סיום, מופיעה רשימת אנשי הקשר של אפליקציית אנשי הקשר. המשתמשים לוחצים על הקודם כדי לחזור לאפליקציה.

עריכת איש קשר קיים באמצעות Intent

עריכת איש קשר קיים באמצעות Intent שימושית אם המשתמש כבר בחר איש קשר רלוונטי. לדוגמה, אפליקציה שמוצאת אנשי קשר שיש להם כתובות דואר אבל אין להם מיקוד, יכולה לתת למשתמשים אפשרות לחפש את המיקוד ולהוסיף אותו לאיש הקשר.

כדי לערוך איש קשר קיים באמצעות Intent, משתמשים בהליך דומה להוספת איש קשר. יוצרים Intent כמו שמתואר בקטע הוספת איש קשר חדש באמצעות Intent, אבל מוסיפים ל-Intent את ה-Contacts.CONTENT_LOOKUP_URI של איש הקשר ואת סוג ה-MIME‏ Contacts.CONTENT_ITEM_TYPE. אם רוצים לערוך את איש הקשר עם פרטים שכבר יש, אפשר להוסיף אותם לנתונים המורחבים של ה-Intent. שימו לב שאי אפשר לערוך חלק מעמודות השמות באמצעות Intent. העמודות האלה מפורטות בקטע הסיכום של מאמרי העזרה של ה-API למחלקה ContactsContract.Contacts, בכותרת Update.

בסיום, שולחים את ה-Intent. בתגובה, אפליקציית אנשי הקשר מציגה מסך עריכה. כשהמשתמש מסיים לערוך ושומר את השינויים, אפליקציית אנשי הקשר מציגה רשימת אנשי קשר. כשהמשתמש לוחץ על חזרה, האפליקציה מוצגת.

יצירת ה-intent

כדי לערוך איש קשר, צריך להפעיל את Intent(action) כדי ליצור Intent עם הפעולה ACTION_EDIT. מפעילים את setDataAndType() כדי להגדיר את ערך הנתונים של ה-Intent ל-Contacts.CONTENT_LOOKUP_URI של איש הקשר ואת סוג ה-MIME לסוג ה-MIME של Contacts.CONTENT_ITEM_TYPE. מכיוון שהפעלת setType() מחליפה את ערך הנתונים הנוכחי של Intent, צריך להגדיר את הנתונים ואת סוג ה-MIME בו-זמנית.

כדי לקבל את Contacts.CONTENT_LOOKUP_URI של איש קשר, מפעילים את הפונקציה Contacts.getLookupUri(id, lookupkey) עם הערכים Contacts._ID ו-Contacts.LOOKUP_KEY של איש הקשר כארגומנטים.

הערה: הערך של LOOKUP_KEY של איש קשר הוא המזהה שבו צריך להשתמש כדי לאחזר איש קשר. הוא נשאר קבוע, גם אם הספק משנה את מזהה השורה של איש הקשר כדי לטפל בפעולות פנימיות.

בקטע הקוד הבא אפשר לראות איך יוצרים Intent:

Kotlin

    // The Cursor that contains the Contact row
    var mCursor: Cursor? = null
    // The index of the lookup key column in the cursor
    var lookupKeyIndex: Int = 0
    // The index of the contact's _ID value
    var idIndex: Int = 0
    // The lookup key from the Cursor
    var currentLookupKey: String? = null
    // The _ID value from the Cursor
    var currentId: Long = 0
    // A content URI pointing to the contact
    var selectedContactUri: Uri? = null
    ...
    /*
     * Once the user has selected a contact to edit,
     * this gets the contact's lookup key and _ID values from the
     * cursor and creates the necessary URI.
     */
    mCursor?.apply {
        // Gets the lookup key column index
        lookupKeyIndex = getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)
        // Gets the lookup key value
        currentLookupKey = getString(lookupKeyIndex)
        // Gets the _ID column index
        idIndex = getColumnIndex(ContactsContract.Contacts._ID)
        currentId = getLong(idIndex)
        selectedContactUri = ContactsContract.Contacts.getLookupUri(currentId, mCurrentLookupKey)
    }

    // Creates a new Intent to edit a contact
    val editIntent = Intent(Intent.ACTION_EDIT).apply {
        /*
         * Sets the contact URI to edit, and the data type that the
         * Intent must match
         */
        setDataAndType(selectedContactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE)
    }

Java

    // The Cursor that contains the Contact row
    public Cursor mCursor;
    // The index of the lookup key column in the cursor
    public int lookupKeyIndex;
    // The index of the contact's _ID value
    public int idIndex;
    // The lookup key from the Cursor
    public String currentLookupKey;
    // The _ID value from the Cursor
    public long currentId;
    // A content URI pointing to the contact
    Uri selectedContactUri;
    ...
    /*
     * Once the user has selected a contact to edit,
     * this gets the contact's lookup key and _ID values from the
     * cursor and creates the necessary URI.
     */
    // Gets the lookup key column index
    lookupKeyIndex = mCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY);
    // Gets the lookup key value
    currentLookupKey = mCursor.getString(lookupKeyIndex);
    // Gets the _ID column index
    idIndex = mCursor.getColumnIndex(ContactsContract.Contacts._ID);
    currentId = mCursor.getLong(idIndex);
    selectedContactUri =
            Contacts.getLookupUri(currentId, mCurrentLookupKey);
    ...
    // Creates a new Intent to edit a contact
    Intent editIntent = new Intent(Intent.ACTION_EDIT);
    /*
     * Sets the contact URI to edit, and the data type that the
     * Intent must match
     */
    editIntent.setDataAndType(selectedContactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);

הוספת דגל הניווט

ב-Android מגרסה 4.0 (גרסת API‏ 14) ואילך, בעיה באפליקציית אנשי הקשר גורמת לניווט שגוי. כשהאפליקציה שולחת Intent של עריכה לאפליקציית אנשי הקשר, והמשתמשים עורכים ושומרים איש קשר, כשהם לוחצים על חזרה הם רואים את מסך רשימת אנשי הקשר. כדי לחזור לאפליקציה, הם צריכים ללחוץ על אפליקציות אחרונות ולבחור את האפליקציה.

כדי לעקוף את הבעיה הזו ב-Android 4.0.3 (גרסת API ‏15) ואילך, מוסיפים את מפתח הנתונים המורחב finishActivityOnSaveCompleted ל-Intent, עם הערך true. גרסאות Android שקודמות ל-Android 4.0 מקבלות את המפתח הזה, אבל אין לו השפעה. כדי להגדיר את הנתונים המורחבים:

Kotlin

    // Sets the special extended data for navigation
    editIntent.putExtra("finishActivityOnSaveCompleted", true)

Java

    // Sets the special extended data for navigation
    editIntent.putExtra("finishActivityOnSaveCompleted", true);

הוספת נתונים מורחבים אחרים

כדי להוסיף עוד נתונים מורחבים אל Intent, צריך להפעיל את putExtra() לפי הצורך. אפשר להוסיף נתונים מורחבים לשדות נפוצים של אנשי קשר באמצעות ערכי המפתחות שצוינו ב-Intents.Insert. חשוב לזכור שאי אפשר לשנות חלק מהעמודות בטבלה ContactsContract.Contacts. העמודות האלה מפורטות בקטע הסיכום של מאמרי העזרה של ה-API למחלקה ContactsContract.Contacts, בכותרת Update.

שליחת ה-intent

בסיום, שולחים את ה-Intent שיצרתם. לדוגמה:

Kotlin

    // Sends the Intent
    startActivity(editIntent)

Java

    // Sends the Intent
    startActivity(editIntent);

המשתמשים יכולים לבחור להוסיף או לערוך באמצעות כוונה

אתם יכולים לאפשר למשתמשים לבחור אם להוסיף איש קשר או לערוך איש קשר קיים על ידי שליחת Intent עם הפעולה ACTION_INSERT_OR_EDIT. לדוגמה, אפליקציה של תוכנת אימייל יכולה לאפשר למשתמשים להוסיף כתובת אימייל נכנסת לאיש קשר חדש, או להוסיף אותה ככתובת נוספת לאיש קשר קיים. מגדירים את סוג ה-MIME של ה-Intent הזה בתור Contacts.CONTENT_ITEM_TYPE, אבל לא מגדירים את ה-URI של הנתונים.

כששולחים את ה-Intent הזה, אפליקציית אנשי הקשר מציגה רשימה של אנשי קשר. המשתמשים יכולים להוסיף איש קשר חדש או לבחור איש קשר קיים ולערוך אותו. כל שדות הנתונים המורחבים שתוסיפו ל-Intent יאכלסו את המסך שיופיע. אפשר להשתמש בכל אחד מהערכים של המפתחות שצוינו ב-Intents.Insert. בקטע הקוד הבא מוצג איך ליצור ולשלוח את ה-Intent:

Kotlin

    // Creates a new Intent to insert or edit a contact
    val intentInsertEdit = Intent(Intent.ACTION_INSERT_OR_EDIT).apply {
        // Sets the MIME type
        type = ContactsContract.Contacts.CONTENT_ITEM_TYPE
    }
    // Add code here to insert extended data, if desired

    // Sends the Intent with an request ID
    startActivity(intentInsertEdit)

Java

    // Creates a new Intent to insert or edit a contact
    Intent intentInsertEdit = new Intent(Intent.ACTION_INSERT_OR_EDIT);
    // Sets the MIME type
    intentInsertEdit.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
    // Add code here to insert extended data, if desired
    ...
    // Sends the Intent with an request ID
    startActivity(intentInsertEdit);