React Native

On Android the token comes from Firebase Messaging. On iOS, @react-native-firebase/messaging can hand over the raw APNs token, and that raw token is the one to register, since we deliver to Apple without Firebase in the middle. The console needs the Firebase key and the APNs key before either platform receives anything.

The adapter

The React Native adapter 1.6.0 passes its tests, and @bolrach/push-client goes up on npm once the publishing account exists.

In the meantime the code here relies on @react-native-firebase, which you can install from npm right now.

Register and report

// npm install @react-native-firebase/app @react-native-firebase/messaging
import messaging from "@react-native-firebase/messaging";
import { Platform } from "react-native";

export async function enablePush(push) {
  const status = await messaging().requestPermission();
  const granted = status === messaging.AuthorizationStatus.AUTHORIZED || status === messaging.AuthorizationStatus.PROVISIONAL;
  if (!granted) return;

  // Android: an FCM token. iOS: the raw APNs token, so Bolrach Push talks to Apple directly.
  const ios = Platform.OS === "ios";
  const token = ios ? await messaging().getAPNSToken() : await messaging().getToken();
  await push.register({ token, platform: ios ? "ios" : "android", provider: ios ? "apns" : "fcm" });

  messaging().onTokenRefresh((fresh) => push.register({ token: fresh, platform: "android", provider: "fcm" }));
  messaging().onNotificationOpenedApp((m) => push.report({ deliveryId: m.data?.delivery_id, event: "opened" }));
}

push.register makes the POST /installations call from the Android page and keeps the installation id and receipt token it returns. push.report posts them to /receipts.

Machine-readable: openapi.json. Console: bolrach.com/push.