إعداد تطبيق عميل "المراسلة عبر السحابة الإلكترونية من Firebase" على Android

يحتاج عملاء FCM إلى أجهزة تعمل بالإصدار 4.4 من نظام التشغيل Android أو إصدار أحدث، ومثبّت عليها تطبيق "متجر Google Play" أيضًا، أو محاكي يعمل بالإصدار 4.4 من نظام التشغيل Android مع واجهات Google APIs. يُرجى ملاحظة أنّه لا تقتصر على نشر تطبيقات Android من خلال متجر Google Play.

إعداد حزمة تطوير البرامج (SDK)

يتناول هذا القسم المهام التي قد تكون أكملتها إذا سبق لك تفعيل ميزات Firebase الأخرى لتطبيقك. إذا لم يسبق لك إجراء ذلك، يمكنك إضافة Firebase إلى مشروع Android

تعديل بيان التطبيق

أضِف ما يلي إلى بيان التطبيق:

  • خدمة تمتد إلى FirebaseMessagingService. يجب تنفيذ هذا الإجراء إذا كنت تريد التعامل مع أي رسالة خارج نطاق تلقّي الإشعارات على التطبيقات في الخلفية. لتلقّي الإشعارات في التطبيقات التي تعمل في المقدّمة ولتلقّي حمولة البيانات وإرسال الرسائل الرئيسية وما إلى ذلك، عليك توسيع نطاق هذه الخدمة.
  • <service
        android:name=".java.MyFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
  • (اختياري) ضمن مكوِّن التطبيق، عناصر البيانات الوصفية لضبط رمز تلقائي للإشعار ولونه. يستخدم Android هذه القيم عندما لا تضبط الرسائل الواردة الرمز أو اللون بشكل صريح.
  • <!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
         See README(https://goo.gl/l4GJaQ) for more. -->
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_stat_ic_notification" />
    <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
         notification message. See README(https://goo.gl/6BKBk7) for more. -->
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorAccent" />
  • (اختياري) بدءًا من نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) والإصدارات الأحدث، أصبحت قنوات الإشعارات متاحة ويُنصح بها. توفّر خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" قناة إشعارات تلقائية مع إعدادات أساسية. إذا أردت إنشاء قناتك التلقائية واستخدامها، يجب ضبط default_notification_channel_id على معرّف عنصر قناة الإشعارات كما هو موضّح، وستستخدم خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" هذه القيمة عندما لا تحدّد الرسائل الواردة قناة إشعارات بشكل صريح. لمزيد من المعلومات، يُرجى الاطّلاع على القسم إدارة قنوات الإشعارات.
  • <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id" />

طلب إذن إرسال الإشعارات في بيئة التشغيل على الإصدار 13 من نظام التشغيل Android أو الإصدارات الأحدث

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

تتضمّن حزمة تطوير البرامج (SDK) لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase" (الإصدار 23.0.6 أو الإصدارات الأحدث) تلقائيًا إذن POST_NOTIFICATIONS المحدَّد في البيان. ومع ذلك، سيحتاج تطبيقك أيضًا إلى طلب إصدار بيئة التشغيل لهذا الإذن من خلال android.permission.POST_NOTIFICATIONS الثابت. ولن يُسمَح لتطبيقك بعرض الإشعارات إلى أن يمنح المستخدم هذا الإذن.

لطلب إذن التشغيل الجديد:

Kotlin+KTX

// Declare the launcher at the top of your Activity/Fragment:
private val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission(),
) { isGranted: Boolean ->
    if (isGranted) {
        // FCM SDK (and your app) can post notifications.
    } else {
        // TODO: Inform user that that your app will not show notifications.
    }
}

private fun askNotificationPermission() {
    // This is only necessary for API level >= 33 (TIRAMISU)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
            PackageManager.PERMISSION_GRANTED
        ) {
            // FCM SDK (and your app) can post notifications.
        } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
            // TODO: display an educational UI explaining to the user the features that will be enabled
            //       by them granting the POST_NOTIFICATION permission. This UI should provide the user
            //       "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.
            //       If the user selects "No thanks," allow the user to continue without notifications.
        } else {
            // Directly ask for the permission
            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
        }
    }
}

