قراءة حزمة تطوير البرامج (SDK) للتفاعل: تعليمات الدمج الفني للجهات الخارجية

زيادة التفاعل مع التطبيق من خلال الوصول إلى المستخدمين في الأماكن التي يتواجدون فيها يمكنك دمج حزمة Engage SDK لتقديم اقتراحات مخصّصة ومحتوى متواصل مباشرةً للمستخدمين على مساحات عرض متعددة على الجهاز فقط، مثل المجموعات ومساحة الترفيه و"متجر Play". تضيف عملية الدمج أقل من 50 كيلوبايت (مضغوطة) إلى متوسط حجم حزمة APK، وتستغرق معظم التطبيقات حوالي أسبوع من وقت المطوّر. يمكنك الاطّلاع على مزيد من المعلومات في الموقع الإلكتروني الخاص بالأنشطة التجارية.

يحتوي هذا الدليل على تعليمات موجّهة إلى شركاء المطوّرين بشأن عرض محتوى القراءة (الكتب الإلكترونية والكتب الصوتية والكتب المصوّرة/المانغا) على مساحات عرض المحتوى في "تطبيق Google".

تفاصيل عملية الدمج

المصطلحات

يتضمّن هذا الدمج ثلاثة أنواع من المجموعات: الاقتراحات والمحتوى المقترَح لمواصلة المشاهدة والمحتوى المميّز.

  • تعرض مجموعات الاقتراحات اقتراحات مخصّصة حول المحتوى الذي يمكن قراءته من أحد المطوّرين الشركاء.

    تتّبع اقتراحاتك البنية التالية:

    • مجموعة الاقتراحات: هي طريقة عرض لواجهة المستخدم تتضمّن مجموعة من الاقتراحات من شريك مطوّر واحد.

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

      الشكل 2. واجهة مستخدم "مساحة الترفيه" تعرض كيانًا واحدًا ضمن مجموعة اقتراحات خاصة بشريك واحد
  • تعرض مجموعة المحتوى غير المكتمل الكتب غير المكتملة من عدة شركاء مطوّرين في مجموعة واحدة ضمن واجهة المستخدم. سيُسمح لكل شريك مطوّر ببث 10 عناصر كحدّ أقصى في مجموعة "المتابعة".

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

    الشكل 4. واجهة مستخدم "مساحة الترفيه" تعرض مجموعة "محتوى مقترَح" تتضمّن اقتراحات من شركاء متعدّدين (يظهر اقتراح واحد فقط حاليًا).

العمل التحضيري

الحد الأدنى لمستوى واجهة برمجة التطبيقات: 19

أضِف مكتبة com.google.android.engage:engage-core إلى تطبيقك باتّباع الخطوات التالية:

dependencies {
    // Make sure you also include that repository in your project's build.gradle file.
    implementation 'com.google.android.engage:engage-core:1.6.0'
}

ملخّص

ويستند التصميم إلى تنفيذ خدمة مرتبطة.

تخضع البيانات التي يمكن للعميل نشرها للحدود التالية لأنواع المجموعات المختلفة:

نوع المجموعة حدود المجموعات الحدود القصوى للعناصر في مجموعة
مجموعات الاقتراحات 7 على الأكثر 50 بحد أقصى
مجموعة المتابعة 1 على الأكثر 20 بحد أقصى
المجموعة المميزة 1 على الأكثر 20 بحد أقصى

الخطوة 1: تقديم بيانات المؤسسة

حدّدت حزمة تطوير البرامج (SDK) عناصر مختلفة لتمثيل كل نوع من أنواع العناصر. نوفّر الكيانات التالية ضمن فئة "القراءة":

  1. EbookEntity
  2. AudiobookEntity
  3. BookSeriesEntity

توضّح الرسوم البيانية أدناه السمات والمتطلبات المتاحة لكل نوع.

EbookEntity

يمثّل العنصر EbookEntity كتابًا إلكترونيًا (على سبيل المثال، الكتاب الإلكتروني Becoming من تأليف ميشيل أوباما).

السمة المتطلبات ملاحظات
الاسم مطلوبة
صور الملصقات مطلوبة يجب تقديم صورة واحدة على الأقل. يُرجى الاطّلاع على مواصفات الصور للحصول على إرشادات.
المؤلِّف مطلوبة يجب تقديم اسم مؤلف واحد على الأقل.
معرّف الموارد المنتظم (URI) لرابط لاتّخاذ إجراء مطلوبة

الرابط العميق لتطبيق مقدّمي الخدمات للكتاب الإلكتروني.

