FCM HTTP v1 API'den AndroidConfigV2'ye geçiş

FCM AndroidConfigV2 kullanarak Android cihazlara amaca dayalı mesajlar gönderebilir, bildirimleri zamanında teslim edebilir ve basitleştirilmiş bir API'den yararlanabilirsiniz.

Bu kılavuzda, arka uç gönderme isteklerinizi AndroidConfig yerine AndroidConfigV2 kullanacak şekilde nasıl taşıyacağınız ve Android uygulama istemcilerinizi eski onMessageReceived işleme yerine yeni v2 istemci geri çağırmaları onNotificationReceived ve onBackgroundSyncReceived kullanacak şekilde nasıl güncelleyeceğiniz açıklanmaktadır.

AndroidConfigV2'deki yenilikler

FCM AndroidConfigV2 API, iki mesaj türü sunarak geliştirici deneyimini basitleştirir:

  • RemoteNotification: Kullanıcıya acil ve zamana duyarlı bir bildirim gösteren tüm FCM mesajları için önerilir. Bu mesajlar, pil tasarrufu önlemlerini atlar ve gecikme olmadan teslim edilir. Cihazda, FCM SDK'sı ve Google Play Hizmetleri, bildirimi Android'in NotificationManager uygulamasına gönderme işlemini üstlenir.
  • BackgroundSync: Arka plan senkronizasyonu ve uygulama durumu güncellemeleri için tasarlanmış acil olmayan veri mesajları. Pil ömrünü optimize etmek için teslimat toplu olarak yapılabilir veya geciktirilebilir.
Özellik Eski (AndroidConfig v1) Yeni (AndroidConfigV2)
Yapılandırma alanı message.android message.android_v2
Öncelik tanımı Uygunsuz priority: "high" veya priority: "normal" Birleşim türü tarafından ima edilir (acil uyarılar için remote_notification, acil olmayan senkronizasyon için background_sync)
Bildirim yayınlama Uygulama, NotificationManager.notify() yöntemini manuel olarak çağırıyor FCM SDK ve GMS Core yayınları doğrudan veya NotificationResponse kullanılarak
İstemci geri çağırmaları • onMessageReceived(RemoteMessage)
• onDeletedMessages()
• onNotificationReceived(RemoteMessage)
• onBackgroundSyncReceived(RemoteMessage)
• onDeletedMessages()
Daraltılabilirlik Değişken; açıkça ayarlanması gerekir Her iki mesaj türü de daraltılabilir veya daraltılamaz olabilir (varsayılan olarak daraltılamaz).

AndroidConfigV2 gönderme isteklerini yetkilendirme

Google Uygulama Varsayılan Kimlik Bilgileri'ni veya Admin SDK'yı kullanarak Firebase hizmet hesabınızdan türetilen OAuth 2.0 erişim jetonlarını kullanmaya devam edebilir ve HTTP v1 messages:send uç noktasına POST istekleri gönderebilirsiniz.

Firebase hizmet hesabınızı kullanmıyorsanız özel hesabınızı Firebase Cloud Messaging API Yöneticisi rolüne (roles/firebase.messagingAdmin) atadığınızdan ve erişim jetonları oluştururken https://www.googleapis.com/auth/firebase.messaging OAuth 2.0 kapsamını istediğinizden emin olun:

POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send HTTP/1.1
Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN
Content-Type: application/json

Sunucu gönderme isteklerini güncelleme (REST)

REST API'yi kullanarak AndroidConfigV2 isteği göndermek için istek gövdenizdeki android nesnesini android_v2 ile değiştirin. android_v2 içinde ortak parametreleri (ttl, collapse_key, data ve restricted_package_name gibi) belirtin ve şu birleşim alanlarından birini sağlayın: remote_notification veya background_sync.

RemoteNotification mesajı gönderme

Kullanıcılara yönelik acil bir bildirim göndermek için remote_notification nesnesini ve önerilen notification yükünü ekleyin. Varsayılan olarak mutable_content "false" değerine ayarlıdır. GMS Core, arka plan uygulama kodunu çalıştırmadan bildirimi hemen oluşturur ve sistem tepsisinde yayınlar.

Tam HTTP isteği JSON örneği (otomatik olarak oluşturulan bildirim)

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

