הגדרה של אפליקציית לקוח להעברת הודעות בענן ב-Firebase ב-Android

לקוחות FCM דורשים מכשירים עם Android מגרסה 5.0 ואילך, שבהם מותקנת גם אפליקציית חנות Play, או אמולטור עם Android מגרסה 5.0 עם ממשקי Google API. חשוב לזכור שאתם לא מוגבלים לפריסה של אפליקציות ל-Android דרך חנות Google Play.

הגדרת ה-SDK

בקטע הזה מפורטות משימות שאולי כבר ביצעתם אם כבר הפעלתם תכונות אחרות של Firebase באפליקציה. אם עדיין לא עשיתם זאת, מוסיפים את Firebase לפרויקט Android.

עריכת המניפסט של האפליקציה

מוסיפים את הקוד הבא למניפסט של האפליקציה:

  • שירות שמרחיב את FirebaseMessagingService. צריך לעשות זאת אם רוצים לבצע טיפול בהודעות מעבר לקבלת התראות באפליקציות שפועלות ברקע. כדי לקבל התראות באפליקציות שבחזית, לקבל עומס נתונים, לשלוח הודעות למקור (upstream) וכו', צריך להרחיב את השירות הזה.
  • <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 (רמת API 26) ואילך, ערוצי התראות נתמכים ומומלצים. FCM מספק ערוץ התראות בברירת מחדל עם הגדרות בסיסיות. אם אתם מעדיפים ליצור ערוץ ברירת מחדל משלכם ולהשתמש בו, צריך להגדיר את default_notification_channel_id למזהה של אובייקט ערוץ ההתראות, כפי שמוצג. הערך הזה ישמש את FCM בכל פעם שמסרים נכנסים לא מגדירים באופן מפורש ערוץ התראות. למידע נוסף, קראו את המאמר ניהול ערוצי התראות.
  • <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id" />

שליחת בקשה להרשאה לקבלת התראות בזמן ריצה ב-Android מגרסה 13 ואילך

ב-Android 13 נוספה הרשאה חדשה בסביבת זמן הריצה להצגת התראות. השינוי הזה משפיע על כל האפליקציות שפועלות ב-Android מגרסה 13 ואילך ומשתמשות בהתראות FCM.

כברירת מחדל, ה-SDK של FCM (גרסה 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);
        }
    }
}

באופן כללי, צריך להציג ממשק משתמש שבו מוסבר למשתמש אילו תכונות יופעלו אם הן מעניקות הרשאות לאפליקציה לפרסם התראות. ממשק המשתמש הזה צריך לספק למשתמשים אפשרויות לאשר או לדחות, כמו לחצנים של אישור ולא תודה. אם המשתמש בוחר OK, צריך לבקש את ההרשאה ישירות. אם המשתמש בוחר באפשרות לא תודה, מאפשרים לו להמשיך בלי התראות.

במאמר הרשאה בתחילת ההפעלה של התראות מפורטות שיטות מומלצות נוספות לגבי מתי האפליקציה צריכה לבקש את ההרשאה POST_NOTIFICATIONS מהמשתמש.

הרשאות לשליחת התראות באפליקציות שמטרגטות את Android 12L (רמת API 32) ומטה

מערכת Android מבקשת מהמשתמש הרשאה באופן אוטומטי בפעם הראשונה שהאפליקציה יוצרת ערוץ התראות, כל עוד האפליקציה בחזית. עם זאת, יש אזהרות חשובות לגבי התזמון של יצירת הערוץ ושל בקשות להרשאות:

  • אם האפליקציה יוצרת את ערוץ ההתראות הראשון שלה כשהיא פועלת ברקע (כפי ש-SDK של FCM עושה כשמתקבלת התראה של FCM), מערכת Android לא תאפשר להצגת ההתראה ולא תציג למשתמש בקשה להענקת הרשאת התראות עד הפעם הבאה שהאפליקציה תיפתח. המשמעות היא שכל ההתראות שהתקבלו לפני שהאפליקציה נפתחה והמשתמש מאשר את ההרשאה יאבדו.
  • מומלץ מאוד לעדכן את האפליקציה כך שתתמקד ב-Android 13 ואילך, כדי ליהנות מממשקי ה-API של הפלטפורמה ולבקש הרשאה. אם זה לא אפשרי, על האפליקציה ליצור ערוצי התראות לפני שליחת התראות לאפליקציה, כדי להפעיל את תיבת הדו-שיח של ההרשאות לשליחת התראות ולוודא שההתראות לא נמחקות. מידע נוסף זמין במאמר שיטות מומלצות לשימוש בהרשאות לשליחת התראות.

