جهات الاتصال للملف الشخصي للعمل

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

نظرة عامة

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

غالبًا ما يرغب المستخدمون في استخدام أجهزتهم الشخصية وتطبيقاتهم للعمل. باستخدام جهات الاتصال في ملف العمل، يمكن أن يصبح تطبيقك جزءًا من يوم عمل المستخدم.

تجربة المستخدم

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

  • هل يجب أن يتضمّن تطبيقك جهات اتصال ملف العمل تلقائيًا أم يجب على المستخدم الموافقة؟
  • كيف سيؤثر مزج أو فصل جهات اتصال الملف الشخصي للعمل والملف الشخصي في تدفق المستخدم؟
  • ما تأثير النقر غير المقصود على جهة اتصال في ملف العمل؟
  • ما يحدث لواجهة تطبيقك عندما لا تكون جهات اتصال ملف العمل متوفرة؟

يجب أن يشير تطبيقك بوضوح إلى جهة اتصال ملف العمل. يمكنك الحصول على شارة جهة الاتصال باستخدام أيقونة عمل مألوفة - مثل حقيبة.

لقطة شاشة تعرض نتائج البحث في قائمة
الشكل 1. كيفية فصل تطبيق "جهات اتصال Google" لملف العمل جهات الاتصال

على سبيل المثال، يقوم تطبيق جهات اتصال Google (الموضح في الشكل 1) بما يلي إدراج مزيج من جهات اتصال العمل والملف الشخصي:

  1. تدرج عنوانًا فرعيًا لفصل أقسام العمل عن الأقسام الشخصية في القائمة.
  2. شارات لجهات اتصال العمل مع رمز حقيبة الأوراق.
  3. يفتح جهة اتصال عمل في ملف العمل عند النقر عليه.

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

الأذونات

إذا كان تطبيقك يعمل بالفعل مع جهات اتصال المستخدم، ستتوفّر لك READ_CONTACTS (أو ربما WRITE_CONTACTS) الذي طلبته في ملف بيان التطبيق. لأن الشخص نفسه يستخدم الملف الشخصي والعمل فإنك لا تحتاج إلى إذن إضافي للوصول إلى بيانات جهة الاتصال من ملف العمل بك.

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

عمليات البحث عن جهات الاتصال

يمكنك الحصول على جهات اتصال من ملف العمل باستخدام واجهات برمجة التطبيقات والعمليات نفسها التي التي يستخدمها تطبيقك للحصول على جهات الاتصال في الملف الشخصي. معرف الموارد المنتظم (URI) الخاص بالمؤسسة جهات الاتصال في نظام التشغيل Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث. عليك إجراء التعديلات التالية على عنوان URI:

  1. ضبط معرّف الموارد المنتظم (URI) لموفّر المحتوى على Contacts.ENTERPRISE_CONTENT_FILTER_URI، وقدم اسم جهة الاتصال كسلسلة استعلام.
  2. اضبط دليل جهات اتصال للبحث. على سبيل المثال: يعثر ENTERPRISE_DEFAULT على جهات اتصال في العمل. المتجر المحلي الخاص بالملف الشخصي.

يعمل تغيير عنوان URI مع أي آلية لمقدم محتوى مثل CursorLoader: مثالية لتحميل بيانات جهات الاتصال في واجهات المستخدم للأسباب التالية: يتم الوصول إلى البيانات في مؤشر ترابط العامل. للتبسيط، تتمثل الأمثلة في هذا مكالمة إرشادية ContentResolver.query(). وفي ما يلي كيفية العثور على جهات الاتصال في دليل جهات الاتصال المحلي لملف العمل:

Kotlin

// First confirm the device user has given permission for the personal profile.
// There isn't a separate work permission, but an IT admin can block access.
val readContactsPermission =
  ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.READ_CONTACTS)
if (readContactsPermission != PackageManager.PERMISSION_GRANTED) {
  return
}

// Fetch Jackie, James, & Jason (and anyone else whose names begin with "ja").
val nameQuery = Uri.encode("ja")

// Build the URI to look up work profile contacts whose name matches. Query
// the default work profile directory which is the locally-stored contacts.
val contentFilterUri =
  ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI
    .buildUpon()
    .appendPath(nameQuery)
    .appendQueryParameter(
      ContactsContract.DIRECTORY_PARAM_KEY,
      ContactsContract.Directory.ENTERPRISE_DEFAULT.toString()
    )
    .build()

