# التحديثات المباشرة على Android

يدعم Pushwoosh تحديثات Android المباشرة (Android Live Updates) من خلال وحدة `pushwoosh-liveupdates` (SDK 6.9.0 والإصدارات الأحدث). التحديث المباشر هو إشعار مستمر بنمط التقدم يبرزه النظام على شاشة القفل، وفي درج الإشعارات، وكشريحة حالة في شريط الحالة، حتى يتمكن المستخدمون من متابعة نشاط ما دون فتح تطبيقك.

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

## ما هي التحديثات المباشرة (Live Updates)

تم تقديم التحديثات المباشرة في Android 16 (API 36) كطريقة لإظهار نشاط حساس للوقت يبدأه المستخدم من البداية إلى النهاية. وهي مبنية على إشعارات المنصة التي تركز على التقدم وواجهة برمجة التطبيقات `Notification.ProgressStyle`. من حيث المفهوم، هي النظير في Android لـ Live Activities في iOS.

تغطي هذه الصفحة تكامل Pushwoosh فقط. لسلوك المنصة، وقواعد الترويج، وإرشادات التصميم، راجع وثائق Android الرسمية:

- [إشعارات تتمحور حول التقدم](https://developer.android.com/about/versions/16/features/progress-centric-notifications)
- [إنشاء إشعارات تحديث مباشر (Views)](https://developer.android.com/develop/ui/views/notifications/live-update)
- [إنشاء إشعارات تحديث مباشر (Compose)](https://developer.android.com/develop/ui/compose/notifications/live-update)

## متى تستخدم التحديثات المباشرة

التحديثات المباشرة مخصصة لنشاط مستمر، يبدأه المستخدم، وحساس للوقت — شيء له بداية ونهاية واضحتان يهتم به المستخدم بنشاط في الوقت الحالي. السيناريوهات النموذجية لعملاء Pushwoosh:

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

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

<Aside type="caution">
لا تستخدم التحديثات المباشرة للعروض الترويجية، أو رسائل الدردشة، أو المعلومات المحيطة، ولا تعيد نشر تحديث مباشر رفضه المستخدم. قد يلغي Android قدرة التطبيق على نشر الإشعارات المروجة. اتبع [إرشادات Android بشأن الاستخدام المناسب](https://developer.android.com/develop/ui/views/notifications/live-update#best-practices).
</Aside>

## المتطلبات

- Android 16 (API 36) أو أحدث. على الأجهزة الأقدم، تظل الوحدة غير نشطة وكل استدعاء API للتحديث المباشر هو عملية آمنة لا تفعل شيئًا.
- Pushwoosh Android SDK 6.9.0 أو أحدث.

## أضف وحدة pushwoosh-liveupdates

أضف التبعية إلى ملف **app/build.gradle** الخاص بك:

```groovy
dependencies {
    implementation 'com.pushwoosh:pushwoosh-liveupdates:<latest-version>'
}
```

استبدل `<latest-version>` بالإصدار الحالي من [Maven Central](https://mvnrepository.com/artifact/com.pushwoosh/pushwoosh-liveupdates).

يتم اكتشاف الوحدة تلقائيًا عند بدء التشغيل. تعلن عن الإذن المطلوب `POST_PROMOTED_NOTIFICATIONS`، وتسجل قناة الإشعارات الخاصة بها، وتعترض إشعارات التحديث المباشر قبل مسار الإشعارات الافتراضي. لا يوجد رمز تهيئة إضافي — يقوم SDK بتعيين علامات `ongoing` و`promoted`، وتنزيل الأيقونة الكبيرة، وتعيين أزرار الإجراءات، ونشر الإشعار نيابة عنك.

## إرسال تحديث مباشر

يمكنك إرسال التحديثات المباشرة من خلال [Messaging API v2](/ar/developer/api-reference/messaging-api-v2/) عن طريق إضافة كائن `live_update` إلى كتلة محتوى `android`. استخدم طلبًا `transactional` — يستهدف التحديث المباشر المستخدم المحدد الذي يتتبع نشاطه. حقل `schedule` مطلوب؛ `{ "after": "0s" }` يرسل على الفور. تحتوي دورة الحياة على ثلاث عمليات، يتم تعيينها في `live_update.op`:

- `OPERATION_START` — أول إشعار لنشاط. ينشر الإشعار المستمر.
- `OPERATION_UPDATE` — إشعار لاحق لنفس النشاط. يحدّثه في مكانه، بصمت.
- `OPERATION_END` — إشعار نهائي. يرفض الإشعار.

يجب أن تشترك جميع الإشعارات التي تنتمي إلى نفس النشاط في نفس `live_update.id`. يربط هذا المعرف التحديثات معًا وهو أيضًا ما تستخدمه لرفض التحديث من التطبيق.

يصف كل إشعار بالكامل — لا يتم نقل أي شيء من الإشعار السابق. أعد إرسال كل حقل تريد الاحتفاظ به، مثل الشرائح والأيقونة الكبيرة، مع كل `OPERATION_UPDATE`؛ يتم عرض الحقل المحذوف على أنه غائب.

### معلمات التحديث المباشر

توضع هذه المفاتيح داخل كائن `live_update` في كتلة محتوى `android`. يستخدم العنوان والنص والأيقونة الكبيرة حقول الإشعارات القياسية في Android (`title`, `body`, `custom_icon`)، والتي يتم إرسالها إلى جانب `live_update`.

| المعلمة | النوع | الوصف |
|---|---|---|
| `op` | string | عملية دورة الحياة: `OPERATION_START`، `OPERATION_UPDATE`، أو `OPERATION_END`. مطلوب. |
| `id` | string | معرف نشاط ثابت مشترك بين جميع إشعارات تحديث مباشر واحد. مطلوب. |
| `progress` | int | قيمة التقدم، مقاسة مقابل أطوال الشرائح المجمعة. |
| `progress_indeterminate` | bool | إظهار رسم متحرك غير محدد بدلاً من قيمة ملموسة. |
| `progress_bar` | bool | إظهار شريط التقدم على الإطلاق. الافتراضي هو `true`. |
| `segments` | array | شرائح تقدم مرتبة، كل منها `{ "color": "#RRGGBB", "length": N }`. |
| `extras` | object | بيانات عشوائية يتم تمريرها إلى مزود نمط مخصص. |
| `when` | int64 | مرساة زمنية للرأس، بالمللي ثانية منذ بداية الحقبة. |
| `chronometer` | bool | إظهار وقت الرأس كمؤقت يعمل. |
| `chronometer_count_down` | bool | مؤقت يعمل يعد تنازليًا بدلاً من تصاعدي. |
| `show_when` | bool | إظهار عمود وقت الرأس على الإطلاق. الافتراضي هو `true`. |

<Aside>
يجب أن تكون قيمة `op` أحد أسماء التعداد الدقيقة `OPERATION_START`، `OPERATION_UPDATE`، أو `OPERATION_END` — يتم تجاهل الأشكال المختصرة. يحمل كل حقل نوع JSON الأصلي الخاص به: `segments` هي مصفوفة JSON و`extras` كائن JSON، وليست سلاسل نصية مشفرة.
</Aside>

تتحد حقول الوقت الأربعة على النحو التالي: عند تعيين `show_when` إلى `false` يتم إخفاء الوقت؛ وإلا فإن `when` هو المرساة، و`chronometer` يحوله إلى عداد مباشر، و`chronometer_count_down` يجعل هذا العداد يعمل بشكل عكسي.

### إشعار البدء

```bash
curl -X POST https://api.pushwoosh.com/messaging/v2/notify \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transactional": {
      "application": "XXXXX-XXXXX",
      "platforms": ["ANDROID"],
      "users": { "list": ["customer-42"] },
      "payload": {
        "content": {
          "localized_content": {
            "default": {
              "android": {
                "title": "Order #4521",
                "body": "We are preparing your order",
                "custom_icon": "https://example.com/restaurant.png",
                "live_update": {
                  "op": "OPERATION_START",
                  "id": "order_4521",
                  "progress": 1,
                  "segments": [
                    { "color": "#34A853", "length": 3 },
                    { "color": "#FBBC05", "length": 4 },
                    { "color": "#4285F4", "length": 3 }
                  ],
                  "extras": { "eta": "18:40" }
                }
              }
            }
          }
        }
      },
      "schedule": { "after": "0s" },
      "message_type": "MESSAGE_TYPE_TRANSACTIONAL"
    }
  }'
```

### إشعار التحديث

أرسل `OPERATION_UPDATE` بنفس `id` كلما تقدم النشاط. كرر الشرائح والأيقونة — التحديث الذي يحذفها يتم عرضه بدونها.

```bash
curl -X POST https://api.pushwoosh.com/messaging/v2/notify \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transactional": {
      "application": "XXXXX-XXXXX",
      "platforms": ["ANDROID"],
      "users": { "list": ["customer-42"] },
      "payload": {
        "content": {
          "localized_content": {
            "default": {
              "android": {
                "title": "Order #4521",
                "body": "Your courier is on the way",
                "custom_icon": "https://example.com/restaurant.png",
                "live_update": {
                  "op": "OPERATION_UPDATE",
                  "id": "order_4521",
                  "progress": 7,
                  "segments": [
                    { "color": "#34A853", "length": 3 },
                    { "color": "#FBBC05", "length": 4 },
                    { "color": "#4285F4", "length": 3 }
                  ]
                }
              }
            }
          }
        }
      },
      "schedule": { "after": "0s" },
      "message_type": "MESSAGE_TYPE_TRANSACTIONAL"
    }
  }'
```

### إشعار الإنهاء

يحتاج الإشعار النهائي فقط إلى العملية والمعرف.

```bash
curl -X POST https://api.pushwoosh.com/messaging/v2/notify \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transactional": {
      "application": "XXXXX-XXXXX",
      "platforms": ["ANDROID"],
      "users": { "list": ["customer-42"] },
      "payload": {
        "content": {
          "localized_content": {
            "default": {
              "android": {
                "live_update": {
                  "op": "OPERATION_END",
                  "id": "order_4521"
                }
              }
            }
          }
        }
      },
      "schedule": { "after": "0s" },
      "message_type": "MESSAGE_TYPE_TRANSACTIONAL"
    }
  }'
```

## تخصيص المظهر

يأتي SDK مع نمط تقدم افتراضي مبني من `progress`، `progress_indeterminate`، و`segments`. للتحكم الكامل في شريط التقدم، قم بتنفيذ `LiveUpdateProgressStyleProvider` وشكل `Notification.ProgressStyle` بنفسك.

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

<Tabs>
<TabItem label="Java">
```java
import android.app.Notification;
import androidx.annotation.NonNull;
import com.pushwoosh.liveupdates.LiveUpdateProgressStyleProvider;
import com.pushwoosh.liveupdates.LiveUpdateSegment;
import com.pushwoosh.liveupdates.LiveUpdateState;
import java.util.List;

public class OrderStyleProvider implements LiveUpdateProgressStyleProvider {
    @NonNull
    @Override
    public Notification.ProgressStyle createStyle(@NonNull LiveUpdateState state) {
        Notification.ProgressStyle style = new Notification.ProgressStyle();
        if (state.getProgress() != null) {
            style.setProgress(state.getProgress());
        }
        style.setProgressIndeterminate(state.isProgressIndeterminate());

        List<LiveUpdateSegment> segments = state.getSegments();
        int boundary = 0;
        for (int i = 0; i < segments.size(); i++) {
            LiveUpdateSegment seg = segments.get(i);
            style.addProgressSegment(
                new Notification.ProgressStyle.Segment(seg.getLength()).setColor(seg.getColor()));
            boundary += seg.getLength();
            if (i < segments.size() - 1) {
                style.addProgressPoint(new Notification.ProgressStyle.Point(boundary));
            }
        }
        return style;
    }
}
```
</TabItem>
<TabItem label="Kotlin">
```kotlin
import android.app.Notification
import com.pushwoosh.liveupdates.LiveUpdateProgressStyleProvider
import com.pushwoosh.liveupdates.LiveUpdateState

class OrderStyleProvider : LiveUpdateProgressStyleProvider {
    override fun createStyle(state: LiveUpdateState): Notification.ProgressStyle {
        val style = Notification.ProgressStyle()
        state.progress?.let { style.setProgress(it) }
        style.setProgressIndeterminate(state.isProgressIndeterminate)

        val segments = state.segments
        var boundary = 0
        segments.forEachIndexed { i, seg ->
            style.addProgressSegment(
                Notification.ProgressStyle.Segment(seg.length).setColor(seg.color))
            boundary += seg.length
            if (i < segments.size - 1) {
                style.addProgressPoint(Notification.ProgressStyle.Point(boundary))
            }
        }
        return style
    }
}
```
</TabItem>
</Tabs>

سجل المزود بعلامة `<meta-data>` في **AndroidManifest.xml**. يجب أن يحتوي الفصل على مُنشئ عام بدون وسائط.

```xml
<meta-data
    android:name="com.pushwoosh.LIVE_UPDATE_STYLE_PROVIDER"
    android:value="com.example.OrderStyleProvider" />
```

استخدم `LiveUpdateState.getExtras()` لقراءة JSON الذي أرسلته في `live_update.extras` وتكييف النمط مع بيانات عملك الخاصة.

## إدارة التحديثات المباشرة من تطبيقك

يقود الخادم كل `OPERATION_START`، `OPERATION_UPDATE`، و`OPERATION_END`، لذلك لا توجد واجهة برمجة تطبيقات من جانب التطبيق لنشر أو تحديث تحديث مباشر. تغطي واجهة `PushwooshLiveUpdates` فقط ما لا يستطيع الخادم القيام به — رفض تحديث محليًا والتحقق من التحديثات المعروضة على الشاشة.

```java
import com.pushwoosh.liveupdates.PushwooshLiveUpdates;

// رفض تحديث مباشر معين عندما ينهي المستخدم النشاط داخل التطبيق،
// دون انتظار إشعار "end" النهائي من الخادم
PushwooshLiveUpdates.endLiveUpdate("order_4521");

// سرد معرفات الأنشطة المعروضة حاليًا بواسطة هذا التطبيق
List<String> active = PushwooshLiveUpdates.getActiveIds();

// مسح كل ما يعرضه هذا التطبيق، على سبيل المثال عند تسجيل الخروج
PushwooshLiveUpdates.endAllLiveUpdates();
```

جميع الطرق آمنة للاستدعاء من أي خيط وهي عملية لا تفعل شيئًا على الأجهزة التي تعمل بإصدار أقدم من Android 16.

## روابط ذات صلة

- [نظرة عامة على Pushwoosh Android SDK](/ar/developer/pushwoosh-sdk/android-sdk/)
- [مرجع واجهة برمجة تطبيقات Pushwoosh Android SDK](https://pushwoosh.github.io/pushwoosh-android-sdk/)
- [Messaging API](/ar/developer/api-reference/messaging-api-v2/)
- [إشعارات Android التي تركز على التقدم](https://developer.android.com/about/versions/16/features/progress-centric-notifications)