ملاحظة: يمكنك استخدام الروابط المؤدية إلى صفحات في التطبيق لتحديد المصدر. يُرجى الرجوع إلى الأسئلة الشائعة

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

‫TYPE_CONTINUE: استئناف قراءة كتاب غير مكتمل

‫TYPE_NEXT - مواصلة سلسلة جديدة

‫TYPE_NEW - تم إصداره حديثًا.

مدة التفاعل الأخيرة مطلوب بشكل مشروط

يجب تقديمها عندما يكون المنتج في مجموعة "المنتجات المشابهة".

يمكن أن تكون الكتب الإلكترونية *التي تم شراؤها حديثًا* جزءًا من مجموعة "مواصلة القراءة".

بالملّي ثانية منذ بدء حساب الفترة

النسبة المئوية لمستوى التقدّم المكتمل مطلوب بشكل مشروط

يجب تقديمها عندما يكون المنتج في مجموعة "المنتجات المشابهة".

يجب أن تكون القيمة أكبر من 0 وأقل من 100.

DisplayTimeWindow - ضبط فترة زمنية لعرض المحتوى على السطح
الطابع الزمني للبدء اختياري

الطابع الزمني الخاص بالحقبة الذي يجب أن يظهر بعده المحتوى على مساحة العرض.

في حال عدم ضبط هذه السياسة، يكون المحتوى مؤهلاً للعرض على المساحة.

بالملّي ثانية منذ بدء حساب الفترة

الطابع الزمني للنهاية اختياري

تمثّل هذه السمة الطابع الزمني لوقت بدء العرض الذي يتوقف بعده المحتوى عن الظهور على مساحة العرض.

في حال عدم ضبط هذه السياسة، يكون المحتوى مؤهلاً للعرض على المساحة.

بالملّي ثانية منذ بدء حساب الفترة

AudiobookEntity

يمثّل العنصر AudiobookEntity كتابًا مسموعًا (على سبيل المثال، الكتاب المسموع Becoming من تأليف ميشيل أوباما).

السمة المتطلبات ملاحظات
الاسم مطلوبة
صور الملصقات مطلوبة يجب تقديم صورة واحدة على الأقل. يُرجى الاطّلاع على مواصفات الصور للحصول على إرشادات.
المؤلِّف مطلوبة يجب تقديم اسم مؤلف واحد على الأقل.
معرّف الموارد المنتظم (URI) لرابط لاتّخاذ إجراء مطلوبة

تمثّل هذه السمة الرابط العميق لتطبيق مقدّمي الخدمات الخاص بالكتاب المسموع.

ملاحظة: يمكنك استخدام الروابط المؤدية إلى صفحات في التطبيق لتحديد المصدر. يُرجى الرجوع إلى الأسئلة الشائعة

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

‫TYPE_CONTINUE: استئناف قراءة كتاب غير مكتمل

‫TYPE_NEXT - مواصلة سلسلة جديدة

‫TYPE_NEW - تم إصداره حديثًا.

مدة التفاعل الأخيرة مطلوب بشكل مشروط

يجب تقديمها عندما يكون المنتج في مجموعة "المنتجات المشابهة".

بالملّي ثانية منذ بدء حساب الفترة

النسبة المئوية لمستوى التقدّم المكتمل مطلوب بشكل مشروط

يجب تقديمها عندما يكون المنتج في مجموعة "المنتجات المشابهة".

يمكن أن تكون الكتب الصوتية التي تم شراؤها *حديثًا* جزءًا من مجموعة "مواصلة القراءة".

يجب أن تكون القيمة أكبر من 0 وأقل من 100.

DisplayTimeWindow - ضبط فترة زمنية لعرض المحتوى على السطح
الطابع الزمني للبدء اختياري

الطابع الزمني الخاص بالحقبة الذي يجب أن يظهر بعده المحتوى على مساحة العرض.

في حال عدم ضبط هذه السياسة، يكون المحتوى مؤهلاً للعرض على المساحة.

بالملّي ثانية منذ بدء حساب الفترة

الطابع الزمني للنهاية اختياري

تمثّل هذه السمة الطابع الزمني لوقت بدء العرض الذي يتوقف بعده المحتوى عن الظهور على مساحة العرض.

في حال عدم ضبط هذه السياسة، يكون المحتوى مؤهلاً للعرض على المساحة.

بالملّي ثانية منذ بدء حساب الفترة

BookSeriesEntity

يمثّل العنصر BookSeriesEntity سلسلة كتب (على سبيل المثال، سلسلة كتب هاري بوتر التي تتضمّن 7 كتب).

