| Platform seçin: | iOS+ Android Web Flutter Unity C++ |
Gelen mesajlar, cihazın durumuna göre farklı şekilde işlenir. Bu senaryoları ve FCM'yi kendi uygulamanıza nasıl entegre edeceğinizi anlamak için öncelikle bir cihazın bulunabileceği çeşitli durumları belirlemek önemlidir:
| Eyalet | Açıklama |
|---|---|
| Ön plan | Uygulama açık, görünür ve kullanımdayken |
| Arka plan | Uygulama açık ancak arka planda (küçültülmüş) olduğunda. Bu durum genellikle kullanıcı cihazdaki "ana sayfa" düğmesine bastığında, uygulama değiştirme aracını kullanarak başka bir uygulamaya geçtiğinde veya uygulamayı farklı bir sekmede (web) açtığında ortaya çıkar. |
| Sonlandırıldı | Cihaz kilitliyken veya uygulama çalışmıyorken |
Uygulamanın FCM kullanarak mesaj yüklerini alabilmesi için karşılanması gereken birkaç ön koşul vardır:
- Uygulamanın en az bir kez açılmış olması gerekir (FCM'ye kaydolabilmek için).
- iOS'te, kullanıcı uygulamayı uygulama değiştirme aracından kaydırarak kapatırsa arka plan mesajlarının tekrar çalışmaya başlaması için uygulamanın manuel olarak yeniden açılması gerekir.
- Android'de, kullanıcı uygulamayı cihaz ayarlarından kapanmaya zorlarsa mesajların çalışmaya başlaması için uygulamanın manuel olarak yeniden açılması gerekir.
- Web'de, web push sertifikanızla birlikte bir jeton (
getToken()kullanarak) istemiş olmanız gerekir.
Mesaj alma izni isteme
iOS, macOS, web ve Android 13 (veya daha yeni sürümler) cihazlarda FCM yüklerinin alınabilmesi için önce kullanıcıdan izin istemeniz gerekir.
firebase_messaging paketi, requestPermission yöntemiyle izin istemek için bir API sağlar. Bu API, istemek istediğiniz izin türünü tanımlayan birkaç adlandırılmış bağımsız değişkeni kabul eder. Örneğin, bildirim yükleri içeren mesajların bir sesi tetikleyip tetikleyemeyeceği veya Siri'yi kullanarak mesajları okuyup okuyamayacağı gibi. Varsayılan olarak, yöntem makul varsayılan izinler ister. Referans API'si, her iznin ne için kullanıldığıyla ilgili eksiksiz dokümanlar sağlar.
Başlamak için uygulamanızdan yöntemi çağırın (iOS'te yerleşik bir kalıcı pencere gösterilir, web'de tarayıcının API akışı tetiklenir):
FirebaseMessaging messaging = FirebaseMessaging.instance;
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
print('User granted permission: ${settings.authorizationStatus}');
İstekten döndürülen NotificationSettings nesnesinin authorizationStatus özelliği, kullanıcının genel kararını belirlemek için kullanılabilir:
authorized: Kullanıcı izin verdi.denied: Kullanıcı izni reddetti.notDetermined: Kullanıcı henüz izin verip vermeyeceğini seçmemiştir.provisional: Kullanıcı geçici izin verdi
NotificationSettings üzerindeki diğer özellikler, belirli bir iznin etkinleştirilip etkinleştirilmediğini, devre dışı bırakılıp bırakılmadığını veya mevcut cihazda desteklenip desteklenmediğini döndürür.
İzin verildikten ve farklı cihaz durumu türleri anlaşıldıktan sonra uygulamanız artık gelen FCM yüklerini işlemeye başlayabilir.
İleti işleme
Uygulamanızın mevcut durumuna bağlı olarak, farklı mesaj türlerinin gelen yüklerini işlemek için farklı uygulamalar gerekir:
Ön plan mesajları
Uygulamanız ön plandayken mesajları işlemek için onMessage akışını dinleyin.
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
print('Message data: ${message.data}');
if (message.notification != null) {
print('Message also contained a notification: ${message.notification}');
}
});
Akışta, yükle ilgili çeşitli bilgileri (ör. nereden geldiği, benzersiz kimliği, gönderilme zamanı, bildirim içerip içermediği) ayrıntılı olarak açıklayan bir RemoteMessage bulunur. Mesaj, uygulamanız ön plandayken alındığından Flutter uygulamanızın durumuna ve bağlamına doğrudan erişebilirsiniz.
Ön plan ve bildirim mesajları
Uygulama ön plandayken gelen bildirim mesajları, hem Android hem de iOS'te varsayılan olarak görünür bir bildirim göstermez. Ancak bu davranışı geçersiz kılmak mümkündür:
- Android'de "Yüksek Öncelikli" bir bildirim kanalı oluşturmanız gerekir.
- iOS'te, uygulamanın sunu seçeneklerini güncelleyebilirsiniz.
Arka plan mesajları
Arka plan mesajlarını işleme süreci Android, Apple ve web tabanlı platformlarda farklıdır.
Apple platformları ve Android
onBackgroundMessage işleyici kaydederek arka plan mesajlarını işleme Mesajlar alındığında, uygulamanız çalışmıyorken bile mesajları işlemenize olanak tanıyan bir yalıtılmış alan oluşturulur (yalnızca Android'de geçerlidir, iOS/macOS'te ayrı bir yalıtılmış alan gerekmez).
Arka plan mesaj işleyicinizle ilgili olarak unutmamanız gereken birkaç nokta vardır:
- İsimsiz bir işlev olmamalıdır.
- Üst düzey bir işlev olmalıdır (ör. başlatma gerektiren bir sınıf yöntemi olmamalıdır).
- Flutter 3.3.0 veya sonraki sürümler kullanılırken ileti işleyici, işlev bildiriminin hemen üzerinde
@pragma('vm:entry-point')ile açıklama eklenmiş olmalıdır (aksi takdirde, yayın modu için ağaç temizleme sırasında kaldırılabilir).
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
print("Handling a background message: ${message.messageId}");
}
void main() {
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyApp());
}
İşleyici, uygulama bağlamınızın dışında kendi izolatında çalıştığından uygulama durumunu güncellemek veya kullanıcı arayüzünü etkileyen herhangi bir mantığı yürütmek mümkün değildir. Ancak HTTP istekleri gibi mantık işlemleri gerçekleştirebilir, G/Ç işlemleri (ör. yerel depolamayı güncelleme) yapabilir, diğer eklentilerle iletişim kurabilirsiniz.
Mantığınızı en kısa sürede tamamlamanız da önerilir. Uzun ve yoğun görevler çalıştırmak cihaz performansını etkiler ve işletim sisteminin işlemi sonlandırmasına neden olabilir. Görevler 30 saniyeden uzun sürerse cihaz, işlemi otomatik olarak sonlandırabilir.
Web
Web'de, arka planda çalışan bir JavaScript Service Worker yazın. Arka plan mesajlarını işlemek için hizmet çalışanını kullanın.
Başlamak için web dizininizde yeni bir dosya oluşturun ve dosyayı firebase-messaging-sw.js olarak adlandırın:
// See this file for the latest firebase-js-sdk version:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart
importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js");
importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js");
firebase.initializeApp({
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
});
const messaging = firebase.messaging();
// Optional:
messaging.onBackgroundMessage((message) => {
console.log("onBackgroundMessage", message);
});
Dosya hem uygulama hem de mesajlaşma SDK'larını içe aktarmalı, Firebase'i başlatmalı ve messaging değişkenini göstermelidir.
Ardından, çalışanın kaydolması gerekir. index.html dosyasında, Flutter'ı başlatan <script> etiketini değiştirerek çalışanı kaydedin:
<script src="flutter_bootstrap.js" async>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('firebase-messaging-sw.js', {
scope: '/firebase-cloud-messaging-push-scope',
});
});
}
</script>
Hâlâ eski şablon sistemini kullanıyorsanız Flutter'ı başlatmak için kullanılan <script> etiketini aşağıdaki gibi değiştirerek çalışanı kaydedebilirsiniz:
<html>
<body>
<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
if ('serviceWorker' in navigator) {
// Service workers are supported. Use them.
window.addEventListener('load', function () {
// Register Firebase Messaging service worker.
navigator.serviceWorker.register('firebase-messaging-sw.js', {
scope: '/firebase-cloud-messaging-push-scope',
});
// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl =
'flutter_service_worker.js?v=' + serviceWorkerVersion;
navigator.serviceWorker.register(serviceWorkerUrl).then((reg) => {
function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state == 'activated') {
console.log('Installed new service worker.');
loadMainDartJs();
}
});
}
if (!reg.active && (reg.installing || reg.waiting)) {
// No active web worker and we have installed or are installing
// one for the first time. Simply wait for it to activate.
waitForActivation(reg.installing ?? reg.waiting);
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update.
console.log('New service worker available.');
reg.update();
waitForActivation(reg.installing);
} else {
// Existing service worker is still good.
console.log('Loading app from service worker.');
loadMainDartJs();
}
});
// If service worker doesn't succeed in a reasonable amount of time,
// fallback to plaint <script> tag.
setTimeout(() => {
if (!scriptLoaded) {
console.warn(
'Failed to load app from service worker. Falling back to plain <script> tag.'
);
loadMainDartJs();
}
}, 4000);
});
} else {
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs();
}
</script>
</body>
Ardından Flutter uygulamanızı yeniden başlatın. Çalışan kaydedilir ve arka plandaki tüm mesajlar bu dosya kullanılarak işlenir.
Etkileşimleri Yönetme
Bildirimler görünür bir işaret olduğundan kullanıcıların bunlarla etkileşim kurması (basarak) yaygındır. Hem Android hem de iOS'te varsayılan davranış, uygulamayı açmaktır. Uygulama sonlandırıldıysa başlatılır, arka plandaysa ön plana getirilir.
Bildirimin içeriğine bağlı olarak, uygulama açıldığında kullanıcının etkileşimini yönetmek isteyebilirsiniz. Örneğin, bildirim kullanılarak yeni bir sohbet mesajı gönderilirse ve kullanıcı bu bildirime basarsa uygulama açıldığında ilgili görüşmeyi açmak isteyebilirsiniz.
firebase-messaging paketi, bu etkileşimi ele almanın iki yolunu sunar:
getInitialMessage(): Uygulama sonlandırılmış bir durumdan açılırsaRemoteMessageiçeren birFuturedöndürülür. Kullanıldıktan sonraRemoteMessagekaldırılır.onMessageOpenedApp: Uygulama arka plan durumundan açıldığındaRemoteMessageyayınlayan birStream.
Kullanıcılarınıza sorunsuz bir kullanıcı deneyimi sunmak için her iki senaryonun da ele alınması önerilir. Aşağıdaki kod örneğinde bunun nasıl yapılabileceği gösterilmektedir:
class Application extends StatefulWidget {
@override
State<StatefulWidget> createState() => _Application();
}
class _Application extends State<Application> {
// It is assumed that all messages contain a data field with the key 'type'
Future<void> setupInteractedMessage() async {
// Get any messages which caused the application to open from
// a terminated state.
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
// If the message also contains a data property with a "type" of "chat",
// navigate to a chat screen
if (initialMessage != null) {
_handleMessage(initialMessage);
}
// Also handle any interaction when the app is in the background using a
// Stream listener
FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
}
void _handleMessage(RemoteMessage message) {
if (message.data['type'] == 'chat') {
Navigator.pushNamed(context, '/chat',
arguments: ChatArguments(message),
);
}
}
@override
void initState() {
super.initState();
// Run code required to handle interacted messages in an async function
// as initState() must not be async
setupInteractedMessage();
}
@override
Widget build(BuildContext context) {
return Text("...");
}
}
Etkileşimi nasıl ele alacağınız, uygulama kurulumunuza bağlıdır. Önceki örnekte, StatefulWidget kullanan basit bir örnek gösterilmektedir.
Mesajları yerelleştirme
Yerelleştirilmiş dizeleri iki farklı şekilde gönderebilirsiniz:
- Kullanıcılarınızın tercih ettiği dilleri sunucunuzda saklayın ve her dil için özelleştirilmiş bildirimler gönderin.
- Yerelleştirilmiş dizeleri uygulamanıza yerleştirin ve işletim sisteminin yerleşik yerel ayarlarından yararlanın.
İkinci yöntemi şu şekilde kullanabilirsiniz:
Android
Varsayılan dilinizdeki mesajları
resources/values/strings.xmliçinde belirtin:<string name="notification_title">Hello world</string> <string name="notification_message">This is a message</string>Çevrilen mesajları
values-languagedizininde belirtin. Örneğin,resources/values-fr/strings.xmldilinde Fransızca mesajlar belirtin:<string name="notification_title">Bonjour le monde</string> <string name="notification_message">C'est un message</string>Sunucu yükünde
title,messagevebodyanahtarlarını kullanmak yerine yerelleştirilmiş mesajınız içintitle_loc_keyvebody_loc_keyanahtarlarını kullanın ve bunları, görüntülemek istediğiniz mesajınnameözelliğine ayarlayın.Mesaj yükü şu şekilde görünür:
{ "android": { "notification": { "title_loc_key": "notification_title", "body_loc_key": "notification_message" } } }
iOS
Base.lproj/Localizable.stringsdilindeki varsayılan dil mesajlarınızı belirtin:"NOTIFICATION_TITLE" = "Hello World"; "NOTIFICATION_MESSAGE" = "This is a message";language.lprojdizininde çevrilen mesajları belirtin. Örneğin,fr.lproj/Localizable.stringsdilinde Fransızca mesajlar belirtin:"NOTIFICATION_TITLE" = "Bonjour le monde"; "NOTIFICATION_MESSAGE" = "C'est un message";İleti yükü şöyle görünür:
{ "apns": { "payload": { "alert": { "title-loc-key": "NOTIFICATION_TITLE", "loc-key": "NOTIFICATION_MESSAGE" } } } }
İleti teslimi verilerini dışa aktarmayı etkinleştirme
Daha ayrıntılı analiz için mesaj verilerinizi BigQuery'ye aktarabilirsiniz. BigQuery, BigQuery SQL'i kullanarak verileri analiz etmenize, başka bir bulut sağlayıcıya aktarmanıza veya özel ML modelleriniz için kullanmanıza olanak tanır. BigQuery'ye yapılan dışa aktarma işlemlerinde, mesaj türü veya mesajın API ya da Bildirimler oluşturucu kullanılarak gönderilip gönderilmediğine bakılmaksızın mesajlarla ilgili tüm veriler yer alır.
Dışa aktarma işlemini etkinleştirmek için önce BigQuery veri dışa aktarma belgesindeki adımları uygulayın. Bu özelliği uygulama örneği düzeyinde programatik olarak etkinleştirmek, son kullanıcılardan mesaj teslim verilerini analiz etmek için izin istemenize olanak tanır (önerilir). Dışa aktarmayı programatik olarak etkinleştirmek için aşağıdaki talimatları uygulayın:
Android
Aşağıdaki kodu kullanabilirsiniz:
await FirebaseMessaging.instance.setDeliveryMetricsExportToBigQuery(true);
iOS
iOS için AppDelegate.m dosyasını aşağıdaki içerikle değiştirmeniz gerekir.
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
#import <Firebase/Firebase.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[FIRMessaging extensionHelper] exportDeliveryMetricsToBigQueryWithMessageInfo:userInfo];
}
@end
Web
Web için SDK'nın v9 sürümünü kullanmak üzere hizmet çalışanınızı değiştirmeniz gerekir. v9 sürümünün paketlenmesi gerektiğinden, hizmet çalışanının çalışması için esbuild gibi bir paketleyici kullanmanız gerekir. Bunu nasıl yapacağınızı öğrenmek için örnek uygulamaya göz atın.
v9 SDK'ya geçiş yaptıktan sonra aşağıdaki kodu kullanabilirsiniz:
import {
experimentalSetDeliveryMetricsExportedToBigQueryEnabled,
getMessaging,
} from 'firebase/messaging/sw';
...
const messaging = getMessaging(app);
experimentalSetDeliveryMetricsExportedToBigQueryEnabled(messaging, true);
Hizmet çalışanınızın yeni sürümünü web klasörüne aktarmak için yarn build komutunu çalıştırmayı unutmayın.
iOS'te bildirimlerde resim gösterme
Apple cihazlarda, gelen FCM bildirimlerinin FCM yükündeki resimleri görüntülemesi için ek bir bildirim hizmeti uzantısı eklemeniz ve uygulamanızı bu uzantıyı kullanacak şekilde yapılandırmanız gerekir.
Firebase telefon kimlik doğrulaması kullanıyorsanız Firebase Auth pod'unu Podfile'ınıza eklemeniz gerekir.
1. adım: Bildirim hizmeti uzantısı ekleyin
- Xcode'da File > New > Target... (Dosya > Yeni > Hedef...) seçeneğini tıklayın.
- Olası hedeflerin listesini içeren bir modal gösterilir. Notification Service Extension'ı seçmek için ekranı kaydırın veya filtreyi kullanın. Next'i (Sonraki) tıklayın.
- Ürün adı ekleyin (bu eğitimle birlikte ilerlemek için "ImageNotification"ı kullanın),
SwiftveyaObjective-C'ı seçin ve Bitir'i tıklayın. - Etkinleştir'i tıklayarak şemayı etkinleştirin.
2. adım: Hedefi Podfile'a ekleyin
Swift
Yeni uzantınızın FirebaseMessaging Swift paketine erişebilmesi için paketi Runner hedefinize ekleyin:
Gezgin'den Firebase Apple platformları SDK'sını ekleyin: File > Add Package Dependencies... (Dosya > Paket Bağımlılıkları Ekle...)
Paket URL'sini arayın veya girin:
none https://github.com/firebase/firebase-ios-sdkRunnerprojesine ekleme: Paket EkleFirebaseMessaging'i seçin ve ImageNotification hedefine ekleyin: Add Package (Paket Ekle)
Objective-C
Podfile'a ekleyerek yeni uzantınızın Firebase/Messaging pod'una erişebildiğinden emin olun:
Navigator'dan Podfile'ı açın: Pods > Podfile
Dosyanın en altına gidip şunları ekleyin:
target 'ImageNotification' do use_frameworks! pod 'Firebase/Auth' # Add this line if you are using FirebaseAuth phone authentication pod 'Firebase/Messaging' endiosveyamacosdizinindenpod installkullanarak pod'larınızı yükleyin veya güncelleyin.
3. adım: Uzantı yardımcısını kullanma
Bu noktada her şey normal şekilde çalışmaya devam etmelidir. Son adım, uzantı yardımcısını çağırmaktır.
Swift
Gezginden ImageNotification uzantınızı seçin.
NotificationService.swiftdosyasını açın.NotificationService.swiftdosyasının içeriğini şununla değiştirin:import UserNotifications import FirebaseMessaging class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) Messaging.serviceExtension().populateNotificationContent(bestAttemptContent!, withContentHandler: contentHandler) } override func serviceExtensionTimeWillExpire() { if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } }
Objective-C
Gezginden ImageNotification uzantınızı seçin.
NotificationService.mdosyasını açın.Dosyanın üst kısmında,
NotificationService.höğesinin hemen ardındanFirebaseMessaging.höğesini içe aktarın.NotificationService.mdosyasının içeriğini şununla değiştirin:#import "NotificationService.h" #import "FirebaseMessaging.h" #import <FirebaseAuth/FirebaseAuth-Swift.h> // Add this line if you are using FirebaseAuth phone authentication #import <UIKit/UIKit.h> // Add this line if you are using FirebaseAuth phone authentication @interface NotificationService () <NSURLSessionDelegate> @property(nonatomic) void (^contentHandler)(UNNotificationContent *contentToDeliver); @property(nonatomic) UNMutableNotificationContent *bestAttemptContent; @end @implementation NotificationService /* Uncomment this if you are using Firebase Auth - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options { if ([[FIRAuth auth] canHandleURL:url]) { return YES; } return NO; } - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts { for (UIOpenURLContext *urlContext in URLContexts) { [FIRAuth.auth canHandleURL:urlContext.URL]; } } */ - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; // Modify the notification content here... [[FIRMessaging extensionHelper] populateNotificationContent:self.bestAttemptContent withContentHandler:contentHandler]; } - (void)serviceExtensionTimeWillExpire { // Called just before the extension will be terminated by the system. // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. self.contentHandler(self.bestAttemptContent); } @end
4. adım: Resmi, yük verilerine ekleyin
Artık bildirim yükünüze resim ekleyebilirsiniz. Daha fazla bilgi için gönderme isteği oluşturma başlıklı makaleyi inceleyin.