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

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

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

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

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

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

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

יצירת כוונה

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

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

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

שליחת ה-Intent

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

Kotlin

    // Sends the Intent
    startActivity(editIntent)

Java

    // Sends the Intent
    startActivity(editIntent);

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

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

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

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);