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

במכשירי לקוח של FCM צריך מערכת Android בגרסה 5.0 ומעלה, שמותקנת בה גם אפליקציית חנות Google Play, או אמולטור עם Android בגרסה 5.0 עם 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 (רמת 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.

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

כדי לבקש את הרשאת זמן הריצה החדשה:

Kotlin

// 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.

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

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

  • אם האפליקציה יוצרת את ערוץ ההתראות הראשון שלה כשהיא פועלת ברקע (כמו שקורה ב-FCM SDK כשמתקבלת התראה של 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"/>

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

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

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

אסימון הרישום עשוי להשתנות במקרים הבאים:

  • האפליקציה משוחזרת במכשיר חדש
  • המשתמש מסיר את האפליקציה ומתקין אותה מחדש
  • המשתמש מוחק את נתוני האפליקציה.

אחזור טוקן הרישום הנוכחי

כשצריך לאחזר את הטוקן הנוכחי, מתקשרים אל FirebaseMessaging.getInstance().getToken():

Kotlin

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();
        }
    });

מעקב אחרי יצירת טוקנים

פונקציית ה-callback‏ onNewToken מופעלת בכל פעם שנוצר טוקן חדש.

Kotlin

/**
 * 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 מותקנים

אפליקציות שמסתמכות על 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

Firebase.messaging.isAutoInitEnabled = true

Java

FirebaseMessaging.getInstance().setAutoInitEnabled(true);

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

setAnalyticsCollectionEnabled(true);

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

השלבים הבאים

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

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

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