The Push Notifications API provides a unified interface for requesting push notification permissions and managing push tokens across iOS (APNS) and Android (FCM).
Usage
Enroll for push notifications and request permissions:
use Native\Mobile\Facades\PushNotifications;
// Simple enrollment
PushNotifications::enroll();
// Enrollment with tracking
PushNotifications::enroll()
->id('user-' . auth()->id())
->remember();
When the token is generated, the TokenGenerated event is dispatched with the push token.
Requesting Permissions
The enroll() method handles the entire permission flow:
- Requests notification permissions from the OS
- Registers for push notifications
- Generates a push token (APNS for iOS, FCM for Android)
- Dispatches the
TokenGenerated event
use Native\Mobile\Facades\PushNotifications;
PushNotifications::enroll();
Checking Permission Status
Check the current permission status without prompting the user:
$status = PushNotifications::checkPermission();
// Possible values:
// - "granted" - User has granted permission
// - "denied" - User has denied permission
// - "not_determined" - User hasn't been asked yet
// - "provisional" - iOS provisional authorization (quiet notifications)
// - "ephemeral" - iOS ephemeral authorization (App Clips)
if ($status === 'granted') {
// Notifications are enabled
}
Getting the Push Token
Retrieve the current push token:
$token = PushNotifications::getToken();
if ($token) {
// APNS token on iOS, FCM token on Android
// Send this to your backend server
}
Listening for Token Generation
Listen for the TokenGenerated event in your Livewire components:
use Livewire\Attributes\On;
use Native\Mobile\Events\PushNotification\TokenGenerated;
class NotificationSettings extends Component
{
#[On('native:Native\\Mobile\\Events\\PushNotification\\TokenGenerated')]
public function handleTokenGenerated($data)
{
$token = $data['token'];
$id = $data['id'] ?? null;
// Save the token to your backend
auth()->user()->update([
'push_token' => $token,
]);
}
}
Tracking Enrollment
Use unique identifiers to track specific enrollment requests:
// Enroll with an ID
PushNotifications::enroll()
->id('enrollment-' . time())
->remember();
// In your event handler
#[On('native:Native\\Mobile\\Events\\PushNotification\\TokenGenerated')]
public function handleTokenGenerated($data)
{
$enrollmentId = $data['id'];
$rememberedId = PendingPushNotificationEnrollment::lastId();
if ($enrollmentId === $rememberedId) {
// This is the enrollment we initiated
}
}
Custom Event Classes
Dispatch custom events when the token is generated:
use Native\Mobile\Facades\PushNotifications;
use App\Events\UserEnrolledForNotifications;
PushNotifications::enroll()
->event(UserEnrolledForNotifications::class);
Your custom event should accept these parameters:
namespace App\Events;
class UserEnrolledForNotifications
{
public function __construct(
public string $token,
public ?string $id = null
) {}
}
Methods Reference
PushNotifications Facade
enroll()
Requests push notification permissions and enrolls for notifications.
Returns: PendingPushNotificationEnrollment
PushNotifications::enroll();
checkPermission()
Checks the current notification permission status without prompting.
Returns: string|null
Possible values:
"granted" - User has granted permission
"denied" - User has denied permission
"not_determined" - User hasn’t been asked yet (iOS)
"provisional" - Provisional authorization granted (iOS)
"ephemeral" - Ephemeral authorization granted (iOS App Clips)
$status = PushNotifications::checkPermission();
if ($status === 'not_determined') {
// User hasn't been asked yet - good time to explain benefits
}
getToken()
Retrieves the current push notification token.
Returns: string|null
- On iOS: Returns APNS token
- On Android: Returns FCM token
- Returns
null if no token is available
$token = PushNotifications::getToken();
if ($token) {
// Send token to your backend
}
PendingPushNotificationEnrollment Methods
id(string $id)
Sets a unique identifier for this enrollment.
Parameters:
$id (string) - Unique identifier for the enrollment
Returns: self
PushNotifications::enroll()->id('user-123');
getId()
Gets the enrollment’s unique identifier. Generates a UUID if not set.
Returns: string
$enrollment = PushNotifications::enroll();
$id = $enrollment->getId();
event(string $eventClass)
Sets a custom event class to dispatch when the token is generated.
Parameters:
$eventClass (string) - Fully qualified class name of the event
Returns: self
Throws: InvalidArgumentException if the class doesn’t exist
PushNotifications::enroll()->event(CustomTokenEvent::class);
remember()
Stores the enrollment ID in the session for later retrieval.
Returns: self
PushNotifications::enroll()->id('user-123')->remember();
lastId()
Retrieves the last remembered enrollment ID from the session.
Returns: string|null
$lastId = PendingPushNotificationEnrollment::lastId();
enroll()
Explicitly starts the enrollment process.
Returns: void
PushNotifications::enroll()->enroll();
If you don’t call enroll() explicitly, the enrollment will automatically start when the PendingPushNotificationEnrollment object is destroyed.
Complete Example
use Livewire\Component;
use Livewire\Attributes\On;
use Native\Mobile\Facades\PushNotifications;
use Native\Mobile\PendingPushNotificationEnrollment;
class NotificationPreferences extends Component
{
public $permissionStatus = 'unknown';
public $pushToken = null;
public $isEnrolled = false;
public function mount()
{
$this->checkPermissionStatus();
$this->pushToken = PushNotifications::getToken();
$this->isEnrolled = $this->pushToken !== null;
}
public function checkPermissionStatus()
{
$this->permissionStatus = PushNotifications::checkPermission() ?? 'unknown';
}
public function enableNotifications()
{
if ($this->permissionStatus === 'denied') {
// Can't request again - user must enable in settings
session()->flash('message', 'Please enable notifications in your device settings.');
return;
}
// Request permissions and enroll
PushNotifications::enroll()
->id('user-' . auth()->id())
->remember();
}
#[On('native:Native\\Mobile\\Events\\PushNotification\\TokenGenerated')]
public function handleTokenGenerated($data)
{
$token = $data['token'];
$enrollmentId = $data['id'] ?? null;
$rememberedId = PendingPushNotificationEnrollment::lastId();
// Verify this is our enrollment
if ($enrollmentId === $rememberedId) {
$this->pushToken = $token;
$this->isEnrolled = true;
// Save to database
auth()->user()->update([
'push_token' => $token,
'push_platform' => PHP_OS, // iOS or Android
]);
// Send to your backend API
Http::post('https://api.yourapp.com/push-tokens', [
'user_id' => auth()->id(),
'token' => $token,
'platform' => PHP_OS,
]);
session()->flash('message', 'Notifications enabled successfully!');
}
}
public function render()
{
return view('livewire.notification-preferences');
}
}
iOS (APNS)
- Returns APNS device token
- Requires proper app signing with push notification capability
- Configure push notifications in Xcode:
- Enable “Push Notifications” capability
- Configure APNS certificates in Apple Developer portal
- Permission states:
not_determined - User hasn’t been asked
granted - Full notification permissions
denied - User declined permissions
provisional - Provisional authorization (quiet notifications)
ephemeral - App Clip authorization
Info.plist:
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
Android (FCM)
- Returns Firebase Cloud Messaging (FCM) registration token
- Requires Firebase configuration:
- Add
google-services.json to your Android project
- Configure Firebase in your app’s build.gradle
- On Android 13+, requires POST_NOTIFICATIONS permission
- Permission states are simpler:
granted - Permission granted
denied - Permission denied
AndroidManifest.xml (Android 13+):
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Testing
Development Testing
// Check if enrollment works
$status = PushNotifications::checkPermission();
dd($status); // Should return current permission state
// Get current token
$token = PushNotifications::getToken();
dd($token); // Should return token if enrolled
Testing Push Notifications
- iOS: Use APNS testing tools or your backend to send test notifications
- Android: Use Firebase Console to send test messages to specific tokens
Best Practices
- Explain Before Asking: Show users why notifications are valuable before requesting permission
public function showNotificationBenefits()
{
// Show modal explaining notification benefits
$this->showBenefitsModal = true;
}
public function requestPermissions()
{
PushNotifications::enroll();
}
- Handle Denied State: Guide users to settings if they’ve denied permission
if (PushNotifications::checkPermission() === 'denied') {
// Show instructions to enable in settings
}
-
Store Tokens Securely: Always store push tokens associated with the user in your database
-
Update Tokens: Tokens can change - always update when you receive a new one
-
Handle Token Expiry: Implement logic to refresh tokens when they become invalid