我使用
react-native Firebase
和 react-native-push-notification
创建了推送通知。我已经实现了所有类型的通知,如本地、日程背景和退出。但当我的应用程序处于退出状态时,我已通过 FCM 发送了推送通知。所以我在控制台上显示了一个警告,即“警告没有为关键的ReactNativeFirebaseMessagingHeadlessTask注册任务”。那我该如何解决呢。
代码:
import React, {Fragment, useEffect} from 'react';
import {StyleSheet, View, Text, Button} from 'react-native';
import PushNotification from 'react-native-push-notification';
import messaging from '@react-native-firebase/messaging';
//1
const checkPermission = () => {
messaging()
.hasPermission()
.then((enabled) => {
if (enabled) {
getToken();
} else {
requestPermission();
}
})
.catch((error) => {
console.log('error checking permisions ' + error);
});
};
//2
const requestPermission = () => {
messaging()
.requestPermission()
.then(() => {
getToken();
})
.catch((error) => {
console.log('permission rejected ' + error);
});
};
//3
const getToken = () => {
messaging()
.getToken()
.then((token) => {
console.log('push token ' + token);
})
.catch((error) => {
console.log('error getting push token ' + error);
});
};
const NotificationTwo = () => {
useEffect(() => {
checkPermission();
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
console.log('Message handled in the background!', remoteMessage);
});
});
const calledLocalNotify = () => {
PushNotification.localNotification({
/* Android Only Properties */
title: 'Hello world Local Notify', // (optional)
message: 'Successfully!, Implement the Local Notifications', // (required)
});
};
const calledLocalScheduleNotify = () => {
PushNotification.localNotificationSchedule({
//... You can use all the options from localNotifications
message: 'Successfully!, Implement the Local Schedule Notifications', // (required)
date: new Date(Date.now() + 60 * 1000), // in 60 secs
allowWhileIdle: false, // (optional) set notification to work while on doze, default: false
});
};
return (
<View style={styles.container}>
<Text>Push Notification</Text>
<View style={styles.button}>
<Button
color="green"
title="Local Notification"
onPress={calledLocalNotify}
/>
</View>
<View style={styles.button}>
<Button
color="purple"
title="Local Schedule Notification"
onPress={calledLocalScheduleNotify}
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
button: {
margin: 10,
},
});
export default NotificationTwo;
要设置后台处理程序,请尽早在应用程序逻辑之外调用 setBackgroundMessageHandler。
虽然该库支持在后台/退出状态下处理消息,但其工作方式的底层实现在 Android 和 iOS 上是不同的。
在 Android 上,会创建一个 Headless JS 任务(Android 独有的功能),该任务与主 React 组件分开运行;允许您的后台处理程序代码在不安装根组件的情况下运行。
但是在 iOS 上,当收到消息时,设备会在后台状态下静默启动您的应用程序。此时,您的后台处理程序(通过 setBackgroundMessageHandler)被触发,但您的根 React 组件也被安装。这对于某些用户来说可能会出现问题,因为任何副作用都会在您的应用程序内部调用(例如 useEffects、分析事件/触发器等)。要解决此问题,您可以配置 AppDelegate.m 文件(请参阅下面的说明)以将 isHeadless 属性注入根组件中。如果您的应用程序在后台启动,请使用此属性有条件地呈现 null(“无”):
在应用程序根文件夹中的index.js 文件上尝试此操作。
// index.js
import { AppRegistry } from 'react-native';
import messaging from '@react-native-firebase/messaging';
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
console.log('Message handled in the background!', remoteMessage);
});
function HeadlessCheck({ isHeadless }) {
if (isHeadless) {
// App has been launched in the background by iOS, ignore
return null;
}
return <App />;
}
function App() {
// Your application
}
AppRegistry.registerComponent('app', () => HeadlessCheck);
将这些行添加到您的
/android/app/src/main/AndroidManifest.xml
和
/android/app/src/debug/AndroidManifest.xml
文件 ...
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
....
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
....
<service android:name="com.emekalites.react.alarm.notification.ANService" android:enabled="true"/>
<receiver android:name="com.emekalites.react.alarm.notification.ANAlarmReceiver" android:enabled="true"/>
<receiver android:name="com.emekalites.react.alarm.notification.ANBootReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
...
</application>
....
</manifest>
现在,如果您使用 FCM 触发通知,请按照以下步骤操作:
import React from 'react';
import ReactNativeAN from 'react-native-alarm-notification';
import {AppRegistry} from 'react-native';
import messaging from '@react-native-firebase/messaging';
messaging().setBackgroundMessageHandler(async remoteMessage => {
const alarmNotifData = {
title: 'My Notification Title',
message: 'My Notification Message',
channel: 'my_channel_id',
small_icon: 'ic_launcher',
};
// trigger the alarm
ReactNativeAN.sendNotification(alarmNotifData);
});
function HeadlessCheck({isHeadless}) {
if (isHeadless) {
// App has been launched in the background by iOS, ignore
return null;
}
return <App />;
}
export default function App() {
return (
// your rest of the project
);
}
AppRegistry.registerComponent('app', () => HeadlessCheck);
此代码在任何情况下都可以像魅力一样工作(应用程序最小化、关闭、手机锁定等)。 现在要停止警报......您需要采取自己的方法。但这里有一些有用的功能。
ReactNativeAN.removeAllFiredNotifications();
ReactNativeAN.stopAlarmSound();
ReactNativeAN.deleteAlarm(alarmId);
享受!! ✨
帮助了我。
基本上编辑您的 './index.js' 以包含以下内容。
import {AppRegistry} from 'react-native';
import messaging from '@react-native-firebase/messaging';
import App from './App';
import {name as appName} from './app.json';
// Kill state Notification Listener.
messaging().setBackgroundMessageHandler(async remoteMessage => {
// Your code to handle notifications in killed state. For example
console.log('Killed state notification.', remoteMessage)
});
AppRegistry.registerComponent(appName, () => App);
/**
* @format
*/
import {AppRegistry} from 'react-native';
import App from './App';
import messaging from '@react-native-firebase/messaging';
import {name as appName} from './app.json';
// Register background handler
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
});
//KillState
messaging().getInitialNotification(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
});
AppRegistry.registerComponent(appName, () => App);
在使用 messages().getInitialNotification() 之前还要注意:
* Beware of this [issue](https://github.com/invertase/react-native-firebase/issues/3469#issuecomment-660121376) when integrating with splash screen modules. If you are using * `react-native-splash-screen` we strongly recommend you migrate to `react-native-bootsplash`