blutrixx / nativephp-fcm
Firebase Cloud Messaging (FCM) push notification plugin for NativePHP Mobile
Package info
github.com/joelnjoshkibona/nativephp-fcm
Language:Kotlin
Type:nativephp-plugin
pkg:composer/blutrixx/nativephp-fcm
Requires
- php: ^8.1
This package is not auto-updated.
Last update: 2026-08-15 12:22:18 UTC
README
A NativePHP Mobile plugin for Firebase Cloud Messaging (FCM) push notifications on Android. Handles requesting notification permission, retrieving/refreshing the FCM registration token, and receiving + displaying incoming pushes (foreground and background). Sending pushes is your app's own job — this package only handles the device side.
Composer package: blutrixx/nativephp-fcm
Repo: joelnjoshkibona/nativephp-fcm
Current release: v1.0.0 — verified end-to-end on a real Android device (device registered a
live FCM token with a real backend, a real push sent via the FCM HTTP v1 API was received and
displayed).
Requirements
- PHP ^8.1
- A Laravel app running under
nativephp/mobile, Android only (no iOS support in this package) - A real Firebase project:
google-services.jsonin the app's root (client config) and, on the server side, a service-account key for actually sending pushes (this package doesn't send — see Sending pushes below). Both must belong to the same Firebase project — a token registered under one project cannot receive pushes sent via another project's service account. - Android: requests
POST_NOTIFICATIONSpermission (Android 13+ only; notifications are enabled by default on older versions)
Installation
Not on Packagist yet.
As a git submodule (how this repo itself consumes it):
git submodule add https://github.com/joelnjoshkibona/nativephp-fcm.git packages/nativephp-fcm
// composer.json { "repositories": [ {"type": "path", "url": "packages/nativephp-fcm"} ], "require": { "blutrixx/nativephp-fcm": "@dev" } }
Without a submodule:
{
"repositories": [
{"type": "vcs", "url": "https://github.com/joelnjoshkibona/nativephp-fcm"}
],
"require": {
"blutrixx/nativephp-fcm": "^1.0"
}
}
Laravel auto-discovers FcmServiceProvider. There's no facade — see
How the bridge works for why.
How the bridge works
All three bridge functions are synchronous — no async download/progress lifecycle like
nativephp-mobile-updater. There's no PHP facade because nothing here has a meaningful
server-side equivalent to call; every method is invoked directly from JS via BridgeCall.
Incoming pushes are handled entirely native-side by NativePHPFirebaseMessagingService
(Android's FirebaseMessagingService) — there's no PHP involvement in receiving/displaying a
push. A new/refreshed FCM token during RequestPermission fires a TokenGenerated event the
same way nativephp-mobile-updater's download events work (matching by .endsWith() on the
event name — see that package's README for the exact JS listener pattern).
API reference
| Method | Sync? | Returns | Notes |
|---|---|---|---|
GetToken() |
Sync | {token: string} |
Reads the current FCM token. Falls back to the last token cached in SharedPreferences (by onNewToken) if the live Firebase call fails. |
RequestPermission() |
Sync (blocks on token fetch) | {token: string} |
Requests POST_NOTIFICATIONS (Android 13+) if not already granted, then fetches/caches the FCM token and dispatches TokenGenerated once available. |
CheckPermission() |
Sync | {status: 'granted' | 'denied'} |
Checks current permission state without requesting it. |
import { BridgeCall } from '@nativephp/mobile' const { status } = await BridgeCall('PushNotification.CheckPermission', {}) if (status !== 'granted') { const { token } = await BridgeCall('PushNotification.RequestPermission', {}) // token is also delivered via the TokenGenerated event — see below } document.addEventListener('native-event', (e) => { const { event: eventName, payload } = e.detail if (eventName.endsWith('PushNotification\\TokenGenerated')) { const { token } = typeof payload === 'string' ? JSON.parse(payload) : payload // POST this token to your backend's device-token registration endpoint } })
Sending pushes (not this package's job)
This package never talks to Firebase's send API — that's a server-side concern with its own
service-account credential, entirely separate from google-services.json (which only configures
the client). Your backend needs its own FCM HTTP v1 API integration (or a library like
kreait/firebase-php) to actually deliver a push to a token this package retrieved.
Quick start: full push flow
The pattern this package's own test app (MOBILE_APP) uses, end to end — request permission +
register the token after login, then re-register automatically whenever FCM rotates the token:
// resources/js/src/composables/usePushNotifications.ts (excerpt) import { BridgeCall } from '@nativephp/mobile' async function requestPermissionAndRegister() { const { token } = await BridgeCall('PushNotification.RequestPermission', {}) if (!token) return // permission denied await sendPostRequest('/device-tokens/register', { token, platform: 'android', device_name: navigator.userAgent.substring(0, 100), }) } // Call after a successful login: await requestPermissionAndRegister() // Token can rotate at any time (reinstall, app data clear) — listen and re-register: document.addEventListener('native-event', (e) => { const { event: eventName, payload } = e.detail if (!eventName.endsWith('PushNotification\\TokenGenerated')) return const { token } = typeof payload === 'string' ? JSON.parse(payload) : payload sendPostRequest('/device-tokens/register', { token, platform: 'android', device_name: navigator.userAgent.substring(0, 100) }) })
// Server side — a real send, once you have a token in your own device-tokens table. // See SendNotificationJob::sendFcmPush() in this test app's BACKEND for the full version // (handles token deactivation on failed sends, batching, etc.) — the essential call: use Google\Auth\Credentials\ServiceAccountCredentials; use Illuminate\Support\Facades\Http; $credentials = new ServiceAccountCredentials( 'https://www.googleapis.com/auth/firebase.messaging', json_decode(file_get_contents(config('firebase.credentials_file')), true) ); $accessToken = $credentials->fetchAuthToken()['access_token']; Http::withToken($accessToken)->post( 'https://fcm.googleapis.com/v1/projects/' . config('firebase.project_id') . '/messages:send', ['message' => ['token' => $deviceToken, 'data' => ['title' => 'Hello', 'body' => 'It works']]] );
A device-token registration endpoint isn't part of this package (it's ordinary backend CRUD —
match a token to a user, deactivate it on a failed send) — the shape above is what this test app's
UserDeviceTokensModel/DeviceTokenController implement, one reasonable way to do it.
Android manifest impact
- Permission:
android.permission.POST_NOTIFICATIONS - Service:
com.nativephp.firebase.push.NativePHPFirebaseMessagingService, intent-filtered oncom.google.firebase.MESSAGING_EVENT - Requires
google-services.jsonat the app root and the Google Services Gradle plugin (already present in NativePHP Mobile's defaultbuild.gradle.kts—id("com.google.gms.google-services"))