السمة المتطلبات ملاحظات
الاسم مطلوبة
صور الملصقات مطلوبة يجب تقديم صورة واحدة على الأقل. يُرجى الاطّلاع على مواصفات الصور للحصول على إرشادات.
المؤلِّف مطلوبة يجب توفّر اسم مؤلف واحد على الأقل.
معرّف الموارد المنتظم (URI) لرابط لاتّخاذ إجراء مطلوبة

تمثّل هذه السمة الرابط لصفحة معيّنة في تطبيق الموفّر للكتاب المسموع أو الإلكتروني.

ملاحظة: يمكنك استخدام الروابط المؤدية إلى صفحات في التطبيق لتحديد المصدر. يُرجى الرجوع إلى الأسئلة الشائعة

عدد الكتب مطلوبة عدد الكتب في السلسلة
الوصف اختياري يجب أن يتألف من 200 حرف كحد أقصى إذا تم تقديمه.
النوع اختياري قائمة بأنواع الكتب المرتبطة بالكتاب
نوع الكتاب الذي ستتم مواصلة قراءته اختياري

‫TYPE_CONTINUE: استئناف قراءة كتاب غير مكتمل

‫TYPE_NEXT - مواصلة سلسلة جديدة

‫TYPE_NEW - تم إصداره حديثًا.

مدة التفاعل الأخيرة مطلوب بشكل مشروط

يجب تقديمها عندما يكون المنتج في مجموعة "المنتجات المشابهة".

بالملّي ثانية منذ بدء حساب الفترة

النسبة المئوية لمستوى التقدّم المكتمل مطلوب بشكل مشروط

يجب تقديمها عندما يكون المنتج في مجموعة "المنتجات المشابهة".

يمكن أن تكون سلاسل الكتب التي تم شراؤها *حديثًا* جزءًا من مجموعة "مواصلة القراءة".

يجب أن تكون القيمة أكبر من 0 وأقل من 100.

DisplayTimeWindow - ضبط فترة زمنية لعرض المحتوى على السطح
الطابع الزمني للبدء اختياري

الطابع الزمني الخاص بالحقبة الذي يجب أن يظهر بعده المحتوى على مساحة العرض.

في حال عدم ضبط هذه السياسة، يكون المحتوى مؤهلاً للعرض على المساحة.

بالملّي ثانية منذ بدء حساب الفترة

الطابع الزمني للنهاية اختياري

تمثّل هذه السمة الطابع الزمني لوقت بدء العرض الذي يتوقف بعده المحتوى عن الظهور على مساحة العرض.

في حال عدم ضبط هذه السياسة، يكون المحتوى مؤهلاً للعرض على المساحة.

بالملّي ثانية منذ بدء حساب الفترة

مواصفات الصور

في ما يلي المواصفات المطلوبة لمواد عرض الصور:

نسبة العرض إلى الارتفاع المجموعات المتوافقة الحدّ الأدنى لعدد وحدات البكسل وحدات البكسل المقترَحة
مربّعة (1x1) جميع المجموعات 300x300 1200x1200
أفقية (1.91x1) المحتوى المميز والمحتوى المتسلسل 600x314 ‫1200 x ‏628
عمودية (4x5) الاقتراح 480x600 960x1200

تنسيقات الملفات

‫PNG أو JPG أو GIF ثابت أو WebP

الحد الأقصى لحجم الملف

5120 كيلوبايت

اقتراحات إضافية

  • مساحة القسم المهم في الصور: ضَع المحتوى المهم في الوسط ليشغل ‎80% من الصورة.

مثال

AudiobookEntity audiobookEntity =
        new AudiobookEntity.Builder()
            .setName("Becoming")
            .addPosterImage(
                      new Image.Builder()
                          .setImageUri(Uri.parse("http://www.x.com/image.png"))
                          .setImageHeightInPixel(960)
                          .setImageWidthInPixel(408)
                          .build())
            .addAuthor("Michelle Obama")
            .addNarrator("Michelle Obama")
            .setActionLinkUri(Uri.parse("https://play.google/audiobooks/1"))
            .setDurationMillis(16335L)
            .setPublishDateEpochMillis(1633032895L)
            .setDescription("An intimate, powerful, and inspiring memoir")
            .setPrice("$16.95")
            .addGenre("biography")
            .build();

الخطوة 2: تقديم بيانات المجموعة

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

تتحمّل AppEngagePublishClient مسؤولية نشر المجموعات. تتوفّر واجهات برمجة التطبيقات التالية في العميل:

  • isServiceAvailable
  • publishRecommendationClusters
  • publishFeaturedCluster
  • publishContinuationCluster
  • publishUserAccountManagementRequest
  • updatePublishStatus
  • deleteRecommendationsClusters
  • deleteFeaturedCluster
  • deleteContinuationCluster
  • deleteUserManagementCluster
  • deleteClusters

