Beyond FCM: Exploring Reliable Push Notification Alternatives for Flutter (Android Specific)
The Flutter news you actually need
No spam, ever. Unsubscribe in one click.
When FCM Isn’t Enough: Exploring Android Push Notification Alternatives
As Flutter developers, we’ve all been there. You implement Firebase Cloud Messaging (FCM), test your push notifications, and everything works perfectly… until it doesn’t. Particularly on Android, you might notice that notifications sometimes fail to arrive when the app is terminated, or they’re delayed due to battery optimization features. While FCM is Google’s recommended solution and works well for most use cases, there are scenarios where you need more control over delivery reliability.
Why Look Beyond FCM?
FCM operates within Google’s ecosystem, which means it’s subject to Android’s power management policies. When a device enters Doze mode or applies App Standby, FCM messages are batched and delivered during maintenance windows. For many applications, this is perfectly acceptable. But what if you’re building:
- A real-time trading app where notification delays cost users money
- A critical alert system for healthcare or safety applications
- An app targeting regions where Google Play Services might be unreliable
- A solution where you need full control over the notification delivery pipeline
This is where alternative approaches can shine, particularly on Android where the platform allows more flexibility than iOS.
The Pushy.me Alternative
One notable alternative is Pushy.me, which takes a different approach by managing its own persistent background service on Android. This allows it to maintain a direct connection to their servers, bypassing some of the FCM delivery bottlenecks.
Let’s look at how you might implement Pushy.me in a Flutter app:
First, add the dependency to your pubspec.yaml:
dependencies:
pushy_flutter: ^2.0.0
Initialize the SDK in your main Dart file:
import 'package:pushy_flutter/pushy_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Pushy
try {
await Pushy.listen();
// Register for push notifications
String deviceToken = await Pushy.register();
// Send this token to your backend
print('Pushy device token: $deviceToken');
// Listen for incoming notifications
Pushy.setNotificationListener((Map<String, dynamic> data) async {
// Handle foreground notification
print('Received notification: $data');
// Show local notification
// You'll need to implement showLocalNotification or use a package like flutter_local_notifications
// Navigate or update UI as needed
});
// Listen for notification clicks
Pushy.setNotificationClickListener((Map<String, dynamic> data) async {
// Handle notification tap
print('Notification clicked: $data');
// Note: Cannot use Navigator here without BuildContext
// This should be handled in your app's UI layer
});
} catch (e) {
print('Pushy initialization error: $e');
}
runApp(MyApp());
}
For Android-specific configuration, you’ll need to modify your AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<application>
<!-- Pushy service declaration -->
<service
android:name="me.pushy.sdk.services.PushyService"
android:exported="false">
<intent-filter>
<action android:name="me.pushy.sdk.services.PushyService" />
</intent-filter>
</service>
<!-- Pushy job service for newer Android versions -->
<service
android:name="me.pushy.sdk.job.PushyJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" />
<!-- Pushy broadcast receiver -->
<receiver android:name="me.pushy.sdk.broadcast.PushyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
Trade-offs and Considerations
Before jumping to an alternative solution, consider these important factors:
-
Battery Impact: Persistent connections can consume more battery than FCM’s batched approach. Monitor your users’ feedback and battery usage statistics.
-
Foreground Service Requirement: On Android 8.0 (Oreo) and above, you’ll need to manage a foreground service with a persistent notification, which some users might find intrusive.
-
Platform Limitations: Remember that iOS has stricter limitations, so you’ll likely need to maintain both FCM (for iOS) and your Android solution.
-
Implementation Complexity: You’re taking on more responsibility for connection management, reconnection logic, and error handling.
-
Device Compatibility: Test thoroughly across different manufacturers, as some have aggressive battery optimization that might interfere with background services.
Best Practices for Implementation
If you decide to implement an alternative push notification system:
// Implement a robust error handling and retry mechanism
class NotificationManager {
Future<void> initializeNotifications() async {
try {
await _initializePushy();
} catch (e) {
print('Pushy failed, falling back to FCM');
await _initializeFCM();
}
}
Future<void> _initializePushy() async {
// Pushy initialization code
}
Future<void> _initializeFCM() async {
// FCM fallback initialization
}
// Method to show notifications consistently
Future<void> showNotification(Map<String, dynamic> data) async {
// Always show local notification as backup
// Note: This requires the flutter_local_notifications package
// await LocalNotifications.show(
// 0,
// data['title'] ?? 'Notification',
// data['body'] ?? '',
// NotificationDetails(),
// );
// Update app state if in foreground
// if (AppState.isForeground) {
// // Update UI or show in-app banner
// }
}
}
When to Stick with FCM
Despite the alternatives, FCM remains the best choice for:
- Apps targeting both iOS and Android with a single implementation
- Projects with limited development resources
- Applications where slight notification delays are acceptable
- Apps that don’t require real-time, guaranteed delivery
Conclusion
Exploring push notification alternatives for Android can give you more control and potentially improve reliability for terminated apps, but it comes with trade-offs. The right choice depends on your specific requirements, target audience, and development capacity.
For most applications, sticking with FCM and optimizing its implementation is the pragmatic choice. But when you absolutely need more control over notification delivery on Android, solutions like Pushy.me offer a viable alternative worth considering. Always test thoroughly, monitor performance metrics, and be prepared to maintain a more complex notification infrastructure.
This blog is produced with the assistance of AI by a human editor. Learn more
Related Posts
Flutter's Hidden Gem: Building Powerful Linux Desktop Apps with Ease
Flutter is gaining traction as a robust framework for Linux desktop development, offering a smoother experience compared to traditional toolkits like GTK and Qt. This post will explore why Flutter excels for Linux apps, highlight its advantages, and provide practical insights for developers looking to leverage Flutter for their desktop projects.
Simplifying Flutter Desktop Deployment: Signing and Distribution for Windows
Deploying Flutter desktop apps on Windows can be challenging, especially regarding code signing and preventing Windows from blocking installations. This post will guide developers through the process of signing their Flutter desktop applications, exploring alternatives to the Microsoft Store like creating executable installers, and covering the necessary steps to ensure a smooth user experience.
Mastering Flutter Tooling: Streamlining SDK Management and Installation on Windows
Developers frequently voice frustrations about Flutter SDK version management and installation processes, particularly on Windows. This post will explore best practices for managing multiple Flutter versions using tools like FVM, discuss integrating Flutter with package managers like Winget for a smoother Windows setup, and offer strategies to ensure a consistent development environment across projects and teams.