blutrixx/nativephp-fcm

Firebase Cloud Messaging (FCM) push notification plugin for NativePHP Mobile

Maintainers

Package info

github.com/joelnjoshkibona/nativephp-fcm

Language:Kotlin

Type:nativephp-plugin

pkg:composer/blutrixx/nativephp-fcm

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-08-14 14:01 UTC

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.json in 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_NOTIFICATIONS permission (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 on com.google.firebase.MESSAGING_EVENT
  • Requires google-services.json at the app root and the Google Services Gradle plugin (already present in NativePHP Mobile's default build.gradle.ktsid("com.google.gms.google-services"))