Entwickler · API v1.0.0

React-Native-Integration (Bare / CLI)

Dieser Leitfaden richtet sich an React-Native-Projekte (ohne Expo), die mit npx @react-native-community/cli init erstellt wurden. Die allgemeine API-Referenz finden Sie in der Überblick.

Unterstützte Versionen: React Native 0.74+ (inkl. New Architecture) · iOS 13.4+ · Android 7.0+ (API 24) · Node 18+

Da NotiPilot 1.0.0 über den Expo Push Service zustellt, benötigt das Gerät einen Expo Push Token. In einem Bare-React-Native-Projekt gibt es dafür zwei Wege:

Methode Wann?
A. expo-notifications (empfohlen) Für die meisten Projekte. Expo-Module werden dem Bare-Projekt hinzugefügt; ein Umstieg auf Expo ist nicht nötig.
B. @react-native-firebase/messaging + Token-Konvertierung Wenn das Projekt bereits Firebase Messaging nutzt.

Bei beiden Methoden müssen Sie ein EAS-Projekt anlegen (npx eas-cli init) und die FCM-V1- / APNs-Zugangsdaten mit eas credentials hochladen. Die EAS-Projekt-ID ist der Wert, der im NotiPilot-Dashboard im Feld Expo Project ID eingetragen und als app_id an die API gesendet wird.


Methode A — expo-notifications (empfohlen)

1. Installation

Terminal
npx install-expo-modules@latest
npx expo install expo-notifications expo-device expo-secure-store expo-localization expo-crypto expo-application
cd ios && pod install && cd ..

Android

  1. Laden Sie die Datei google-services.json aus der Firebase-Konsole herunter und legen Sie sie in android/app/ ab.
  2. android/build.gradle → dependencies { classpath 'com.google.gms:google-services:4.4.2' }
  3. android/app/build.gradle → ganz unten apply plugin: 'com.google.gms.google-services'

iOS (Xcode → Signing & Capabilities)

  1. Fügen Sie die Capability Push Notifications hinzu.
  2. Aktivieren Sie unter Background Modes die Option Remote notifications.

2. Client-Code

Sie können die Datei src/notipilot.ts aus dem Expo-Leitfaden unverändert übernehmen. Da es in einem Bare-Projekt kein expo-constants-Manifest gibt, geben Sie lediglich die Projekt-ID als Konstante an und beziehen app_version aus expo-application:

TypeScript
import * as Application from 'expo-application';

// Identisch mit der "Expo Project ID" im NotiPilot-Dashboard
const PROJECT_ID = 'IHRE-EAS-PROJEKT-ID';

// Attributes in registerDevice():
//   app_version: Application.nativeApplicationVersion,

Methode B — Firebase Messaging + Expo-Token-Konvertierung

Ist @react-native-firebase/messaging im Projekt bereits installiert, können Sie den nativen Token des Geräts in einen Expo-Token konvertieren und an NotiPilot senden.

Terminal
npm i @react-native-firebase/app @react-native-firebase/messaging react-native-get-random-values uuid @react-native-async-storage/async-storage react-native-localize react-native-device-info
TypeScript
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
import messaging from '@react-native-firebase/messaging';
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as RNLocalize from 'react-native-localize';
import DeviceInfo from 'react-native-device-info';
import { Platform, PermissionsAndroid } from 'react-native';

const NOTIPILOT_BASE_URL = 'https://app.notipilot.com/api/v1';
const PROJECT_ID = 'IHRE-EAS-PROJEKT-ID';

async function getDeviceUid() {
  let uid = await AsyncStorage.getItem('notipilot_device_uid');
  if (!uid) {
    uid = uuidv4();
    await AsyncStorage.setItem('notipilot_device_uid', uid);
  }
  return uid;
}

async function requestPermission(): Promise<boolean> {
  if (Platform.OS === 'android' && Platform.Version >= 33) {
    const r = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
    if (r !== PermissionsAndroid.RESULTS.GRANTED) return false;
  }
  const status = await messaging().requestPermission();
  return (
    status === messaging.AuthorizationStatus.AUTHORIZED ||
    status === messaging.AuthorizationStatus.PROVISIONAL
  );
}

/** Konvertiert den nativen FCM-/APNs-Token in einen Expo Push Token. */
async function toExpoPushToken(deviceUid: string): Promise<string> {
  const isIOS = Platform.OS === 'ios';
  const deviceToken = isIOS ? await messaging().getAPNSToken() : await messaging().getToken();
  if (!deviceToken) throw new Error('Nativer Push-Token konnte nicht abgerufen werden');

  const res = await fetch('https://exp.host/--/api/v2/push/getExpoPushToken', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      type: isIOS ? 'apns' : 'fcm',
      deviceId: deviceUid.toLowerCase(),
      development: __DEV__ && isIOS, // iOS-Debug-Builds nutzen die APNs-Sandbox
      appId: DeviceInfo.getBundleId(), // Android package / iOS bundle id
      deviceToken,
      projectId: PROJECT_ID,
    }),
  });
  if (!res.ok) throw new Error(`Expo-Token-Konvertierung fehlgeschlagen: ${res.status}`);
  const json = await res.json();
  return json.data.expoPushToken; // "ExponentPushToken[...]"
}

export async function registerDevice(extra: Record<string, string | number | boolean | null> = {}) {
  if (!(await requestPermission())) return null;

  const deviceUid = await getDeviceUid();
  const token = await toExpoPushToken(deviceUid);
  const locale = RNLocalize.getLocales()[0];

  const res = await fetch(`${NOTIPILOT_BASE_URL}/register-device`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      app_id: PROJECT_ID,
      device_uid: deviceUid,
      token,
      platform: Platform.OS,
      provider: 'expo',
      attributes: {
        locale: locale?.languageCode ?? null,
        country: RNLocalize.getCountry(),
        app_version: DeviceInfo.getVersion(),
        ...extra,
      },
    }),
  });
  return res.json();
}

// Bei Token-Erneuerung erneut registrieren
messaging().onTokenRefresh(() => registerDevice().catch(() => {}));

exp.host/--/api/v2/push/getExpoPushToken ist der Endpoint, den Expos eigene Bibliothek expo-notifications verwendet; er ist von Expo nicht gesondert dokumentiert. Langfristig ist Methode A die sicherste Option.

Für den Aufruf von identify-device und die Fehlerbehandlung können Sie die Funktionen identify, logout und post aus dem Expo-Leitfaden unverändert übernehmen.

Checkliste

  • EAS-Projekt angelegt, Projekt-ID im Dashboard als Expo Project ID eingetragen
  • FCM-V1- + APNs-Zugangsdaten mit eas credentials hochgeladen
  • Unter Android 13+ wird die Berechtigung POST_NOTIFICATIONS angefragt
  • Unter iOS sind die Capabilities Push Notifications + Remote notifications aktiviert
  • country und nach Möglichkeit city werden als Attributes gesendet