我已经实现了Firebase推送通知使用Firebase和react-native-push-通知包。
目前,我已经根据每个推送通知的点击操作实现了操作按钮。一旦应用程序位于前台,它就会工作,一旦应用程序被关闭,状态或后台操作按钮就不会显示。
我的FCM助手文件
class FCMServiceHelper {
register = (onRegister, onNotification, onOpenNotification) => {
this.checkPermission(onRegister);
this.createNotificationListeners(
onRegister,
onNotification,
onOpenNotification,
);
};
registerAppWithFCM = async () => {
if (Platform.OS === 'ios') {
await messaging().registerDeviceForRemoteMessages();
await messaging().setAutoInitEnabled(true);
}
};
checkPermission = (onRegister) => {
messaging()
.hasPermission()
.then((enabled) => {
if (enabled) {
// User has permissions
this.deleteToken()
this.getToken(onRegister);
} else {
// User doesn't have permission
this.requestPermission(onRegister);
}
})
.catch((error) => {
console.log('[FCMService] Permission rejected ', error);
});
};
getToken = (onRegister) => {
messaging()
.getToken(undefined,'*')
.then((fcmToken) => {
if (fcmToken) {
onRegister(fcmToken);
} else {
console.log('[FCMService] User does not have a device token');
}
})
.catch((error) => {
console.log('[FCMService] getToken rejected ', error);
});
};
requestPermission = (onRegister) => {
messaging()
.requestPermission()
.then(() => {
this.deleteToken()
this.getToken(onRegister);
})
.catch((error) => {
console.log('[FCMService] Request Permission rejected ', error);
});
};
deleteToken = () => {
console.log('[FCMService] deleteToken ');
messaging()
.deleteToken(undefined,'*')
.catch((error) => {
console.log('[FCMService] Delete token error ', error);
});
};
unregisterDeviceFromNotifications = () => {
console.log('[FCMService] unreg ');
messaging()
.unregisterDeviceForRemoteMessages()
.catch((error) => {
console.log('[FCMService] Unreg device ', error);
});
};
createNotificationListeners = (
onRegister,
onNotification,
onOpenNotification,
) => {
// When the application is running, but in the background
messaging().onNotificationOpenedApp((remoteMessage) => {
console.log(
'[FCMService] onNotificationOpenedApp Notification caused app to open from background state:',
remoteMessage,
);
if (remoteMessage) {
let notification = null;
let data = remoteMessage.data;
let openFromKilling = {"checked" : true}
notification = remoteMessage.notification;
notification.data = data;
notification.checking = openFromKilling;
onOpenNotification(notification);
}
});
// When the application is opened from a quit state.
messaging()
.getInitialNotification()
.then((remoteMessage) => {
console.log(
'[FCMService] getInitialNotification Notification caused app to open from quit state:',
remoteMessage,
);
if (remoteMessage) {
let notification = null;
let data = remoteMessage.data;
let openFromKilling = {"checked" : true}
notification = remoteMessage.notification;
notification.data = data;
notification.checking = openFromKilling;
onOpenNotification(notification);
}
});
// Foreground state messages
this.messageListener = messaging().onMessage(async (remoteMessage) => {
console.log(
'[FCMService] A new FCM message arrived! foreground',
remoteMessage,
);
if (remoteMessage) {
let notification = null;
let data = remoteMessage.data;
if (Platform.OS === 'ios') {
notification = remoteMessage.notification;
} else {
notification = remoteMessage.notification;
}
notification.data = data;
onNotification(notification);
// onOpenNotification(remoteMessage.data);
}
});
// Triggered when have new token
// messaging().onTokenRefresh((fcmToken) => {
// alert('REFRESH TOKEN');
// console.log('[FCMService] New token refresh: ', fcmToken);
// onRegister(fcmToken);
// });
};
unRegister = () => {
// if(this.messageListener){
this.messageListener();
// }
};
}
我的通知处理程序文件
fcmService.registerAppWithFCM();
fcmService.register(onRegister, onNotification, onOpenNotificaion , onAction);
localNotificationService.configure(onOpenNotificaion,onAction);
function onRegister(token) {
saveFCMToken(token);
}
if (Platform.OS == 'android') {
localNotificationService.createChannelAndroid('wapp');
}
function onNotification(notify) {
var RandomNumber = Math.floor(Math.random() * 100) + 1;
let actionData = [];
if(Platform.OS == 'android'){
if(notify.data.click_action == 'alert_dashboard'){
actionData = ["Update contact number"]
}else if(notify.data.click_action == 'account_edit'){
actionData = ["Update Email"]
}
}
const options = {
soundName: 'default',
playSound: true,
};
localNotificationService.showNotification(
RandomNumber,
notify.title,
Platform.OS == 'android' ? notify.body : notify.body,
notify,
options,
'wapp',
actionData
);
}
function onAction(notification) {
console.log ('Notification action received:');
console.log(notification.action);
console.log(notification);
}
通知助手文件
class NotificationHelper {
configure = (onOpenNotification) => {
PushNotification.configure({
onRegister: function (token) {
console.log('[NotificationManager] onRegister token:', token.token);
},
onNotification: function (notification) {
console.log('[NotificationManager] onNotification:', notification);
if (Platform.OS === 'ios') {
if (notification.data.openedInForeground) {
notification.userInteraction = true;
}
}
if (notification.userInteraction) {
onOpenNotification(notification);
} else {
onNotification(notification);
}
if (Platform.OS === 'android') {
notification.userInteraction = true;
}
// Only call callback if not from foreground
if (Platform.OS === 'ios') {
if (!notification.data.openedInForeground) {
notification.finish('backgroundFetchResultNoData');
}
} else {
notification.finish('backgroundFetchResultNoData');
}
},
onAction: function (notification) {
// alert(notification)
console.log("ACTION:", notification.action);
console.log("NOTIFICATION:", notification);
// notification.userInteraction = true;
// PushNotification.invokeApp(notification);
},
});
};
unregister = () => {
PushNotification.unregister();
};
createChannelAndroid = (channel) => {
PushNotification.createChannel(
{
channelId: channel, // (required)
channelName: 'My channel', // (required)
channelDescription: 'A channel to categorise your notifications', // (optional) default: undefined.
playSound: false, // (optional) default: true
soundName: 'default', // (optional) See `soundName` parameter of `localNotification` function
importance: 4, // (optional) default: 4. Int value of the Android notification importance
vibrate: true, // (optional) default: true. Creates the default vibration patten if true.
},
(created) => console.log(`createChannel returned '${created}'`), // (optional) callback returns whether the channel was created, false means it already existed.
);
};
showNotification = (id, title, message, data = {}, options = {}, channel , testData) => {
PushNotification.localNotification({
/* Android Only Properties */
...this.buildAndroidNotification(
id,
title,
message,
data,
options,
channel,
testData
),
/* iOS and Android properties */
...this.buildIOSNotification(id, title, message, data, options),
/* iOS and Android properties */
title: title || '',
message: message || '',
playSound: options.playSound || true,
soundName: options.soundName || 'default',
userInteraction: true, // BOOLEAN: If the notification was opened by the user from the notification area or not
});
};
buildAndroidNotification = (
id,
title,
message,
data = {},
options = {},
channel,
testData
) => {
console.log('TEST DATA -> ',data)
return {
showWhen: true, // This is probably not needed, since default value is TRUE.
when: new Date().getTime(),
group: "wapp",
groupSummary: true,
channelId: channel,
id: id,
autoCancel: true,
largeIcon: options.largeIcon || 'ic_launcher',
smallIcon: options.smallIcon || 'ic_launcher',
bigText: message || '',
subText: title || '',
vibrate: options.vibrate || true,
vibration: options.vibration || 300,
priority: options.priority || 'high',
importance: options.importance || 'high', // (optional) set notification importance, default: high,
data: data,
actions:testData,
// invokeApp:false,
};
};
buildIOSNotification = (id, title, message, data = {}, options = {}) => {
return {
alertAction: options.alertAction || 'view',
alertBody: message || '',
category: options.category || '',
userInfo: {
id: id,
item: data,
},
};
};
cancelAllLocalNotifications = () => {
if (Platform.OS === 'ios') {
PushNotificationIOS.removeAllDeliveredNotifications();
} else {
PushNotification.cancelAllLocalNotifications();
}
};
removeDeliveredNotificationByID = (notificationId) => {
console.log(
'[LocalNotificationService] removeDeliveredNotificationByID: ',
notificationId,
);
PushNotification.cancelLocalNotifications({id: `${notificationId}`});
};
}
我的应用index.js文件
/**
* @format
*/
import React from 'react';
import 'react-native-gesture-handler';
import { AppRegistry, LogBox, YellowBox } from 'react-native';
import App from './app/Entrypoint';
import { name as appName } from './app.json';
import { enableScreens } from 'react-native-screens';
import messaging from '@react-native-firebase/messaging';
import { backgroundGeo, checkLocationLogics } from './app/helpers/backgroundLocationTracking';
import env from 'react-native-config';
enableScreens();
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 />;
}
AppRegistry.registerComponent(appName, () => HeadlessCheck);
尝试调用setBackgroundMessageHandler中的showNotification方法,当应用程序未处于前台或已终止状态时,会调用该方法
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
console.log('Message handled in the background!', remoteMessage);
const options = {
soundName: 'default',
playSound: true,
};
const {title, body, data} = remoteMessage;
localNotificationService.showNotification(
title,
body,
data,
options,
}
});
解决方案见Deepa答案:) 我阅读了StackOverFlow中给出的所有解决方案,但在我的情况下似乎没有一个可行。问题是我的应用程序中有几个按钮,它们会对用户的操作做出不同的反应。例如,当应用程序启动时,除了两个按钮之外,所有按钮都被禁用。因此我将默认的drawable设置到XML中。当我打开一个文件时,所有这些都是可点击的,但其中一些,当按下时,需要保持按下(我已经这样做了),但其他的只是需
我正在使用一个android模拟器来测试通知。
参考:如何在颜色状态列表资源中指定背景颜色? 我已经按照上面链接中流行的答案。 我有以下绘图; 我理解,它将始终遵循优先顺序,因此在当前顺序中,只有激活和停用可能被触发。然而,目前我没有得到任何结果 我的按钮; 按钮显示为白色,在我的材质主题中,这是色彩主属性 首先,我假设一个主题覆盖了整个应用程序,但如果你明确指定一个特定按钮的背景,它应该覆盖主题值,如果我错了,请纠正我。 我从res/colo
我正在尝试制作一个调查应用程序,学习一些关于FragmentContainerView和导航图的知识。当我使用现有的小部件(如radiobuttons或checkboxes)来获取答案时,所有的工作都很完美。 当我尝试制作自己的小部件或更改一个普通按钮的行为以使其行为如以下屏幕截图所示时,问题就出现了: 该行为与ToggleButton类似,但我不想更改文本(开/关文本)。我需要的是,当我点击按钮
这肯定是个愚蠢的问题,因为stackoverflow中有很多相关的问题,也许答案很简单。但不管怎样,它在这里。我有一个按钮,并为它创建一个可绘制的xml。所以在我的按钮下面是代码: 现在,在我的drawable/button2下,我创建了一个选择器,其中我没有使用图像。下面是我的代码: 现在我要完成的是,当我单击该按钮时,它将其背景颜色改变为state_pressed所暗示的颜色,并且如果单击另一
我以编程方式生成了许多按钮(一些按钮用于增加值,而另一些按钮用于减少值),当它们调整的值达到最大值或最小值时,我会禁用这些按钮。(即,当达到最大值时,“增加”按钮被禁用,而当达到最小值时,“减少”按钮被禁用。)除了禁用,我还将按钮状态设置为“按下”,以直观地指示已达到极限值,并且按钮不再工作。 我的按钮onClickListener的'增加'按钮看起来像这样: ClickListeners上相应的