Notification Events
Learn how to listen for push received events, notification responses, and implement background message handling.
The Airship SDK provides event streams to listen for push notifications and user interactions. These callbacks allow you to perform custom processing, navigate to specific content, or update your app’s state.
Listen for Push Received Events
The onPushReceived stream fires when a push notification is received while your app is in the foreground or background:
import 'dart:async';
import 'package:airship_flutter/airship_flutter.dart';
StreamSubscription? _pushSubscription;
@override
void initState() {
super.initState();
// Listen for push notifications
_pushSubscription = Airship.push.onPushReceived.listen((event) {
print('Push received:');
print('Alert: ${event.pushPayload.alert}');
print('Extras: ${event.pushPayload.extras}');
// Handle the push notification
// e.g., show an in-app banner, update UI, etc.
});
}
@override
void dispose() {
_pushSubscription?.cancel();
super.dispose();
}Android: The onPushReceived listener is not called when the app is terminated. For terminated app states on Android, use the background message handler instead.
Listen for Notification Responses
The onNotificationResponse stream fires when a user interacts with a notification (taps it, taps an action button, or dismisses it):
StreamSubscription? _responseSubscription;
@override
void initState() {
super.initState();
// Listen for notification interactions
_responseSubscription = Airship.push.onNotificationResponse.listen((event) {
print('Notification tapped:');
print('Action ID: ${event.actionId}'); // null for default tap
print('Alert: ${event.pushPayload.alert}');
// Navigate to specific content based on the push
if (event.pushPayload.extras['deep_link'] != null) {
String deepLink = event.pushPayload.extras['deep_link'];
_navigateToDeepLink(deepLink);
}
});
}
void _navigateToDeepLink(String deepLink) {
// Navigate to the appropriate screen
Navigator.pushNamed(context, deepLink);
}
@override
void dispose() {
_responseSubscription?.cancel();
super.dispose();
}Listen for Notification Status Changes
Monitor changes to the notification status:
StreamSubscription? _statusSubscription;
@override
void initState() {
super.initState();
_statusSubscription = Airship.push.onNotificationStatusChanged.listen((event) {
print('Notification status changed:');
print('Opted in: ${event.status.isOptedIn}');
print('System allowed: ${event.status.areNotificationsAllowed}');
});
}
@override
void dispose() {
_statusSubscription?.cancel();
super.dispose();
}Complete Example
Here’s a complete example showing how to handle both push received and notification response events:
import 'package:flutter/material.dart';
import 'package:airship_flutter/airship_flutter.dart';
import 'dart:async';
class NotificationHandler extends StatefulWidget {
@override
_NotificationHandlerState createState() => _NotificationHandlerState();
}
class _NotificationHandlerState extends State<NotificationHandler> {
StreamSubscription? _pushSubscription;
StreamSubscription? _responseSubscription;
String _lastNotification = 'No notifications yet';
@override
void initState() {
super.initState();
_setupNotificationListeners();
}
void _setupNotificationListeners() {
// Handle push received (foreground/background)
_pushSubscription = Airship.push.onPushReceived.listen((event) {
setState(() {
_lastNotification = 'Received: ${event.pushPayload.alert ?? "No alert"}';
});
// Show an in-app notification
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(event.pushPayload.alert ?? 'New notification')),
);
});
// Handle notification interaction
_responseSubscription = Airship.push.onNotificationResponse.listen((event) {
setState(() {
_lastNotification = 'Tapped: ${event.pushPayload.alert ?? "No alert"}';
});
// Handle deep links or custom actions
Map<String, dynamic> extras = event.pushPayload.extras;
if (extras.containsKey('screen')) {
Navigator.pushNamed(context, extras['screen']);
} else if (extras.containsKey('url')) {
// Open URL with url_launcher package
// launch(extras['url']);
}
});
}
@override
void dispose() {
_pushSubscription?.cancel();
_responseSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Notifications')),
body: Center(
child: Text(_lastNotification),
),
);
}
}Android Background Message Handler
For Android, you must set up a background message handler to receive push notifications when the app is completely terminated (not running in the foreground or background).
import 'package:flutter/material.dart';
import 'package:airship_flutter/airship_flutter.dart';
// Background message handler (must be a top-level function)
Future<void> backgroundMessageHandler(PushReceivedEvent event) async {
print('Received background push:');
print('Alert: ${event.pushPayload.alert}');
print('Extras: ${event.pushPayload.extras}');
// Perform background work
// Note: Keep this lightweight and fast
// Avoid UI operations or heavy processing
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Register the background message handler (Android only)
Airship.push.android.setBackgroundPushReceivedHandler(backgroundMessageHandler);
// Initialize Airship
var config = AirshipConfig(
defaultEnvironment: ConfigEnvironment(
appKey: "YOUR_APP_KEY",
appSecret: "YOUR_APP_SECRET"
),
site: Site.us,
);
Airship.takeOff(config);
runApp(MyApp());
}Background handler requirements:
- Must be a top-level function (not a class method)
- Should complete quickly (within a few seconds)
- Avoid UI operations or long-running tasks
- Cannot access
BuildContextor app state directly - Only applies to Android (iOS handles background notifications differently)
Working with Push Payloads
The PushPayload object contains all notification data:
Airship.push.onNotificationResponse.listen((event) {
PushPayload payload = event.pushPayload;
// Standard fields
print('Alert: ${payload.alert}');
print('Title: ${payload.title}');
print('Subtitle: ${payload.subtitle}');
print('Notification ID: ${payload.notificationId}');
// Custom data
Map<String, dynamic> extras = payload.extras;
if (extras.containsKey('product_id')) {
String productId = extras['product_id'];
// Navigate to product details
}
});Categories