FCM (Android and web push)

Firebase Cloud Messaging carries Android push and web push. As with APNs, Appwin sends with your credentials.

Appwin uses the FCM v1 API, the one that authenticates with a service account. The old legacy server keys (AAAA…) do not work - Google has retired them.

1. Project ID and service account

In the Firebase console, on your project. While you are there, check that Cloud Messaging (API V1) is enabled.

  1. 1

    Collect the Project ID

    Gear icon → Project settings → General tab → "Project ID", of the form my-app-1a2b3.

    That is the technical identifier, not the display name. The two often look alike, and confusing them gives a 404 on every send.

    Firebase Project ID in Settings → General.

  2. 2

    Open Service accounts

    Project settings → Service accounts tab.

    Service accounts tab in Firebase.

  3. 3

    Generate the private key

    Generate new private key → confirm. The JSON downloads.

    Generating a Firebase service account private key.

    The JSON cannot be downloaded again. If lost, generate a new one and delete the old one from Google Cloud.

  4. 4

    Import in Appwin

    Settings → Projects → your app → Integrations → Firebase Cloud Messaging.

    FieldValue
    Firebase Project IDmy-app-1a2b3
    Service Account JSONThe entire contents of the file

    Use Import a file rather than a copy and paste: the JSON contains a private key with escaped \n, which a clipboard damages easily.

    Importing the service account JSON into Appwin.

2. Register the device token

Every device declares its FCM token after permission is granted.

dart
final token = await FirebaseMessaging.instance.getToken();
if (token != null) {
  await AppwinCore.instance.registerPushToken(
    token: token,
    platform: 'android',
    pushOptIn: true,
  );
}

FCM can rotate a token at any time. Hook registration onto onTokenRefresh as well, otherwise the device becomes unreachable with no warning:

dart
FirebaseMessaging.instance.onTokenRefresh.listen((token) {
  AppwinCore.instance.registerPushToken(
    token: token,
    platform: 'android',
  );
});

pushOptIn reflects the user's consent. Set it back to false if they withdraw permission, rather than stopping token registration: that keeps "declined" distinguishable from "never seen".

Checking

As with APNs, a missing key makes the API simulate the send rather than fail. A campaign can therefore look like it went out with nothing sent.

Check the API logs: a not configured - simulating delivery message means the key is missing.

Troubleshooting

SymptomLikely cause
Android silentAn old legacy server key instead of a service account
404 on every sendThe display name entered instead of the project ID
UNREGISTEREDStale token: the app was uninstalled, or refresh is not hooked up
SENDER_ID_MISMATCHThe token comes from a different Firebase project than the configured one
JSON rejectedFile truncated on copy and paste: use the import
Nothing goes out at allNo key: the API simulates and says so in its logs

Next