{
  "message": {
    "token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification": {
      "title": "FCM Message",
      "body": "This is an FCM notification message!"
    },
    "android_v2": {
      "ttl": "3600s",
      "remote_notification": {
        "mutable_content": false,
        "notification": {
          "title": "Order update",
          "body": "Your order has been shipped!",
          "icon": "ic_notification_custom",
          "sound": "default",
          "tag": "alert_tag_1",
          "id": 100
        }
      }
    }
  }
}

Değiştirilebilir içerikli bir RemoteNotification gönderme

Uygulamanızın, cihazdaki bildirimi gösterilmeden önce değiştirmesi gerekiyorsa remote_notification içinde mutable_content: true değerini ayarlayın. Bu, GMS Core'a istemci uygulamanıza bağlanmasını ve onNotificationReceived() yöntemini çağırmasını söyler. Bu, uçtan uca şifrelenmiş bir yükün şifresini çözmek, kullanıcı avatarları eklemek veya dizeleri yerelleştirmek istediğinizde kullanışlıdır.

mutable_content, true olduğunda bile remote_notification içine bir notification nesnesi eklediğinizden emin olun. GMS Core, istemci geri çağırma zaman aşımına uğrarsa veya gizleme sınırlarını aşarsa bu notification nesnesini yedek bildirim olarak kullanır.

Eski v1 veri mesajlarından geçiş yapıyorsanız ve FCM hizmetinin, yükü eski v1 istemci yüklemelerine saf veri mesajı olarak göndermesini istiyorsanız remote_notification içinde use_as_v1_data_message: true değerini ayarlayın.

Tam HTTP isteği JSON örneği

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

{
  "message": {
    "token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data": {
      "encrypted_content": "U2FsdGVkX19vN2m+",
      "sender_id": "user_98124"
    },
    "android_v2": {
      "ttl": "3600s",
      "remote_notification": {
        "mutable_content": true,
        "use_as_v1_data_message": true,
        "notification": {
          "title": "New message",
          "body": "You have a new message",
          "tag": "chat_alert",
          "id": 1001
        }
      }
    }
  }
}

BackgroundSync mesajı gönderme

Arka planda veri senkronizasyonu, sessiz durum güncellemeleri veya uygulama rozeti ya da widget'ı güncellemek için acil olmayan bir mesaj göndermek istiyorsanız background_sync nesnesini kullanın. Bu mesajları, kullanıcı tarafından görülebilen bildirimler yayınlamak için kullanmayın. Bu bildirimler, cihazın pil ömrünü optimize etmek için toplu olarak işlenebilir veya geciktirilebilir.

Tam HTTP isteği JSON örneği

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

{
  "message": {
    "token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data": {
      "score": "FETCH_UPDATES",
      "sync_action": "FETCH_UPDATES"
    },
    "android_v2": {
      "ttl": "86400s",
      "collapse_key": "app_state_sync",
      "background_sync": {}
    }
  }
}

Android istemci geri çağırmalarını güncelleme

Android'de AndroidConfigV2 mesajları almak için uygulamanızı en yeni firebase-messaging SDK'yı kullanacak şekilde yükseltin. onNotificationReceived() ve onBackgroundSyncReceived() uygulayarak FirebaseMessagingService sınıfını genişleten hizmetinizi güncelleyin.

EAP SDK'yı yükleme

EAP sırasında firebase-messaging v2 SDK, Google'ın herkese açık Maven deposu yerine yerel bir Maven deposu arşivi olarak dağıtılır.

  1. firebase-messaging:26.1.0-eap01 dosyasını içeren m2repository dizinini, aşağıdaki seçeneklerden birini kullanarak Android projenizin kök dizinine (<project-root>/m2repository) ekleyin:

    1. A seçeneği: Önceden oluşturulmuş arşivi indirin: FirebaseMessaging_26.1.0-eap01.zip dosyasını indirin ve m2repository dizinini Android projenizin kök dizinine (<project-root>/m2repository) çıkarın.
    2. B seçeneği: Gradle ile GitHub'dan derleme: firebase/firebase-android-sdk'in feature/fcm-android-config-v2-eap dalını kopyalayın, yerel Maven deposunu derleyin ve oluşturulan build/m2repository dizinini Android projenizin kök dizinine kopyalayın:

      git clone --branch feature/fcm-android-config-v2-eap --single-branch \
        https://github.com/firebase/firebase-android-sdk.git
      cd firebase-android-sdk
      ./gradlew -PprojectsToPublish="firebase-messaging" firebasePublish
      cp -R build/m2repository /path/to/your/android-project/m2repository
      
  2. Proje düzeyindeki settings.gradle.kts (veya settings.gradle) dosyanızda, yerel m2repository dizinini repositories bloğunuzun en üstüne, google() öğesinin üstüne ekleyin:

    Kotlin

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            maven { url = uri("${rootDir}/m2repository") }
            google()
            mavenCentral()
        }
    }
    

    Groovy

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            maven { url "${rootDir}/m2repository" }
            google()
            mavenCentral()
        }
    }
    
  3. Modül düzeyindeki app/build.gradle.kts (veya app/build.gradle) dosyanızda firebase-messaging bağımlılığınızı 26.1.0-eap01 sürümüne güncelleyin:

    Kotlin

    dependencies {
        implementation("com.google.firebase:firebase-messaging:26.1.0-eap01")
    }
    

    Groovy

    dependencies {
        implementation 'com.google.firebase:firebase-messaging:26.1.0-eap01'
    }
    
  4. Projenizi Gradle dosyalarıyla senkronize edin.

