本文主要以
ReactNative IOS
端为演示;以下为正文。
安装
npm install @react-native-community/push-notification-ios --save
# pod install
cd ios && pod install && cd ../
IOS配置
在工程里面找到 AppDekegate.h
,在头部引入下面依赖。
#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h> // add line
// add UNUserNotificationCenterDelegate
@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>
@end
同样,在 AppDekegate.mm
里面添加如下代码。
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTRootView.h>
#import <React/RCTBundleURLProvider.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"timememory";
// 定义通知实例 UNUserNotificationCenter
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
// 新架构使用了JavaScript Instanface(JSI)设计,Fabric 替代之前的 UI Manager 渲染系统
// UI Manager 是绘制元素位置,用于渲染。在Android里面就是viewGroup, Ios里面就是 UIView
// 新架构的 JSI 可以直接调用 Native/UI Thread, JSI 支持其他引擎渲染、例如 V8
// JSI 直接通讯 Native 省略了,之前异步调用过程
// 在 JSI 里 Native 方法会通过 C++ Host Objects 暴露给 JS, 而 JS 可以持有对这些对象的引用,并且使用这些引用直接调用对应的方法。
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
[RNCPushNotificationIOS didReceiveNotificationResponse:response];
}
// 注入前台通知 Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(nonnull UNNotification *)notification withCompletionHandler:(nonnull void (^)(UNNotificationPresentationOptions))completionHandler {
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@"bundle/main" withExtension:@"jsbundle"];
#endif
}
/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
///
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`.
- (BOOL)concurrentRootEnabled
{
return true;
}
@end
项目中使用
useEffect(() => {
const type: "notification" | "localNotification" = 'notification'
PushNotificationIOS.addEventListener(type, onRemoteNotification)
return () => {
PushNotificationIOS.removeEventListener(type)
}
}, [])
const onRemoteNotification = () => {
const isChecked = notification.getData().userInteraction === 1;
if (isChecked) {
console.log('isChecked', isChecked)
} else {
// TODO
}
const result = PushNotificationIOS.FetchResult.NoData;
notification.finish(result)
}
示例
推送一条通知消息。
const setNotificationCategories = () => {
PushNotificationIOS.setNotificationCategories([
{
id: 'userAction',
actions: [
{ id: 'open', title: '消息通知', options: { foreground: true }},
{ id: 'ignore', title: 'Desruptive', options: { foreground: true, destructive: true }},
{
id: 'text',
title: 'Text Input',
options: { foreground: true },
textInput: { buttonTitle: 'Send' }
}
]
}
])
}