isServiceAvailable

تُستخدَم واجهة برمجة التطبيقات هذه للتأكّد من أنّ الخدمة متاحة للدمج وما إذا كان يمكن عرض المحتوى على الجهاز.

يمكنك التحقّق من مدى توفّر الخدمة لكل نوع مجموعة تنوي نشره. تقبل واجهة برمجة التطبيقات isServiceAvailable عنصر طلب، ServiceAvailabilityRequest، يحتوي على أنواع المجموعات التي يجب التحقّق من توفّر الخدمة لها. يمكنك العثور على قيم التعداد ClusterType المطلوبة لـ ServiceAvailabilityRequest من الجدول التالي.

نوع المجموعة ثابت نوع المجموعة قيمة العدد الصحيح
غير معروف TYPE_UNKNOWN 0
مجموعة الاقتراحات TYPE_RECOMMENDATION 1
المجموعة المميزة TYPE_FEATURED 2
مجموعة المتابعة TYPE_CONTINUATION 3
مجموعة إدارة المستخدمين TYPE_ENGAGEMENT 8
مجموعة الاشتراكات TYPE_SUBSCRIPTION 12

Kotlin

val request = ServiceAvailabilityRequest.Builder()
    .addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
    .addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
    .build()

client.isServiceAvailable(request).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        val availabilityMap = task.result
        if (availabilityMap[ClusterType.TYPE_CONTINUATION] == true) {
            // Proceed with publishing continuation content
        }
        if (availabilityMap[ClusterType.TYPE_RECOMMENDATION] == true) {
            // Proceed with publishing recommendation content
        }
    } else {
        // The IPC call itself fails, proceed with error handling logic here,
        // such as retry.
    }
}

Java

ServiceAvailabilityRequest request =
    new ServiceAvailabilityRequest.Builder()
        .addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
        .addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
        .build();

client.isServiceAvailable(request).addOnCompleteListener(task -> {
    if (task.isSuccessful()) {
        Map<Integer, Boolean> availabilityMap = task.getResult();
        if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_CONTINUATION))) {
            // Proceed with publishing continuation content
        }
        if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_RECOMMENDATION))) {
            // Proceed with publishing recommendation content
        }
    } else {
        // The IPC call itself fails, proceed with error handling logic here such as retry.
    }
});
ميزة "توفّر الخدمة المشروط"

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

بدءًا من الإصدار 1.6.0، تتيح حزمة تطوير البرامج (SDK) الخاصة بمنصة Engage التحقّق من مدى التوفّر لأنواع معيّنة من المجموعات. يوفّر ذلك مرونة أكبر، فإذا اعتمد تطبيق معيّن استراتيجية المحتوى المتقطّع، يمكن أن تتّبع بعض أنواع المجموعات هذه الاستراتيجية المتقطّعة، بينما يتم تفعيل أنواع المجموعات الأخرى دائمًا (أي مجموعات المواصلة).

إذا كان من المفترض ألا تكون خدمة Engage مفعّلة "باستمرار" على جميع الأجهزة المتوافقة لأي سبب من الأسباب، وتم ضبطها على الاستيعاب المتقطّع لأي مجموعة من الأجهزة، سيظلّ نشر جميع مجموعات المحتوى المتواصل (مثل "متابعة القراءة") مفعّلاً حسب الإعدادات التلقائية، وسيتم تفعيل بقية أنواع المجموعات وإيقافها بشكل متقطّع. إذا كان الاستيعاب المتقطّع ينطبق عليك ولكن هذا الإعداد التلقائي لا يناسب احتياجاتك، يُرجى التواصل مع engage-developers@google.com.

بالنسبة إلى إصدارات حزمة تطوير البرامج (SDK) الأقدم من الإصدار 1.6.0 (سيتم إيقافها نهائيًا)

Kotlin

client.isServiceAvailable.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Handle IPC call success
        if(task.result) {
          // Service is available on the device, proceed with content publish
          // calls.
        } else {
          // Service is not available, no further action is needed.
        }
    } else {
      // The IPC call itself fails, proceed with error handling logic here,
      // such as retry.
    }
}

Java

client.isServiceAvailable().addOnCompleteListener(task - > {
    if (task.isSuccessful()) {
        // Handle success
        if(task.getResult()) {
          // Service is available on the device, proceed with content publish
          // calls.
        } else {
          // Service is not available, no further action is needed.
        }
    } else {
      // The IPC call itself fails, proceed with error handling logic here,
      // such as retry.
    }
});

publishRecommendationClusters