// Query the content provider using the generated URI.
var cursor =
  getContentResolver()
    .query(
      contentFilterUri,
      arrayOf(
        ContactsContract.Contacts._ID,
        ContactsContract.Contacts.LOOKUP_KEY,
        ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
      ),
      null,
      null,
      null
    )

// Print any results found using the work profile contacts' display name.
cursor?.use {
  while (it.moveToNext()) {
    Log.i(TAG, "Work profile contact: ${it.getString(2)}")
  }
}

Java

// First confirm the device user has given permission for the personal profile.
// There isn't a separate work permission, but an IT admin can block access.
int readContactsPermission = ContextCompat.checkSelfPermission(
    getBaseContext(), Manifest.permission.READ_CONTACTS);
if (readContactsPermission != PackageManager.PERMISSION_GRANTED) {
  return;
}

// Fetch Jackie, James, & Jason (and anyone else whose names begin with "ja").
String nameQuery = Uri.encode("ja");

// Build the URI to look up work profile contacts whose name matches. Query
// the default work profile directory which is the locally stored contacts.
Uri contentFilterUri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI
    .buildUpon()
    .appendPath(nameQuery)
    .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
        String.valueOf(ContactsContract.Directory.ENTERPRISE_DEFAULT))
    .build();

// Query the content provider using the generated URI.
Cursor cursor = getContentResolver().query(
    contentFilterUri,
    new String[] {
        ContactsContract.Contacts._ID,
        ContactsContract.Contacts.LOOKUP_KEY,
        ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
    },
    null,
    null,
    null);
if (cursor == null) {
  return;
}

// Print any results found using the work profile contacts' display name.
try {
  while (cursor.moveToNext()) {
    Log.i(TAG, "Work profile contact: " + cursor.getString(2));
  }
} finally {
  cursor.close();
}

الأدلة

تستخدم العديد من المؤسسات الأدلة البعيدة، مثل Microsoft Exchange أو LDAP، تحتوي على معلومات الاتصال بالمؤسسة بأكملها. يمكنك الاستفادة من تطبيقك يتواصل المستخدمون ويشاركون مع زملاء العمل في مؤسساتهم الدليل. لاحظ أن هذه الأدلة تحتوي عادةً على آلاف جهات الاتصال، ويحتاج التطبيق أيضًا إلى اتصال نشط بالشبكة للبحث فيها. يمكنك استخدام موفّر محتوى Directory للحصول على الأدلة التي يستخدمها حسابات المستخدمين واكتشف المزيد حول دليل فردي.

إرسال طلب بحث إلى Directory.ENTERPRISE_CONTENT_URI المحتوى للحصول على أدلة من الملف الشخصي والعمل ملف التعريف معًا. تتوفر إمكانية البحث في أدلة الملف الشخصي للعمل في الإصدار 7.0 من نظام التشغيل Android (المستوى 24 من واجهة برمجة التطبيقات) أو إصدار أحدث لا يزال تطبيقك بحاجة إلى أن يمنحه المستخدم أذونات READ_CONTACTS للعمل مع جهات الاتصال الأخرى.

نظرًا لأن Android يخزِّن معلومات الاتصال بأنواع مختلفة من الأدلة البعيدة، فإن الفئة Directory تتضمن طرقًا يمكنك استدعاؤها للعثور على المزيد حول دليل:

isEnterpriseDirectoryId()
يمكنك استدعاء هذه الطريقة لمعرفة ما إذا كان الدليل من حساب ملف العمل. يُرجى العلم أنّ موفِّر المحتوى "ENTERPRISE_CONTENT_URI" يعيد جهة الاتصال أدلة لكل من الملف الشخصي وملف العمل معًا
isRemoteDirectoryId()
يمكنك استخدام هذه الطريقة لمعرفة ما إذا كان الدليل عن بُعد. الأدلة البعيدة قد تكون متاجر جهة اتصال للمؤسسات أو قد تكون شبكات اجتماعية للمستخدم.

يوضّح المثال التالي كيفية استخدام هذه الطرق لفلترة ملف العمل. الدلائل:

Kotlin

// First, confirm the device user has given READ_CONTACTS permission.
// This permission is still needed for directory listings ...

// Query the content provider to get directories for BOTH the personal and
// work profiles.
val cursor =
  getContentResolver()
    .query(
      ContactsContract.Directory.ENTERPRISE_CONTENT_URI,
      arrayOf(ContactsContract.Directory._ID, ContactsContract.Directory.PACKAGE_NAME),
      null,
      null,
      null
    )

// Print the package name of the work profile's local or remote contact directories.
cursor?.use {
  while (it.moveToNext()) {
    val directoryId = it.getLong(0)
    if (ContactsContract.Directory.isEnterpriseDirectoryId(directoryId)) {
      Log.i(TAG, "Directory: ${it.getString(1)}")
    }
  }
}

