تعديل جهات الاتصال باستخدام الأغراض

يشرح هذا الدرس كيفية استخدام Intent لإدراج جهة اتصال جديدة أو تعديل بيانات جهة اتصال. بدلاً من الوصول إلى "مقدِّم جهات الاتصال" مباشرةً، يبدأ Intent تطبيق جهات الاتصال الذي يشغّل Activity المناسب. بالنسبة إلى إجراءات التعديل الموضّحة في هذا الدرس، إذا أرسلت بيانات موسّعة في Intent، سيتم إدخالها في واجهة مستخدم Activity التي بدأت.

إنّ استخدام Intent لإدراج جهة اتصال واحدة أو تعديلها هو الطريقة المفضّلة لتعديل مقدّم جهات الاتصال، وذلك للأسباب التالية:

  • يوفر لك الوقت والجهد المبذولين في تطوير واجهة المستخدم والتعليمات البرمجية الخاصة بك.
  • وتتجنّب هذه الميزة حدوث أخطاء ناتجة عن التعديلات التي لا تلتزم بقواعد مقدّم خدمة جهات الاتصال.
  • يقلل عدد الأذونات التي تحتاج إلى طلبها. لا يحتاج تطبيقك إلى إذن للكتابة إلى مقدِّم خدمة جهات الاتصال، لأنّه يفوّض تعديلات على تطبيق جهات الاتصال، الذي حصل على هذا الإذن مسبقًا.

إدراج جهة اتصال جديدة باستخدام هدف

غالبًا ما تريد السماح للمستخدم بإدراج جهة اتصال جديدة عندما يتلقّى تطبيقك بيانات جديدة. على سبيل المثال، يمكن أن يسمح تطبيق مراجعات المطاعم للمستخدمين بإضافة المطعم كجهة اتصال أثناء مراجعتهم. لإجراء ذلك باستخدام صيغة، يجب إنشاء هدف باستخدام أكبر قدر ممكن من البيانات المتاحة ثم إرسال الغرض إلى تطبيق جهات الاتصال.

يؤدي إدراج جهة اتصال باستخدام تطبيق جهات الاتصال إلى إدراج جهة اتصال أولية جديدة في جدول ContactsContract.RawContacts الخاص بمقدِّم جهات الاتصال. وإذا لزم الأمر، يطلب تطبيق "جهات الاتصال" من المستخدمين نوع الحساب والحساب المراد استخدامهما عند إنشاء جهة الاتصال الأولية. كما يرسل تطبيق جهات الاتصال إشعارًا إلى المستخدمين إذا سبق أن تمت إضافة جهة الاتصال الأولية. بعد ذلك، يتوفّر للمستخدمين خيار إلغاء الإدراج، وفي هذه الحالة لن يتم إنشاء أي جهة اتصال. للاطّلاع على مزيد من المعلومات عن جهات الاتصال الأولية، يُرجى الاطّلاع على دليل واجهة برمجة التطبيقات 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);

إذا كانت لديك تفاصيل عن جهة الاتصال، مثل رقم الهاتف أو عنوان البريد الإلكتروني، يمكنك إدراجها في الغرض كبيانات موسّعة. بالنسبة إلى قيمة مفتاح، استخدِم الثابت المناسب من 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، لأنّ هذه الأعمدة مدرَجة في قسم الملخّص من مرجع واجهة برمجة التطبيقات للفئة ContactsContract.Contacts تحت العنوان "تعديل".

أخيرًا، أرسل النية. استجابةً لذلك، يعرض تطبيق جهات الاتصال شاشة تعديل. عندما ينتهي المستخدم من تعديل التعديلات ويحفظها، يعرض تطبيق جهات الاتصال قائمة جهات اتصال. عندما ينقر المستخدم على رجوع، يتم عرض تطبيقك.

إنشاء النية

لتعديل جهة اتصال، اطلب Intent(action) لإنشاء هدف من خلال الإجراء ACTION_EDIT. عليك استدعاء setDataAndType() لضبط قيمة بيانات الغرض على Contacts.CONTENT_LOOKUP_URI لجهة الاتصال ونوع MIME على Contacts.CONTENT_ITEM_TYPE من النوع MIME. ولأنّ طلب setType() يؤدي إلى استبدال قيمة البيانات الحالية لـ Intent، عليك ضبط البيانات ونوع MIME في الوقت نفسه.

للحصول على Contacts.CONTENT_LOOKUP_URI لجهة اتصال، يمكنك طلب Contacts.getLookupUri(id, lookupkey) باستخدام قيمتَي Contacts._ID وContacts.LOOKUP_KEY لجهة الاتصال كوسيطات.

ملاحظة: قيمة LOOKUP_KEY لجهة الاتصال هي المعرّف الذي يجب استخدامه لاسترداد جهة اتصال. وهو يظلّ ثابتًا، حتى إذا غيّر مزوّد الخدمة رقم تعريف صف جهة الاتصال لمعالجة العمليات الداخلية.

يوضّح لك المقتطف التالي كيفية إنشاء هدف:

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 (الإصدار 14 من واجهة برمجة التطبيقات) والإصدارات الأحدث، تؤدي مشكلة في تطبيق جهات الاتصال إلى تنقُّل غير صحيح. عندما يُرسِل تطبيقك هدف تعديل إلى تطبيق جهات الاتصال، ويعدِّل المستخدمون جهة اتصال ويحفظونها، عندما ينقرون على رجوع، تظهر لهم شاشة قائمة جهات الاتصال. وللرجوع إلى تطبيقك، عليه النقر على العناصر الأخيرة واختيار تطبيقك.

لحلّ هذه المشكلة في نظام التشغيل Android 4.0.3 (الإصدار 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. يتم إدراج هذه الأعمدة في قسم الملخّص من مرجع واجهة برمجة التطبيقات للفئة ContactsContract.Contacts ضمن العنوان "تعديل".

إرسال الغرض

أخيرًا، أرسل الهدف الذي أنشأته. مثلاً:

Kotlin

    // Sends the Intent
    startActivity(editIntent)

Java

    // Sends the Intent
    startActivity(editIntent);

السماح للمستخدمين باختيار الإدراج أو التعديل باستخدام هدف

يمكنك السماح للمستخدمين باختيار ما إذا كانوا يريدون إدراج جهة اتصال أو تعديل جهة اتصال حالية عن طريق إرسال Intent مع الإجراء ACTION_INSERT_OR_EDIT. على سبيل المثال، يمكن لتطبيق برنامج بريد إلكتروني السماح للمستخدمين بإضافة عنوان بريد إلكتروني وارد إلى جهة اتصال جديدة أو إضافته كعنوان إضافي لجهة اتصال حالية. اضبط نوع MIME لهذا الغرض على Contacts.CONTENT_ITEM_TYPE، ولكن لا تضبط معرّف الموارد المنتظم (URI) للبيانات.

عند إرسال هذا الغرض، سيعرض تطبيق جهات الاتصال قائمة بجهات الاتصال. بإمكان المستخدمين إما إدراج جهة اتصال جديدة أو اختيار جهة اتصال حالية وتعديلها. تتم تعبئة الشاشة التي تظهر بأي حقول بيانات موسّعة تضيفها إلى الغرض. ويمكنك استخدام أي من القيم الرئيسية المحدّدة في 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);