تُستخدَم واجهة برمجة التطبيقات هذه لنشر قائمة بعناصر RecommendationCluster.

Kotlin

client.publishRecommendationClusters(
            PublishRecommendationClustersRequest.Builder()
                .addRecommendationCluster(
                    RecommendationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .setTitle("Reconnect with yourself")
                        .build())
                .build())

Java

client.publishRecommendationClusters(
            new PublishRecommendationClustersRequest.Builder()
                .addRecommendationCluster(
                    new RecommendationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .setTitle("Reconnect with yourself")
                        .build())
                .build());

عندما تتلقّى الخدمة الطلب، يتم تنفيذ الإجراءات التالية في معاملة واحدة:

  • تتم إزالة بيانات RecommendationCluster الحالية من حساب المطوّر الشريك.
  • يتم تحليل البيانات الواردة من الطلب وتخزينها في مجموعة اقتراحات محدَّثة.

في حال حدوث خطأ، يتم رفض الطلب بأكمله ويتم الحفاظ على الحالة الحالية.

publishFeaturedCluster

تُستخدَم واجهة برمجة التطبيقات هذه لنشر قائمة بعناصر FeaturedCluster.

Kotlin

client.publishFeaturedCluster(
            PublishFeaturedClusterRequest.Builder()
                .setFeaturedCluster(
                    FeaturedCluster.Builder()
                        ...
                        .build())
                .build())

Java

client.publishFeaturedCluster(
            new PublishFeaturedClusterRequest.Builder()
                .setFeaturedCluster(
                    new FeaturedCluster.Builder()
                        ...
                        .build())
                .build());

عندما تتلقّى الخدمة الطلب، يتم تنفيذ الإجراءات التالية في معاملة واحدة:

  • تتم إزالة بيانات FeaturedCluster الحالية من حساب المطوّر الشريك.
  • يتم تحليل البيانات من الطلب وتخزينها في "المجموعة المميّزة" المعدَّلة.

في حال حدوث خطأ، يتم رفض الطلب بأكمله ويتم الحفاظ على الحالة الحالية.

publishContinuationCluster

يتم استخدام واجهة برمجة التطبيقات هذه لنشر عنصر ContinuationCluster.

Kotlin

client.publishContinuationCluster(
            PublishContinuationClusterRequest.Builder()
                .setContinuationCluster(
                    ContinuationCluster.Builder()
                        .addEntity(book_entity1)
                        .addEntity(book_entity2)
                        .build())
                .build())

Java

client.publishContinuationCluster(
            PublishContinuationClusterRequest.Builder()
                .setContinuationCluster(
                    ContinuationCluster.Builder()
                        .addEntity(book_entity1)
                        .addEntity(book_entity2)
                        .build())
                .build())

عندما تتلقّى الخدمة الطلب، يتم تنفيذ الإجراءات التالية في معاملة واحدة:

  • تتم إزالة بيانات ContinuationCluster الحالية من حساب المطوّر الشريك.
  • يتم تحليل البيانات الواردة من الطلب وتخزينها في Continuation Cluster المعدَّل.

في حال حدوث خطأ، يتم رفض الطلب بأكمله ويتم الحفاظ على الحالة الحالية.

publishUserAccountManagementRequest

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

تشكّل البيانات الوصفية التالية جزءًا من "بطاقة تسجيل الدخول":

السمة المتطلبات الوصف
معرّف الموارد المنتظم (URI) للإجراء مطلوب رابط لصفحة تسجيل الدخول إلى التطبيق
صورة اختياري - إذا لم يتم توفيرها، يجب توفير العنوان

الصورة المعروضة على البطاقة

صور بنسبة عرض إلى ارتفاع 16:9 وبدرجة دقة 1264x712

العنوان اختياري - إذا لم يتم توفيرها، يجب توفير الصورة العنوان المكتوب على البطاقة
نص الحث على اتّخاذ إجراء اختياري النص المعروض على عبارة الحثّ على اتّخاذ إجراء (مثل تسجيل الدخول)
العنوان الفرعي اختياري عنوان فرعي اختياري على البطاقة

Kotlin

var SIGN_IN_CARD_ENTITY =
      SignInCardEntity.Builder()
          .addPosterImage(
              Image.Builder()
                  .setImageUri(Uri.parse("http://www.x.com/image.png"))
                  .setImageHeightInPixel(500)
                  .setImageWidthInPixel(500)
                  .build())
          .setActionText("Sign In")
          .setActionUri(Uri.parse("http://xx.com/signin"))
          .build()

client.publishUserAccountManagementRequest(
            PublishUserAccountManagementRequest.Builder()
                .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
                .build());

Java

