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

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

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

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

הוספת איש קשר חדש לפי כוונת רכישה

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

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

יצירת Intent

כדי להתחיל, צריך ליצור אובייקט 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);

אם כבר יש לכם פרטים של איש הקשר, כמו מספר טלפון או כתובת אימייל, תוכלו להוסיף אותם לכוונה כנתונים מורחבים. לערך מפתח, משתמשים בערך הקבוע המתאים מ-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 מועילה אם המשתמש כבר בחר איש קשר מעניין. לדוגמה, אפליקציה שמוצאת אנשי קשר בכתובות דואר אבל ללא מיקוד, המשתמשים יכולים לחפש את הקוד ולהוסיף אותו לאיש הקשר.

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

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

יצירת הכוונה

כדי לערוך איש קשר, צריך להתקשר למספר Intent(action) למספר יוצרים Intent עם הפעולה ACTION_EDIT. קוראים ל-setDataAndType() כדי להגדיר את ערך הנתונים של הכוונה ל-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) ואילך, בעיה באפליקציית 'אנשי קשר' גורמת לבעיה ניווט. כשהאפליקציה שולחת כוונה לעריכה לאפליקציית אנשי הקשר, והמשתמשים עורכים ומשמרים איש קשר, כשהם לוחצים על הקודם הם רואים את המסך של רשימת אנשי הקשר. כדי לחזור לאפליקציה, הם צריכים ללחוץ על Recents (מהזמן האחרון) ולבחור את האפליקציה.

כדי לעקוף את הבעיה הזו ב-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 מתחת לכותרת 'עדכון'.

שליחת הכוונה

לסיום, שולחים את הכוונה שיצרתם. לדוגמה:

Kotlin

    // Sends the Intent
    startActivity(editIntent)

Java

    // Sends the Intent
    startActivity(editIntent);

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

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

כששולחים את הכוונה הזו, באפליקציית אנשי הקשר מוצגת רשימת אנשי קשר. המשתמשים יכולים להוסיף איש קשר חדש או לבחור איש קשר קיים ולערוך אותו. כל שדות הנתונים המורחבים שתוסיפו לכוונה יאכלסו את המסך שיופיע. אפשר להשתמש בכל אחד מערכי המפתח שצוינו ב-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);