Java

// Declare the launcher at the top of your Activity/Fragment:
private final ActivityResultLauncher<String> requestPermissionLauncher =
        registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
            if (isGranted) {
                // FCM SDK (and your app) can post notifications.
            } else {
                // TODO: Inform user that that your app will not show notifications.
            }
        });

private void askNotificationPermission() {
    // This is only necessary for API level >= 33 (TIRAMISU)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
                PackageManager.PERMISSION_GRANTED) {
            // FCM SDK (and your app) can post notifications.
        } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
            // TODO: display an educational UI explaining to the user the features that will be enabled
            //       by them granting the POST_NOTIFICATION permission. This UI should provide the user
            //       "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.
            //       If the user selects "No thanks," allow the user to continue without notifications.
        } else {
            // Directly ask for the permission
            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
        }
    }
}

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

يمكنك الاطّلاع على إذن تشغيل الإشعارات للحصول على مزيد من أفضل الممارسات حول الحالات التي يجب أن يطلب فيها تطبيقك إذن POST_NOTIFICATIONS من المستخدم.

أذونات إرسال الإشعارات للتطبيقات التي تستهدف الإصدار 12L من Android (المستوى 32 لواجهة برمجة التطبيقات) أو الإصدارات الأقدم

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

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

اختياري: إزالة إذن "POST_NOTIFICATIONS"

تتضمّن حزمة تطوير البرامج (SDK) لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase" تلقائيًا إذن POST_NOTIFICATIONS. إذا كان تطبيقك لا يستخدم رسائل الإشعارات (سواء من خلال إشعارات "المراسلة عبر السحابة الإلكترونية من Firebase" أو من خلال حزمة تطوير برامج (SDK) أخرى أو نشرها تطبيقك مباشرةً) ولا تريد أن يتضمّن تطبيقك الإذن، يمكنك إزالته باستخدام علامة remove دمج البيان. يُرجى العلم أنّ إزالة هذا الإذن ستؤدي إلى منع عرض جميع الإشعارات، وليس فقط إشعارات خدمة "المراسلة عبر السحابة الإلكترونية من Firebase". أضف ما يلي إلى ملف بيان تطبيقك:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" tools:node="remove"/>

الوصول إلى الرمز المميّز لتسجيل الجهاز

عند بدء تشغيل التطبيق للمرة الأولى، تُنشئ حزمة تطوير البرامج (SDK) لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase" رمزًا مميّزًا للتسجيل لمثيل تطبيق العميل. إذا كنت ترغب في استهداف أجهزة فردية أو إنشاء مجموعات أجهزة، عليك الوصول إلى هذا الرمز من خلال تمديد FirebaseMessagingService وتجاوز onNewToken.

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

قد يتغيّر الرمز المميّز للتسجيل في الحالات التالية:

  • تتم استعادة التطبيق على جهاز جديد.
  • يلغي المستخدم تثبيت التطبيق أو يعيد تثبيته
  • يمحو المستخدم بيانات التطبيق.

استرداد الرمز المميّز للتسجيل الحالي

عند الحاجة إلى استرداد الرمز المميّز الحالي، عليك طلب FirebaseMessaging.getInstance().getToken():

Kotlin+KTX

FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
    if (!task.isSuccessful) {
        Log.w(TAG, "Fetching FCM registration token failed", task.exception)
        return@OnCompleteListener
    }

    // Get new FCM registration token
    val token = task.result

    // Log and toast
    val msg = getString(R.string.msg_token_fmt, token)
    Log.d(TAG, msg)
    Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
})

Java

FirebaseMessaging.getInstance().getToken()
    .addOnCompleteListener(new OnCompleteListener<String>() {
        @Override
        public void onComplete(@NonNull Task<String> task) {
          if (!task.isSuccessful()) {
            Log.w(TAG, "Fetching FCM registration token failed", task.getException());
            return;
          }

          // Get new FCM registration token
          String token = task.getResult();

          // Log and toast
          String msg = getString(R.string.msg_token_fmt, token);
          Log.d(TAG, msg);
          Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
        }
    });