SignInCardEntity SIGN_IN_CARD_ENTITY =
      new SignInCardEntity.Builder()
          .addPosterImage(
              new Image.Builder()
                  .setImageUri(Uri.parse("http://www.x.com/image.png"))
                  .setImageHeightInPixel(500)
                  .setImageWidthInPixel(500)
                  .build())
          .setActionText("Sign In")
          .setActionUri(Uri.parse("http://xx.com/signin"))
          .build();

client.publishUserAccountManagementRequest(
            new PublishUserAccountManagementRequest.Builder()
                .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
                .build());

عندما تتلقّى الخدمة الطلب، يتم تنفيذ الإجراءات التالية في معاملة واحدة:

  • تتم إزالة بيانات UserAccountManagementCluster الحالية من الشريك المطوِّر.
  • يتم تحليل البيانات من الطلب وتخزينها في مجموعة UserAccountManagementCluster المعدَّلة.

في حال حدوث خطأ، يتم رفض الطلب بأكمله ويتم الحفاظ على الحالة الحالية.

updatePublishStatus

إذا لم يتم نشر أي من المجموعات لأي سبب تجاري داخلي، ننصحك بشدة بتعديل حالة النشر باستخدام واجهة برمجة التطبيقات updatePublishStatus. هذا مهم للأسباب التالية :

  • من المهم تقديم الحالة في جميع السيناريوهات، حتى عندما يكون المحتوى منشورًا (STATUS == PUBLISHED)، وذلك لملء لوحات البيانات التي تستخدم هذه الحالة الواضحة لنقل معلومات حول سلامة عملية الدمج ومقاييس أخرى.
  • إذا لم يتم نشر أي محتوى ولكن حالة الدمج لم تتوقف (STATUS == NOT_PUBLISHED)، يمكن أن تتجنّب Google إرسال تنبيهات في لوحات بيانات سلامة التطبيق. ويؤكّد هذا الرمز أنّ المحتوى لم يتم نشره بسبب حالة متوقّعة من وجهة نظر مقدّم الخدمة.
  • ويساعد المطوّرين في تقديم إحصاءات حول وقت نشر البيانات ووقت عدم نشرها.
  • قد تستخدم Google رموز الحالة لتشجيع المستخدم على اتّخاذ إجراءات معيّنة في التطبيق كي يتمكّن من الاطّلاع على محتوى التطبيق أو التغلّب على المشكلة.

في ما يلي قائمة برموز حالة النشر المؤهَّلة :

// Content is published
AppEngagePublishStatusCode.PUBLISHED,

// Content is not published as user is not signed in
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN,

// Content is not published as user is not subscribed
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SUBSCRIPTION,

// Content is not published as user location is ineligible
AppEngagePublishStatusCode.NOT_PUBLISHED_INELIGIBLE_LOCATION,

// Content is not published as there is no eligible content
AppEngagePublishStatusCode.NOT_PUBLISHED_NO_ELIGIBLE_CONTENT,

// Content is not published as the feature is disabled by the client
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_FEATURE_DISABLED_BY_CLIENT,

// Content is not published as the feature due to a client error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_CLIENT_ERROR,

// Content is not published as the feature due to a service error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_SERVICE_ERROR,

// Content is not published due to some other reason
// Reach out to engage-developers@ before using this enum.
AppEngagePublishStatusCode.NOT_PUBLISHED_OTHER

إذا لم يتم نشر المحتوى لأنّ المستخدم لم يسجّل الدخول، تنصح Google بنشر "بطاقة تسجيل الدخول". إذا تعذّر على مقدّمي الخدمة نشر بطاقة تسجيل الدخول لأي سبب، ننصحك باستخدام واجهة برمجة التطبيقات updatePublishStatus مع رمز الحالة NOT_PUBLISHED_REQUIRES_SIGN_IN.

Kotlin

client.updatePublishStatus(
   PublishStatusRequest.Builder()
     .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
     .build())

Java

client.updatePublishStatus(
    new PublishStatusRequest.Builder()
        .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
        .build());

deleteRecommendationClusters

يتم استخدام واجهة برمجة التطبيقات هذه لحذف محتوى "مجموعات الاقتراحات".

Kotlin

client.deleteRecommendationClusters()

Java

client.deleteRecommendationClusters();

عندما تتلقّى الخدمة الطلب، تزيل البيانات الحالية من "مجموعات الاقتراحات". في حال حدوث خطأ، يتم رفض الطلب بالكامل والاحتفاظ بالحالة الحالية.

deleteFeaturedCluster

يتم استخدام واجهة برمجة التطبيقات هذه لحذف محتوى "المجموعة المميزة".

Kotlin

