我已经使用react-native Firebase
和react-native-push-notification
创建了一个推送通知。我已经实现了所有类型的通知,如本地、日程后台和退出。但当我的应用程序处于退出状态时,我已经通过FCM发送了推送通知。所以我在控制台上显示了一个警告,它是WARN没有为密钥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;
当应用程序处于后台或退出状态时,接收消息时不会调用onMessage处理程序。相反,您需要通过setBackgroundMessageHandler方法设置一个后台回调处理程序。
要设置后台处理程序,请尽早在应用程序逻辑之外调用setBackgroundMessageHandler。
尽管该库支持在后台/退出状态下处理消息,但在安卓系统上,其工作原理的底层实现有所不同;iOS。
在Android上,会创建一个Headless JS任务(仅限Android功能(,该任务与您的主React组件分开运行;允许后台处理程序代码在不安装根组件的情况下运行。
然而,在iOS上,当收到消息时,设备会在后台状态下静默地启动您的应用程序。此时,您的后台处理程序(通过setBackgroundMessageHandler(被触发,但您的根React组件也被挂载。这对一些用户来说可能会有问题,因为任何副作用都会在应用程序内部调用(例如useEffects、分析事件/触发器等(。为了解决这个问题,您可以配置AppDelegate.m文件(请参阅下面的说明(,将isHeadless道具注入到根组件中。如果您的应用程序是在后台启动的,请使用此属性有条件地呈现null("nothing"(:
请在应用程序根文件夹中的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);
享受吧!!✨
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);
在使用messaging((之前也要注意。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`