RemoteNotifications'ı onNotificationReceived ile işleme

AndroidConfigV2 ile RemoteNotification mesajları, mutable_content doğru olarak ayarlanmadığı veya onNotificationReceived() içinde açıkça susturulmadığı sürece gösterilir.

mutable_content: true ile bir RemoteNotification geldiğinde GMS Core, uygulamanıza bağlanır ve onNotificationReceived() yöntemini çağırır. Yönteminiz 20 saniye içinde NotificationResponse döndürmelidir.

Değiştirilmiş bir bildirim döndürme

NotificationResponse.create öğesine ilettiğiniz Notification nesnesi, sunucunun gönderme isteğinde tanımlanan remote_notification.notification yedek yük özelliklerinin yerini alır. Gönderme isteğindeki değerleri korumak için cihaz üzerinde değişiklikler uygularken bu değerleri message.notification (Java'da message.getNotification()) üzerinden okuyun:

Kotlin

import androidx.core.app.NotificationCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.NotificationResponse
import com.google.firebase.messaging.RemoteMessage

class MyFirebaseMessagingService : FirebaseMessagingService() {

    override fun onNotificationReceived(message: RemoteMessage): NotificationResponse {
        val serverNotif = message.notification
        val channelId = serverNotif?.channelId ?: "default_channel"
        // Keep the server-defined title unchanged, or fall back to default
        val title = serverNotif?.title ?: "New message"
        // Modify the notification body on-device (for example, decrypting data)
        val decryptedBody = decryptPayload(message.data["encrypted_content"])

        val builder = NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.drawable.ic_stat_notification)
            .setContentTitle(title)
            .setContentText(decryptedBody)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setAutoCancel(true)

        // Return the response for the open-source FCM SDK to post to the Android platform
        return NotificationResponse.create("optional_tag", 100, builder.build())
    }
}

Java

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import com.google.firebase.messaging.NotificationResponse;
import androidx.core.app.NotificationCompat;

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public NotificationResponse onNotificationReceived(RemoteMessage message) {
        RemoteMessage.Notification serverNotif = message.getNotification();
        String channelId = (serverNotif != null && serverNotif.getChannelId() != null)
                ? serverNotif.getChannelId()
                : "default_channel";
        // Keep the server-defined title unchanged, or fall back to default
        String title = (serverNotif != null && serverNotif.getTitle() != null)
                ? serverNotif.getTitle()
                : "New message";
        // Modify the notification body on-device (for example, decrypting data)
        String decryptedBody = decryptPayload(message.getData().get("encrypted_content"));

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.drawable.ic_stat_notification)
                .setContentTitle(title)
                .setContentText(decryptedBody)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setAutoCancel(true);

        // Return the response for the open-source FCM SDK to post to the Android platform
        return NotificationResponse.create("optional_tag", 100, builder.build());
    }
}

Bildirimleri gizleme

Kullanıcı şu anda ilgili ekranı veya sohbeti etkin olarak kullanıyorsa NotificationResponse.suppress() döndürerek bildirimi gizleyebilirsiniz:

Kotlin

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner

override fun onNotificationReceived(message: RemoteMessage): NotificationResponse {
    val chatId = message.data["chat_id"]
    val isAppForeground = ProcessLifecycleOwner.get()
        .lifecycle
        .currentState
        .isAtLeast(Lifecycle.State.STARTED)

    if (isAppForeground && chatRepository.isConversationActive(chatId)) {
        // Suppress notification display because the user is actively viewing this chat
        return NotificationResponse.suppress()
    }

    val builder = buildNotificationForChat(message)
    return NotificationResponse.create("chat_tag", 101, builder.build())
}

Java

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ProcessLifecycleOwner;

@Override
public NotificationResponse onNotificationReceived(RemoteMessage message) {
    String chatId = message.getData().get("chat_id");
    boolean isAppForeground = ProcessLifecycleOwner.get()
            .getLifecycle()
            .getCurrentState()
            .isAtLeast(Lifecycle.State.STARTED);

    if (isAppForeground && chatRepository.isConversationActive(chatId)) {
        // Suppress notification display because the user is actively viewing this chat
        return NotificationResponse.suppress();
    }

    NotificationCompat.Builder builder = buildNotificationForChat(message);
    return NotificationResponse.create("chat_tag", 101, builder.build());
}

Bildirimleri yayınlama veya eski uyarıları iptal etme (FcmNotificationManager)

Tek bir gelen push için birden fazla bildirim yayınlamanız veya yeni bir bildirim göstermeden önce eski bir bildirimi iptal etmeniz gerekiyorsa FcmNotificationManager kullanın:

Kotlin

override fun onNotificationReceived(message: RemoteMessage): NotificationResponse {
    // Retrieve the scoped manager for this message execution
    val manager = getFcmNotificationManager(message)

    // 1. Cancel an outdated notification right away
    manager.cancelNow("message_tag", 50)

    // 2. Post the item notification immediately
    val itemNotif = NotificationCompat.Builder(this, "chat_channel")
        .setSmallIcon(R.drawable.ic_message)
        .setContentTitle("Alex")
        .setContentText(message.data["text"])
    manager.postNow("item_tag", 51, itemNotif.build())

    // 3. Post a group summary notification
    val summaryNotif = NotificationCompat.Builder(this, "chat_channel")
        .setSmallIcon(R.drawable.ic_message)
        .setContentTitle("New Conversations")
        .setGroupSummary(true)
    manager.postNow("summary_tag", 52, summaryNotif.build())

    // 4. Return finished() to complete the streaming workflow
    return manager.finished()
}

Java

@Override
public NotificationResponse onNotificationReceived(RemoteMessage message) {
    // Retrieve the scoped manager for this message execution
    FcmNotificationManager manager = getFcmNotificationManager(message);

    // 1. Cancel an outdated notification right away
    manager.cancelNow("message_tag", 50);

    // 2. Post the item notification immediately
    NotificationCompat.Builder itemNotif = new NotificationCompat.Builder(this, "chat_channel")
            .setSmallIcon(R.drawable.ic_message)
            .setContentTitle("Alex")
            .setContentText(message.getData().get("text"));
    manager.postNow("item_tag", 51, itemNotif.build());

    // 3. Post a group summary notification
    NotificationCompat.Builder summaryNotif = new NotificationCompat.Builder(this, "chat_channel")
            .setSmallIcon(R.drawable.ic_message)
            .setContentTitle("New Conversations")
            .setGroupSummary(true);
    manager.postNow("summary_tag", 52, summaryNotif.build());

    // 4. Return finished() to complete the streaming workflow
    return manager.finished();
}

onBackgroundSyncReceived kullanarak BackgroundSync mesajlarını işleme

Android'de BackgroundSync mesajlarını işlemek için onBackgroundSyncReceived() kullanın:

Kotlin

override fun onBackgroundSyncReceived(message: RemoteMessage) {
    val syncCommand = message.data["sync_action"]

    try {
        // Perform local database synchronization or cache refresh
        AppDataRepository.getInstance(applicationContext).syncWithServer(syncCommand)
    } catch (e: Exception) {
        Log.e("FCM", "Background sync operation failed", e)
    }
    // Execution completes -> GMS Core marks the message as handled and unbinds.
}

Java

@Override
public void onBackgroundSyncReceived(RemoteMessage message) {
    String syncCommand = message.getData().get("sync_action");

    try {
        // Perform local database synchronization or cache refresh
        AppDataRepository.getInstance(getApplicationContext()).syncWithServer(syncCommand);
    } catch (Exception e) {
        Log.e("FCM", "Background sync operation failed", e);
    }
    // Execution completes -> GMS Core marks the message as handled and unbinds.
}