client.deleteFeaturedCluster()

Java

client.deleteFeaturedCluster();

عندما تتلقّى الخدمة الطلب، تزيل البيانات الحالية من &quot;المجموعة المميزة&quot;. في حال حدوث خطأ، يتم رفض الطلب بالكامل والاحتفاظ بالحالة الحالية.

deleteContinuationCluster

تُستخدَم واجهة برمجة التطبيقات هذه لحذف محتوى مجموعة مواصلة.

Kotlin

client.deleteContinuationCluster()

Java

client.deleteContinuationCluster();

عندما تتلقّى الخدمة الطلب، تزيل البيانات الحالية من مجموعة استمرار المحادثة. في حال حدوث خطأ، يتم رفض الطلب بالكامل والاحتفاظ بالحالة الحالية.

deleteUserManagementCluster

تُستخدَم واجهة برمجة التطبيقات هذه لحذف محتوى مجموعة UserAccountManagement.

Kotlin

client.deleteUserManagementCluster()

Java

client.deleteUserManagementCluster();

عندما تتلقّى الخدمة الطلب، تزيل البيانات الحالية من مجموعة UserAccountManagement. في حال حدوث خطأ، سيتم رفض الطلب بأكمله وسيتم الحفاظ على الحالة الحالية.

deleteClusters

تُستخدَم واجهة برمجة التطبيقات هذه لحذف محتوى نوع مجموعة معيّن.

Kotlin

client.deleteClusters(
    DeleteClustersRequest.Builder()
      .addClusterType(ClusterType.TYPE_FEATURED)
      .addClusterType(ClusterType.TYPE_RECOMMENDATION)
      ...
      .build())

Java

client.deleteClusters(
            new DeleteClustersRequest.Builder()
                .addClusterType(ClusterType.TYPE_FEATURED)
                .addClusterType(ClusterType.TYPE_RECOMMENDATION)
                ...
                .build());

عندما تتلقّى الخدمة الطلب، تزيل البيانات الحالية من جميع المجموعات المتطابقة مع أنواع المجموعات المحدّدة. يمكن للعملاء اختيار تمرير نوع واحد أو عدة أنواع من المجموعات. في حال حدوث خطأ، يتم رفض الطلب بأكمله ويتم الحفاظ على الحالة الحالية.

معالجة الأخطاء

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

client.publishRecommendationClusters(
              new PublishRecommendationClustersRequest.Builder()
                  .addRecommendationCluster(...)
                  .build())
          .addOnCompleteListener(
              task -> {
                if (task.isSuccessful()) {
                  // do something
                } else {
                  Exception exception = task.getException();
                  if (exception instanceof AppEngageException) {
                    @AppEngageErrorCode
                    int errorCode = ((AppEngageException) exception).getErrorCode();
                    if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
                      // do something
                    }
                  }
                }
              });

يتم عرض الخطأ كـ AppEngageException مع تضمين السبب كرمز خطأ.

رمز الخطأ اسم الخطأ ملاحظة
1 SERVICE_NOT_FOUND الخدمة غير متاحة على الجهاز المحدّد.
2 SERVICE_NOT_AVAILABLE الخدمة متاحة على الجهاز المحدّد، ولكنّها غير متاحة في وقت المكالمة (على سبيل المثال، تم إيقافها بشكل صريح).
3 SERVICE_CALL_EXECUTION_FAILURE تعذّر تنفيذ المَهمّة بسبب مشاكل في سلاسل المحادثات. في هذه الحالة، يمكن إعادة المحاولة.
4 SERVICE_CALL_PERMISSION_DENIED لا يُسمح للمتصل بإجراء مكالمة الخدمة.
5 SERVICE_CALL_INVALID_ARGUMENT يحتوي الطلب على بيانات غير صالحة (على سبيل المثال، أكثر من عدد المجموعات المسموح به).
6 SERVICE_CALL_INTERNAL حدث خطأ من جهة الخدمة.
7 SERVICE_CALL_RESOURCE_EXHAUSTED يتم إجراء مكالمة الخدمة بشكل متكرّر جدًا.

الخطوة 3: معالجة أغراض البث

بالإضافة إلى إجراء طلبات البيانات من واجهة برمجة التطبيقات لنشر المحتوى من خلال مهمة، يجب أيضًا إعداد BroadcastReceiver لتلقّي طلب نشر المحتوى.

