Tích hợp push notification React Native
TypeScript, RN 0.71+. Dựa trên @react-native-firebase/messaging và react-native-callkeep.
⚛️ React Native
TypeScript, RN 0.71+. Dựa trên @react-native-firebase/messaging và react-native-callkeep.
Tải SDK trong bảng điều khiển (mục Hướng dẫn tích hợp) sau khi tạo tài khoản miễn phí.
Cài đặt
Giải nén file tải về vào thư mục gốc của project (tạo ra thư mục
PushConsoleSDK/), cấu hình Firebase theo rnfirebase.io, rồi:Terminalnpm install ./PushConsoleSDK/react-native/push-console \ @react-native-firebase/app @react-native-firebase/messaging \ react-native-callkeep react-native-voip-push-notification \ @react-native-async-storage/async-storage react-native-device-info cd ios && pod install
React Native 0.71+. Expo cần development build (không chạy trong Expo Go).
Handler nền trong index.js
index.js// index.js — đăng ký TRƯỚC AppRegistry import { AppRegistry } from 'react-native'; import messaging from '@react-native-firebase/messaging'; import PushConsole from '@pushconsole/react-native'; import App from './App'; import { name as appName } from './app.json'; messaging().setBackgroundMessageHandler(async (message) => { await PushConsole.handleBackgroundMessage(message); // Android: hiện màn hình cuộc gọi }); AppRegistry.registerComponent(appName, () => App);Khởi tạo trong component gốc
App.tsximport { useEffect } from 'react'; import PushConsole from '@pushconsole/react-native'; export default function App() { useEffect(() => { PushConsole.initialize( { appId: 'YOUR_APP_ID', serverUrl: 'https://tingpush.com', appName: 'MyApp' }, { onCallEvent: ({ action, call }) => { if (action === 'accepted') { // Người dùng bấm Nghe → kết nối cuộc gọi (call.id, call.data.room) } }, onNotificationOpened: (data) => { /* điều hướng theo data */ }, }, ); }, []); // ... }Gắn user khi đăng nhập
TypeScriptawait PushConsole.login('user-123'); // sau khi đăng nhập await PushConsole.logout(); // khi đăng xuất await PushConsole.setTags({ plan: 'vip' }); PushConsole.endCall(callId); // kết thúc cuộc gọiiOS: bật capability và sửa AppDelegate (cho cuộc gọi)
Xcode → Signing & Capabilities: Push Notifications, Background Modes (Remote notifications + Voice over IP). VoIP push bắt buộc báo CallKit bằng code native:
ios/AppDelegate.mm// AppDelegate.mm #import <PushKit/PushKit.h> #import "RNCallKeep.h" #import "RNVoipPushNotificationManager.h" @interface AppDelegate () <PKPushRegistryDelegate> @end // Trong didFinishLaunchingWithOptions, trước return: // [RNVoipPushNotificationManager voipRegistration]; - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type { [RNVoipPushNotificationManager didUpdatePushCredentials:credentials forType:(NSString *)type]; } - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion { NSDictionary *p = payload.dictionaryPayload; NSString *uuid = p[@"call_id"] ?: [[NSUUID UUID] UUIDString]; NSString *name = p[@"caller_name"] ?: @""; NSString *handle = p[@"caller_handle"] ?: name; BOOL hasVideo = [p[@"is_video"] isEqualToString:@"true"]; [RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type]; [RNCallKeep reportNewIncomingCall:uuid handle:handle handleType:@"generic" hasVideo:hasVideo localizedCallerName:name supportsHolding:NO supportsDTMF:NO supportsGrouping:NO supportsUngrouping:NO fromPushKit:YES payload:p withCompletionHandler:completion]; }AppDelegate.swift (RN 0.77+): làm tương tự, thêm các header vào bridging header.
Android: khai báo ConnectionService
android/app/src/main/AndroidManifest.xml<uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <application> <service android:name="io.wazo.callkeep.VoiceConnectionService" android:label="Wazo" android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" android:foregroundServiceType="camera|microphone" android:exported="true"> <intent-filter><action android:name="android.telecom.ConnectionService" /></intent-filter> </service> <service android:name="io.wazo.callkeep.RNCallKeepBackgroundMessagingService" /> </application>Lần đầu, Android hỏi quyền "tài khoản gọi điện"; một số máy cần bật trong Cài đặt → Ứng dụng gọi điện.
✅ Kiểm tra sau khi tích hợp
- Chạy app trên máy thật, bật log: thấy
[PushConsole] Đã đăng ký thiết bị …. - Tab Thiết bị của dự án: thiết bị xuất hiện; máy iOS có badge VoIP nếu dùng cuộc gọi.
- Tab Gửi thông báo: gửi thử tới thiết bị đó.
- Chọn 📞 Cuộc gọi, gửi thử khi app đang mở, khi đã tắt app và khi màn hình đang khoá.