Java

// First, confirm the device user has given READ_CONTACTS permission.
// This permission is still needed for directory listings ...

// Query the content provider to get directories for BOTH the personal and
// work profiles.
Cursor cursor = getContentResolver().query(
    ContactsContract.Directory.ENTERPRISE_CONTENT_URI,
    new String[]{
        ContactsContract.Directory._ID,
        ContactsContract.Directory.PACKAGE_NAME
    },
    null,
    null,
    null);
if (cursor == null) {
  return;
}

// Print the package name of the work profile's local or remote contact directories.
try {
  while (cursor.moveToNext()) {
    long directoryId = cursor.getLong(0);

    if (ContactsContract.Directory.isEnterpriseDirectoryId(directoryId)) {
      Log.i(TAG, "Directory: " + cursor.getString(1));
    }
  }
} finally {
  cursor.close();
}

يجلب المثال المعرّف واسم الحزمة للدليل. لعرض مستخدم تساعد المستخدمين في اختيار مصدر دليل جهات الاتصال، قد تحتاج إلى لجلب المزيد من المعلومات حول الدليل. للاطلاع على حقول بيانات التعريف الأخرى التي متاحة، يُرجى الاطّلاع على مرجع فئة Directory.

عمليات البحث عن رقم الهاتف

السماح للتطبيقات بإجراء طلبات بحث PhoneLookup.CONTENT_FILTER_URI بكفاءة البحث عن بيانات جهة الاتصال عن رقم هاتف. يمكنك الحصول على نتائج بحث من كل من جهات الاتصال الشخصية وجهات الاتصال في ملف العمل إذا استبدلت معرّف الموارد المنتظم (URI) هذا PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI يتوفّر معرّف الموارد المنتظم (URI) لمحتوى ملف العمل في الإصدار 5.0 من نظام التشغيل Android (المستوى 21 من واجهة برمجة التطبيقات) أو أعلى.

يعرض المثال التالي تطبيقًا يطلب من أجل الحصول على معرّف الموارد المنتظم (URI) لمحتوى ملف العمل. ضبط واجهة المستخدم لمكالمة واردة:

Kotlin

fun onCreateIncomingConnection(
  connectionManagerPhoneAccount: PhoneAccountHandle,
  request: ConnectionRequest
): Connection {
  var request = request
  // Get the telephone number from the incoming request URI.
  val phoneNumber = this.extractTelephoneNumber(request.address)

  var displayName = "Unknown caller"
  var isCallerInWorkProfile = false

  // Look up contact details for the caller in the personal and work profiles.
  val lookupUri =
    Uri.withAppendedPath(
      ContactsContract.PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
      Uri.encode(phoneNumber)
    )
  val cursor =
    getContentResolver()
      .query(
        lookupUri,
        arrayOf(
          ContactsContract.PhoneLookup._ID,
          ContactsContract.PhoneLookup.DISPLAY_NAME,
          ContactsContract.PhoneLookup.CUSTOM_RINGTONE
        ),
        null,
        null,
        null
      )

  // Use the first contact found and check if they're from the work profile.
  cursor?.use {
    if (it.moveToFirst() == true) {
      displayName = it.getString(1)
      isCallerInWorkProfile = ContactsContract.Contacts.isEnterpriseContactId(it.getLong(0))
    }
  }

  // Return a configured connection object for the incoming call.
  val connection = MyAudioConnection()
  connection.setCallerDisplayName(displayName, TelecomManager.PRESENTATION_ALLOWED)

  // Our app's activity uses this value to decide whether to show a work badge.
  connection.setIsCallerInWorkProfile(isCallerInWorkProfile)

  // Configure the connection further ...
  return connection
}

Java