الغرض من أغراض البث هو بشكل أساسي إعادة تفعيل التطبيق وفرض مزامنة البيانات. لم يتم تصميم مكوّنات intent للبث لإرسالها بشكل متكرر جدًا. لا يتم تشغيلها إلا عندما تحدّد &quot;خدمة التفاعل&quot; أنّ المحتوى قد يكون قديمًا (على سبيل المثال، مضى أسبوع على نشره). بهذه الطريقة، تزداد الثقة في أنّ المستخدم سيحصل على تجربة محتوى جديدة، حتى إذا لم يتم تنفيذ التطبيق لفترة طويلة من الوقت.

يجب إعداد BroadcastReceiver بإحدى الطريقتَين التاليتَين:

  • تسجيل مثيل لفئة BroadcastReceiver بشكل ديناميكي باستخدام Context.registerReceiver() يتيح هذا الإذن التواصل من التطبيقات التي لا تزال نشطة في الذاكرة.

Kotlin

class AppEngageBroadcastReceiver : BroadcastReceiver(){
  // Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
  // is received
  // Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received
  // Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is
  // received
}

fun registerBroadcastReceivers(context: Context){
  var  context = context
  context = context.applicationContext

// Register Recommendation Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_RECOMMENDATION),
                           com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                           /*scheduler=*/null)

// Register Featured Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_FEATURED),
                           com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                           /*scheduler=*/null)

// Register Continuation Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_CONTINUATION),
                           com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                           /*scheduler=*/null)
}

Java

class AppEngageBroadcastReceiver extends BroadcastReceiver {
// Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
// is received

// Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received

// Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is
// received
}

public static void registerBroadcastReceivers(Context context) {

context = context.getApplicationContext();

// Register Recommendation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
                         new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_RECOMMENDATION),
                         com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                         /*scheduler=*/null);

// Register Featured Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
                         new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_FEATURED),
                         com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                         /*scheduler=*/null);

// Register Continuation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
                         new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_CONTINUATION),
                         com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                         /*scheduler=*/null);

}
  • عليك تعريف عملية التنفيذ بشكل ثابت باستخدام العلامة <receiver> في ملف AndroidManifest.xml. يسمح هذا الإذن للتطبيق بتلقّي نوايا البث عندما لا يكون قيد التشغيل، كما يسمح للتطبيق بنشر المحتوى.

<application>
   <receiver
      android:name=".AppEngageBroadcastReceiver"
      android:permission="com.google.android.engage.REQUEST_ENGAGE_DATA"
      android:exported="true"
      android:enabled="true">
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_RECOMMENDATION" />
      </intent-filter>
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_FEATURED" />
      </intent-filter>
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_CONTINUATION" />
      </intent-filter>
   </receiver>
</application>

سيتم إرسال الأهداف التالية من خلال الخدمة:

  • com.google.android.engage.action.PUBLISH_RECOMMENDATION يُنصح ببدء مكالمة publishRecommendationClusters عند تلقّي هذا الغرض.
  • com.google.android.engage.action.PUBLISH_FEATURED يُنصح ببدء مكالمة publishFeaturedCluster عند تلقّي هذا الغرض.
  • com.google.android.engage.action.PUBLISH_CONTINUATIONIt is recommended to start apublishContinuationCluster` call when receiving this intent.

سير عمل الدمج

للحصول على دليل تفصيلي حول كيفية إثبات صحة عملية الدمج بعد اكتمالها، يُرجى الاطّلاع على سير عمل دمج المطوّرين في "تفاعل Google".

الأسئلة الشائعة

يمكنك الاطّلاع على الأسئلة الشائعة حول Engage SDK.

معلومات الاتصال

يُرجى التواصل مع engage-developers@google.com إذا كانت لديك أي أسئلة أثناء عملية الدمج. سيردّ فريقنا عليك في أقرب وقت ممكن.

الخطوات التالية

بعد إكمال عملية الربط هذه، إليك الخطوات التالية:

  • أرسِل رسالة إلكترونية إلى engage-developers@google.com وأرفِق بها حِزمة APK المدمَجة الجاهزة للاختبار من قِبل Google.
  • ستُجري Google عملية تحقّق ومراجعة داخليًا للتأكّد من أنّ عملية الدمج تعمل على النحو المتوقّع. إذا كانت هناك حاجة إلى إجراء تغييرات، ستتواصل معك Google لإطلاعك على التفاصيل اللازمة.
  • عند اكتمال الاختبار وعدم الحاجة إلى إجراء أي تغييرات، ستتواصل معك Google لإعلامك بأنّه يمكنك بدء نشر حِزمة APK المعدَّلة والمدمجة على &quot;متجر Play&quot;.
  • بعد أن يؤكّد Google أنّه تم نشر حزمة APK المعدَّلة على &quot;متجر Play&quot;، سيتم نشر المجموعات مقترَحة ومميّزة ومتابعة وإتاحتها للمستخدمين.