تتبُّع عملية إنشاء الرموز المميّزة

يتم تنشيط معاودة الاتصال onNewToken عند إنشاء رمز مميّز جديد.

Kotlin+KTX

/**
 * Called if the FCM registration token is updated. This may occur if the security of
 * the previous token had been compromised. Note that this is called when the
 * FCM registration token is initially generated so this is where you would retrieve the token.
 */
override fun onNewToken(token: String) {
    Log.d(TAG, "Refreshed token: $token")

    // If you want to send messages to this application instance or
    // manage this apps subscriptions on the server side, send the
    // FCM registration token to your app server.
    sendRegistrationToServer(token)
}

Java

/**
 * There are two scenarios when onNewToken is called:
 * 1) When a new token is generated on initial app startup
 * 2) Whenever an existing token is changed
 * Under #2, there are three scenarios when the existing token is changed:
 * A) App is restored to a new device
 * B) User uninstalls/reinstalls the app
 * C) User clears app data
 */
@Override
public void onNewToken(@NonNull String token) {
    Log.d(TAG, "Refreshed token: " + token);

    // If you want to send messages to this application instance or
    // manage this apps subscriptions on the server side, send the
    // FCM registration token to your app server.
    sendRegistrationToServer(token);
}

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

التحقّق من توفّر "خدمات Google Play"

يجب أن تتحقّق التطبيقات التي تعتمد على "حزمة SDK لخدمات Play" دائمًا من وجود حزمة APK متوافقة لخدمات Google Play في الجهاز قبل الوصول إلى ميزات "خدمات Google Play". ويُنصح بتنفيذ هذا الإجراء في موضعَين: في طريقة onCreate() للنشاط الرئيسي، وفي طريقة onResume(). تضمن عملية التحقّق في onCreate() عدم استخدام التطبيق بدون إجراء عملية فحص ناجحة. تضمن عملية التحقّق في onResume() أنّه في حال عودة المستخدم إلى التطبيق قيد التشغيل باستخدام وسائل أخرى، مثل النقر على زر الرجوع، سيستمرّ التحقّق.

إذا لم يكن الجهاز مزوّدًا بإصدار متوافق من "خدمات Google Play"، يمكن لتطبيقك الاتصال بـ GoogleApiAvailability.makeGooglePlayServicesAvailable() للسماح للمستخدمين بتنزيل "خدمات Google Play" من "متجر Play".

منع الإعداد التلقائي

عند إنشاء رمز مميّز للتسجيل عبر خدمة "المراسلة عبر السحابة الإلكترونية من Firebase"، تحمّل المكتبة المعرّف وبيانات الإعداد إلى Firebase. إذا كنت تفضّل منع الإنشاء التلقائي للرموز المميّزة، أوقِف جمع "إحصاءات Google" والإعداد التلقائي لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase" (يجب إيقاف كليهما) من خلال إضافة قيم البيانات الوصفية التالية إلى AndroidManifest.xml:

<meta-data
    android:name="firebase_messaging_auto_init_enabled"
    android:value="false" />
<meta-data
    android:name="firebase_analytics_collection_enabled"
    android:value="false" />

لإعادة تفعيل التشغيل التلقائي لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase"، عليك إجراء مكالمة في بيئة التشغيل:

Kotlin+KTX

Firebase.messaging.isAutoInitEnabled = true

Java

FirebaseMessaging.getInstance().setAutoInitEnabled(true);

لإعادة تفعيل جمع البيانات في "إحصاءات Google"، يجب استدعاء الطريقة setAnalyticsCollectionEnabled() للفئة FirebaseAnalytics. على سبيل المثال:

setAnalyticsCollectionEnabled(true);

وتظل هذه القيم سارية في جميع عمليات إعادة تشغيل التطبيق بعد ضبطها.

الخطوات اللاحقة

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

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

يُرجى العلم أنّه للاستفادة من هذه الميزات، ستحتاج إلى تنفيذ خادم وخوادم وكيل الخادم (HTTP أو XMPP) أو تنفيذ SDK للمشرف.