אופציונלי: הסרת ההרשאה POST_NOTIFICATIONS

כברירת מחדל, ה-SDK של FCM כולל את ההרשאה POST_NOTIFICATIONS. אם האפליקציה לא משתמשת בהתראות (דרך התראות FCM, דרך ערכת SDK אחרת או דרך הודעות שפרסמה האפליקציה ישירות) ואתם לא רוצים שהאפליקציה תכלול את ההרשאה, תוכלו להסיר אותה באמצעות הסמן remove של מיזוג המניפסטים. חשוב לזכור שהסרת ההרשאה הזו מונעת את ההצגה של כל ההתראות, ולא רק של FCM התראות. מוסיפים את הטקסט הבא לקובץ המניפסט של האפליקציה:

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

גישה לטוקן הרישום של המכשיר

בהפעלה הראשונית של האפליקציה, ה-SDK של FCM יוצר אסימון רישום למכונה של אפליקציית הלקוח. כדי לטרגט מכשירים בודדים או ליצור קבוצות מכשירים, יהיה צורך לגשת לאסימון הזה על ידי הרחבה של 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 Services מותקן

אפליקציות שמסתמכות על Play Services SDK צריכות תמיד לבדוק במכשיר אם יש קובץ APK תואם של Google Play Services לפני שהן ניגשות לתכונות של Google Play Services. מומלץ לעשות זאת בשני מקומות: ב-method‏ onCreate() של הפעילות הראשית וב-method‏ onResume() שלה. הבדיקה ב-onCreate() מבטיחה שלא ניתן להשתמש באפליקציה בלי בדיקה מוצלחת. הבדיקה ב-onResume() מבטיחה שאם המשתמש יחזור לאפליקציה שפועלת באמצעים אחרים, למשל באמצעות לחצן החזרה אחורה, הבדיקה עדיין תתבצע.

אם במכשיר לא מותקנת גרסה תואמת של Google Play Services, האפליקציה יכולה להפעיל את GoogleApiAvailability.makeGooglePlayServicesAvailable() כדי לאפשר למשתמשים להוריד את Google Play Services מחנות Play.

מניעת אתחול אוטומטי

כשיוצרים אסימון רישום מסוג FCM, הספרייה מעלה את המזהה ונתוני ההגדרה ל-Firebase. אם מעדיפים למנוע יצירה אוטומטית של אסימונים, צריך להשבית את איסוף הנתונים ב-Analytics ואת האתחול האוטומטי של FCM (צריך להשבית את שניהם) על ידי הוספת ערכי המטא-נתונים הבאים אל 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" />

כדי להפעיל מחדש את ההפעלה האוטומטית של FCM, צריך לבצע קריאה בסביבת זמן הריצה:

Kotlin+KTX

Firebase.messaging.isAutoInitEnabled = true

Java

FirebaseMessaging.getInstance().setAutoInitEnabled(true);

כדי להפעיל מחדש את האיסוף ב-Analytics, צריך להפעיל את השיטה setAnalyticsCollectionEnabled() של הכיתה FirebaseAnalytics. לדוגמה:

setAnalyticsCollectionEnabled(true);

הערכים האלה נשארים לאחר הפעלה מחדש של האפליקציה.

השלבים הבאים

אחרי שמגדירים את אפליקציית הלקוח, אפשר להתחיל לשלוח הודעות במורד הזרם באמצעות כלי היצירה של התראות. הפונקציונליות הזו מוצגת בדוגמה למתחילים, שאותה אפשר להוריד, להפעיל ולבדוק.

כדי להוסיף לאפליקציה התנהגות מתקדמת יותר, אפשר להצהיר על מסנן כוונה ולהטמיע פעילות כדי להגיב להודעות נכנסות. פרטים נוספים זמינים במדריכים לשליחת הודעות משרת אפליקציה:

חשוב לזכור: כדי ליהנות מהתכונות האלה, תצטרכו הטמעה בשרת ואת הפרוטוקולים של השרת (HTTP או XMPP), או הטמעה של Admin SDK.