Prerequisites
Make sure you’ve completed the Platform
Setup for iOS and Android before
proceeding.
How to Use
Add one line to your app’s main()
function:
import 'package:pnta_flutter/pnta_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// That's it! Handles permissions and registration automatically
await PntaFlutter.initialize('prj_XXXXXXXXX');
runApp(MyApp());
}
That’s it! Your app now receives push notifications.
Advanced Usage
Configuration Options
You can configure optional parameters for more control:
await PntaFlutter.initialize(
'prj_XXXXXXXXX',
metadata: {
'user_id': '123',
'user_email': 'user@example.com',
},
registerDevice: false, // Optional: delay registration until later
autoHandleLinks: true, // Optional: enable auto-handling of links
showSystemUI: true, // Optional: show system UI when app is in foreground
);
// Get device token after initialization/registration
final deviceToken = PntaFlutter.deviceToken;
if (deviceToken != null) {
print('Device registered: $deviceToken');
}
Delayed Registration
If you need to register the device later (e.g., after user login), use delayed registration:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize with metadata but don't register yet
await PntaFlutter.initialize(
'prj_XXXXXXXXX',
metadata: {
'user_id': '123',
'user_email': 'user@example.com',
},
registerDevice: false, // Don't register immediately
);
runApp(MyApp());
}
void _registerAfterLogin() async {
// Register device (uses metadata from initialize)
await PntaFlutter.registerDevice();
}
Best Practice: Consider delayed registration for better opt-in rates.
Prompt users for notifications during onboarding or after signup when they
understand the value.
Custom Notification Handling
Foreground Notifications
When your app is open and active, notifications arrive silently by default (no system banner). Use this to show custom UI like snackbars or dialogs:
PntaFlutter.foregroundNotifications.listen((payload) {
print('Received foreground notification: ${payload['title']}');
// Show custom UI (snackbar, dialog, etc.)
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('${payload['title']}: ${payload['body']}')),
);
// Manually handle links if needed
final link = payload['link_to'] as String?;
if (link != null && link.isNotEmpty) {
PntaFlutter.handleLink(link);
}
});
iOS: Set showSystemUI: true
to display the standard notification
banner when your app is in the foreground.
Android: Set showSystemUI: true
to make notifications appear in the
notification panel. By default, Android foreground notifications are silent
and don’t appear in the panel. You’ll need to handle in-app UI using the
listener above.
Background/Terminated Notifications
When users tap notifications while your app is in background or closed:
PntaFlutter.onNotificationTap.listen((payload) {
print('User tapped notification: $payload');
// Access link_to field (available on both platforms)
final linkTo = payload['link_to'] as String?;
// Track analytics, show specific screen, etc.
// Links are auto-handled if autoHandleLinks is set to true
});
Set autoHandleLinks: true
to automatically handle notification links.
External URLs open in the browser, internal routes navigate within your app
(requires navigator key setup).
Deep Linking Setup
For notifications that navigate to specific pages in your app:
MaterialApp(
navigatorKey: PntaFlutter.navigatorKey, // Required for internal route navigation
// ... rest of your app
)
Only needed if your notifications contain internal routes like /profile
.
External URLs with schemes (https://
, mailto:
, tel:
, sms:
) work automatically with no configuration.
Complete Example
This example shows multiple optional features. Remember: most apps only need the one-liner from “How to Use” above.
import 'package:flutter/material.dart';
import 'package:pnta_flutter/pnta_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize plugin - handles everything automatically
await PntaFlutter.initialize(
'prj_XXXXXXXXX',
metadata: {
'user_id': '123',
'user_email': 'user@example.com',
},
autoHandleLinks: true, // Optional: enable auto-handling of links
);
// App-level listeners - work everywhere, no disposal needed
PntaFlutter.foregroundNotifications.listen((payload) {
print('Foreground notification: ${payload['title']}');
});
PntaFlutter.onNotificationTap.listen((payload) {
print('Notification tapped: ${payload['link_to']}');
});
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: PntaFlutter.navigatorKey, // Required for deep linking
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('PNTA Example')),
body: Center(child: Text('Ready for notifications!')),
);
}
}