onDeletedMessages kullanarak bekleyen mesaj silme işlemlerini yönetme

Cihazın uzun süre FCM hizmetine bağlanmadığı veya sunucu sırasının dolu olduğu bazı durumlarda FCM, bekleyen mesajları teslim edilmeden önce silebilir. Bu durumlarda onDeletedMessages() değerini geçersiz kılın:

Kotlin

override fun onDeletedMessages() {
    // Perform a full state synchronization with your app server
    AppDataRepository.getInstance(applicationContext).scheduleFullSync()
}

Java

@Override
public void onDeletedMessages() {
    // Perform a full state synchronization with your app server
    AppDataRepository.getInstance(getApplicationContext()).scheduleFullSync();
}

Belirli uygulamaları taşıma

Uçtan uca şifrelenmiş (E2EE) bildirimler gönderme

RemoteNotification kullanarak uçtan uca şifrelenmiş bir bildirim gönderirken şifresi çözülmüş bildirim içeriği uygulamanızda ve Android platformunda kalır:

  1. Değişken bildirim gönderme: Sunucunuz, mutable_content: true ile RemoteNotification, data içinde şifrelenmiş yük ve genel şifrelenmemiş yedek notification gönderir. GMS Core, şifrelenmiş mesajı uygulamanızın içindeki açık kaynak FCM SDK'ya iletir.
  2. Şifre çözme ve bildirim döndürme: FCM SDK'sı onNotificationReceived() yöntemini çağırır. Uygulamanız, yükün şifresini yerel olarak çözer, şifresi çözülmüş nihai Android Notification öğesini oluşturur ve NotificationResponse veya FcmNotificationManager kullanarak açık kaynak FCM SDK'sına geri iletir.
  3. Platformda yayınlama ve meta verileri raporlama: Açık kaynak FCM SDK'sı, şifresi çözülmüş bildirimi doğrudan Android platformu NotificationManager API'sinde yayınlar ve teslimatın gözlemlenebilmesi için yalnızca bildirim kimlikleri ve zaman damgaları gibi bildirim meta verilerini GMS Core'a geri gönderir. Şifresi çözülmüş içerik hiçbir zaman GMS Core'a gönderilmez.
  4. Gerekirse yedek bildirim yayınlama: GMS Core, yalnızca uygulamanız 20 saniyelik zaman aşımı süresi içinde yanıt vermezse veya arka planda gizleme sınırlarını aşarsa genel yedek bildirimi notification doğrudan Android platformunda yayınlar.

GMS Core, açık kaynak FCM SDK'sı, uygulamanız ve Android platformu NotificationManager API'si arasındaki 4 adımlı uçtan uca şifrelenmiş bildirim yayınlama akışını gösteren mimari şeması.

Bildirimleri gizleme ve zaman aşımlarını anlama

GMS Core, Android ekosisteminde güvenilir teslimat sağlamak için RemoteNotification mesajlarını işlerken işleme zaman aşımları ve bildirim engelleme sınırları uygular:

İşlem zaman aşımı

mutable_content, true olarak ayarlandığında onNotificationReceived() yönteminiz 20 saniye içinde NotificationResponse döndürmelidir. Yürütme bu eşiği aşarsa geri çağırma iptal edilir ve GMS Core, remote_notification.notification yükünden oluşturulan bir yedek bildirimi otomatik olarak yayınlar.

Bildirim engelleme oranı

RemoteNotification mesajları, kullanıcıları hemen uyarmak için Doze kısıtlamalarını atladığından ve gecikme olmadan teslim edildiğinden, uygulamaların alınan RemoteNotification mesajları için bildirim göstermesi beklenir.

Her uygulamanın, arka planda çalışırken RemoteNotification trafiğinin% 25'ine kadarını engellemesine izin verilir. Bir uygulamanın engelleme oranı %25'i aşarsa GMS Core, remote_notification.notification yükünden oluşturulan bir yedek bildirimi otomatik olarak oluşturur ve yayınlar.

Uygulama ön planda etkinken gerçekleştirilen engellemeler bu eşiğe dahil edilmez. Kısıtlanmamış arka plan kullanım izinleri verilen uygulamalar, arka plan engelleme sınırlarından da muaftır.