How to Implement Push Notifications with Firebase Cloud Messaging

Firebase Cloud Messaging (FCM) gives Android apps a reliable way to deliver alerts, updates and personalised messages. It supports notification messages, data payloads, topic subscriptions and device-specific delivery through registration tokens. For an Australian Android app, it can power anything from a Brisbane delivery update to a Melbourne event reminder.

A working implementation needs more than adding the Firebase SDK. You must configure the Android project, request notification permission, create a notification channel, handle messages in the foreground and background, and send requests securely from a backend. The following approach suits apps built with Kotlin and Android Studio, whether the app is distributed across Australia or targeted at a smaller local audience.

Prepare The Firebase And Android Projects

Create a project in the Firebase Console, then register your Android application with its exact package name. Download google-services.json and place it in the app/ directory of the Android project. The package name must match the applicationId in Gradle, or Firebase services may fail to initialise correctly.

Add the Google services plugin and the Firebase Messaging dependency using the current Firebase Android setup recommended by Google. With the Firebase BoM, related libraries use compatible versions:

dependencies {
    implementation(platform("com.google.firebase:firebase-bom:<current-version>"))
    implementation("com.google.firebase:firebase-messaging")
}

Do not hard-code an old library version simply because it appears in an outdated tutorial. Firebase changes its Android libraries regularly, so check the official release notes before publishing. If the app is being maintained from Sydney while customers use it in Perth, also plan for different time zones when scheduling notification content.

Request Permission And Set Notification Defaults

Android 13 and later require the POST_NOTIFICATIONS runtime permission. Add it to AndroidManifest.xml, then request it at a suitable moment rather than immediately on the first screen. Explain the value clearly, such as receiving an order update or a severe weather notice, before displaying the system permission dialogue.

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Create a notification channel for Android 8.0 and above. A channel gives users control over sound, vibration and importance. Keep operational alerts separate from promotions, so somebody can silence marketing messages without missing a critical account notification. Australian users may have limited data or intermittent coverage in regional Queensland, Western Australia or the Northern Territory, making concise alerts and sensible retry behaviour important.

Set a default channel in the manifest if your notification payload may be displayed automatically while the app is in the background:

<meta-data
    android:name="com.google.firebase.messaging.default_notification_channel_id"
    android:value="@string/default_notification_channel_id" />

Handle Registration Tokens And Incoming Messages

FCM assigns a registration token to an app installation. Retrieve the current token when needed and send it to your backend over an authenticated HTTPS connection. Tokens can change after reinstallations, app data resets or security events, so implement onNewToken() and update the server whenever a replacement is issued.

Create a service extending FirebaseMessagingService to process incoming messages. onMessageReceived() is commonly called for data messages and notification messages received while the app is in the foreground. Use the payload to build a local notification with a PendingIntent that opens the correct screen.

class AppMessagingService : FirebaseMessagingService() {
    override fun onNewToken(token: String) {
        // Send the token securely to your application server
    }

    override fun onMessageReceived(message: RemoteMessage) {
        val title = message.notification?.title ?: "App update"
        val body = message.notification?.body ?: message.data["body"].orEmpty()
        // Create and display a notification on the appropriate channel
    }
}

Declare the service in the manifest with the Firebase messaging intent filter. Avoid placing sensitive information directly in notification text. A message such as “Your booking has changed” is safer than exposing an address or payment detail on a locked screen.

Implementation Checklist

  • Register the exact Android package name in Firebase
  • Store and refresh each device registration token
  • Request notification permission on Android 13 and later
  • Use separate channels for operational and promotional alerts

Send Messages Through A Secure Backend

For production delivery, send FCM messages from a trusted server using the Firebase Cloud Messaging HTTP v1 API or the Firebase Admin SDK. Never embed a Firebase service-account key in the Android application. Anything inside an APK can potentially be extracted, which could allow an attacker to send messages to your users.

A backend request can target a registration token, a topic or a condition. Use a token for a private device-specific update, while topics suit broad opt-in groups such as melbourne_events or brisbane_offers. Keep topic names general and avoid encoding personal information into them. Remove invalid tokens after Firebase reports that they are no longer registered.

Use a data payload when the application needs to decide how to display the alert. Use a notification payload when Firebase’s automatic background handling is appropriate. Include a stable deep-link identifier, an expiry time and an event ID so the app can avoid duplicate processing. Delivery is not guaranteed at an exact second, so FCM should not replace a real-time emergency communications system.

Design For Australian Users And Privacy

Notification timing should reflect Australian time zones rather than assuming a single national clock. Sydney, Melbourne, Brisbane, Canberra and Hobart generally follow Australian Eastern Time, while Adelaide uses Central Time and Perth uses Western Time. Daylight saving affects several eastern and southern states but not Queensland or Western Australia, so store user time zones and calculate delivery windows on the server.

Local context also affects message design. A short “Your parcel is arriving this arvo” may suit a friendly retail brand, while a banking or healthcare app should use restrained language. Consider transport delays, public holidays, sporting events and seasonal demand in cities such as Adelaide and Perth. For users on Telstra, Optus or Vodafone networks outside metropolitan areas, avoid relying on an image being available before the message has value.

Collect only the data needed to deliver and measure notifications. Explain notification preferences in the privacy policy, provide an easy opt-out, and review Australian Privacy Principles obligations under the Privacy Act 1988. Promotional messaging may also involve consent and unsubscribe requirements under the Spam Act 2003. Keep analytics identifiers, token records and device metadata protected, with retention limits and access controls.

Test Delivery, Deep Links And Reliability

Test with physical Android devices and different Android versions, because emulator behaviour does not represent every background, battery or network condition. Check foreground, background, force-stopped and recently updated states. Verify that tapping a message opens the intended screen when the app is closed, and that duplicate taps do not create duplicate orders or bookings.

Use Firebase reporting and your own server logs to track sends, failures, opens and application handling. Test permission denial, expired tokens, malformed payloads and revoked notification channels. Try both Wi-Fi and mobile data, including a low-connectivity scenario that resembles travel through regional New South Wales or a long road trip across Western Australia.

Delivery Scenarios To Verify

  • A foreground data message creates the correct local notification
  • A background notification opens the intended deep link
  • A denied permission produces no misleading in-app success state
  • An expired token is removed without affecting other devices

Use staged rollout through Google Play before sending large campaigns. Start with internal testers, then a small percentage of production users, watching crash reports, token errors and opt-out rates. Keep message content useful and infrequent; an app that interrupts people too often will quickly lose permission to speak.

Implementing Firebase Cloud Messaging well means treating delivery as part of the product experience, not just a Firebase configuration task. Configure the Android client, protect the sending credentials, respect Australian privacy expectations and test every app state before release. Begin with a small authenticated backend flow, validate it on devices in several Australian time zones, and expand to topics and segmentation once the fundamentals are reliable.