public Connection onCreateIncomingConnection (
    PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
  // Get the telephone number from the incoming request URI.
  String phoneNumber = this.extractTelephoneNumber(request.getAddress());

  String displayName = "Unknown caller";
  boolean isCallerInWorkProfile = false;

  // Look up contact details for the caller in the personal and work profiles.
  Uri lookupUri = Uri.withAppendedPath(
      ContactsContract.PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
      Uri.encode(phoneNumber));
  Cursor cursor = getContentResolver().query(
      lookupUri,
      new String[]{
          ContactsContract.PhoneLookup._ID,
          ContactsContract.PhoneLookup.DISPLAY_NAME,
          ContactsContract.PhoneLookup.CUSTOM_RINGTONE
      },
      null,
      null,
      null);

  // Use the first contact found and check if they're from the work profile.
  if (cursor != null) {
    try {
      if (cursor.moveToFirst() == true) {
        displayName = cursor.getString(1);
        isCallerInWorkProfile =
            ContactsContract.Contacts.isEnterpriseContactId(cursor.getLong(0));
      }
    } finally {
      cursor.close();
    }
  }

  // Return a configured connection object for the incoming call.
  MyConnection connection = new MyConnection();
  connection.setCallerDisplayName(displayName, TelecomManager.PRESENTATION_ALLOWED);

  // Our app's activity uses this value to decide whether to show a work badge.
  connection.setIsCallerInWorkProfile(isCallerInWorkProfile);

  // Configure the connection further ...
  return connection;
}

عمليات البحث عن البريد الإلكتروني

يمكن لتطبيقك الحصول على بيانات جهات الاتصال الشخصية أو بيانات جهات الاتصال الخاصة بالعمل لعنوان بريد إلكتروني من خلال إجراء طلبات بحث. Email.ENTERPRISE_CONTENT_LOOKUP_URI يؤدي طلب البحث عن عنوان URL هذا أولاً إلى البحث في جهات الاتصال الشخصية عن مطابقة تامة. في حال حذف عدم تطابق مقدم الخدمة مع أي جهات اتصال شخصية، فسيبحث مقدم الخدمة بعد ذلك جهات اتصال العمل للمطابقة. يتوفّر معرّف الموارد المنتظم (URI) هذا في الإصدار Android 6.0 (المستوى 23 من واجهة برمجة التطبيقات). أو أعلى.

إليك كيفية البحث عن معلومات الاتصال لعنوان بريد إلكتروني:

Kotlin

// Build the URI to look up contacts from the personal and work profiles that
// are an exact (case-insensitive) match for the email address.
val emailAddress = "somebody@example.com"
val contentFilterUri =
  Uri.withAppendedPath(
    ContactsContract.CommonDataKinds.Email.ENTERPRISE_CONTENT_LOOKUP_URI,
    Uri.encode(emailAddress)
  )

// Query the content provider to first try to match personal contacts and,
// if none are found, then try to match the work contacts.
val cursor =
  contentResolver.query(
    contentFilterUri,
    arrayOf(
      ContactsContract.CommonDataKinds.Email.CONTACT_ID,
      ContactsContract.CommonDataKinds.Email.ADDRESS,
      ContactsContract.Contacts.DISPLAY_NAME
    ),
    null,
    null,
    null
  )
    ?: return

// Print the name of the matching contact. If we want to work-badge contacts,
// we can call ContactsContract.Contacts.isEnterpriseContactId() with the ID.
cursor.use {
  while (it.moveToNext()) {
    Log.i(TAG, "Matching contact: ${it.getString(2)}")
  }
}

Java

// Build the URI to look up contacts from the personal and work profiles that
// are an exact (case-insensitive) match for the email address.
String emailAddress = "somebody@example.com";
Uri contentFilterUri = Uri.withAppendedPath(
    ContactsContract.CommonDataKinds.Email.ENTERPRISE_CONTENT_LOOKUP_URI,
    Uri.encode(emailAddress));

// Query the content provider to first try to match personal contacts and,
// if none are found, then try to match the work contacts.
Cursor cursor = getContentResolver().query(
    contentFilterUri,
    new String[]{
        ContactsContract.CommonDataKinds.Email.CONTACT_ID,
        ContactsContract.CommonDataKinds.Email.ADDRESS,
        ContactsContract.Contacts.DISPLAY_NAME
    },
    null,
    null,
    null);
if (cursor == null) {
  return;
}

// Print the name of the matching contact. If we want to work-badge contacts,
// we can call ContactsContract.Contacts.isEnterpriseContactId() with the ID.
try {
  while (cursor.moveToNext()) {
    Log.i(TAG, "Matching contact: " + cursor.getString(2));
  }
} finally {
  cursor.close();
}

عرض جهة اتصال خاصة بالعمل

يمكن للتطبيقات التي تعمل في الملف الشخصي أن تعرض بطاقة جهة اتصال في ملف العمل. اتصل ContactsContract.QuickContact.showQuickContact() بوصة الإصدار 5.0 من Android أو إصدار أحدث لتشغيل تطبيق "جهات الاتصال" في ملف العمل وإظهار بطاقة جهة الاتصال.

لإنشاء معرّف موارد منتظم (URI) صحيح لملف العمل، يجب الاتصال بـ ContactsContract.Contacts.getLookupUri() واجتياز معرف جهة الاتصال ومفتاح البحث. يوضح المثال التالي كيفية الحصول على عنوان URI ثمّ تُظهر البطاقة:

Kotlin

// Query the content provider using the ENTERPRISE_CONTENT_FILTER_URI address.
// We use the _ID and LOOKUP_KEY columns to generate a work-profile URI.
val cursor =
  getContentResolver()
    .query(
      contentFilterUri,
      arrayOf(ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY),
      null,
      null
    )

// Show the contact details card in the work profile's Contacts app. The URI
// must be created with getLookupUri().
cursor?.use {
  if (it.moveToFirst() == true) {
    val uri = ContactsContract.Contacts.getLookupUri(it.getLong(0), it.getString(1))
    ContactsContract.QuickContact.showQuickContact(
      activity,
      Rect(20, 20, 100, 100),
      uri,
      ContactsContract.QuickContact.MODE_LARGE,
      null
    )
  }
}

Java

// Query the content provider using the ENTERPRISE_CONTENT_FILTER_URI address.
// We use the _ID and LOOKUP_KEY columns to generate a work-profile URI.
Cursor cursor = getContentResolver().query(
    contentFilterUri,
    new String[] {
        ContactsContract.Contacts._ID,
        ContactsContract.Contacts.LOOKUP_KEY,
    },
    null,
    null,
    null);
if (cursor == null) {
  return;
}

// Show the contact details card in the work profile's Contacts app. The URI
// must be created with getLookupUri().
try {
  if (cursor.moveToFirst() == true) {
    Uri uri = ContactsContract.Contacts.getLookupUri(
        cursor.getLong(0), cursor.getString(1));
    ContactsContract.QuickContact.showQuickContact(
        getActivity(),
        new Rect(20, 20, 100, 100),
        uri,
        ContactsContract.QuickContact.MODE_LARGE,
        null);
  }
} finally {
  cursor.close();
}

مدى توفّر الخدمة

يلخّص الجدول التالي إصدارات Android التي تتوافق مع ملف العمل بيانات الاتصال في الملف الشخصي:

إصدار Android الدعم
5.0 (مستوى واجهة برمجة التطبيقات 21) يمكنك البحث عن أسماء جهات اتصال العمل لأرقام الهواتف باستخدام PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.
6.0 (مستوى واجهة برمجة التطبيقات 23) يمكنك البحث عن أسماء جهات اتصال العمل لعناوين البريد الإلكتروني باستخدام Email.ENTERPRISE_CONTENT_LOOKUP_URI.
الإصدار 7.0 (مستوى واجهة برمجة التطبيقات 24) يمكنك الاستعلام عن أسماء جهات اتصال العمل من أدلة العمل باستخدام Contacts.ENTERPRISE_CONTENT_FILTER_URI.
يمكنك إدراج جميع الأدلة في الملفات الشخصية والملفات الشخصية للعمل باستخدام Directory.ENTERPRISE_CONTENT_URI.

التطوير والاختبار

لإنشاء ملف شخصي للعمل، اتّبِع الخطوات التالية:

  1. ثبِّت تطبيق Test DPC (اختبار وحدة التحكّم بسياسة الجهاز).
  2. افتح تطبيق Set up Test DPC (إعداد وحدة التحكّم بسياسة الجهاز) (وليس رمز تطبيق Test DPC).
  3. اتّبِع التعليمات الظاهرة على الشاشة لإعداد ملف شخصي مُدار.
  4. في ملف العمل، افتح تطبيق جهات الاتصال وأضِف بعض نماذج جهات الاتصال.

لمحاكاة مشرف تكنولوجيا المعلومات الذي يحظر الوصول إلى جهات اتصال ملف العمل، يمكنك اتباع الخطوات التالية:

  1. في ملف العمل، افتح تطبيق Test DPC (اختبار وحدة التحكّم بسياسة الجهاز).
  2. ابحث عن إعداد إيقاف البحث عن جهات الاتصال بين الملف الشخصي وملف العمل أو عن إيقاف ميزة "إظهار رقم المتّصل" بين الملف الشخصي وملف العمل
  3. اضبط الإعداد على تفعيل.

لمعرفة مزيد من المعلومات عن اختبار تطبيقك باستخدام ملفات العمل، يُرجى الاطّلاع على مقالة اختبار التطبيق التوافق مع الملفات الشخصية للعمل:

مصادر إضافية

لمزيد من المعلومات حول جهات الاتصال أو ملف العمل، يمكنك الاطّلاع على هذه الموارد: