react-native - 将 Expo React Native 应用程序中的推送通知一次发送到多个设备?
问题描述
我仍然是 React Native 的新手,但我正在尝试将推送通知集成到我的 iOS 和 Android 设备中。我在 Expo 上看到的大多数教程都使用他们的网站使用特定令牌推送通知,但我不想这样做。我想一次向多台设备发送一个通知(无论设备上的操作系统如何,也就是 iOS 或 Android)。我认为我最好的选择是通过 Firebase 来完成,这就是本教程所做的。我还找到了GitHub与教程相匹配,但他们使用现在已弃用的 ListView。我收到无法在该 Github 的代码中使用 ListView 的错误,当我尝试将其切换到 Flatlist 时,我收到一个错误,指出 cloneWithRows 不是一个函数。有人可以帮我处理那部分代码吗?或者,如果您有关于如何将通知推送到多个设备的替代资源,请告诉我。编辑:为了方便起见,我将从 GitHub 发布下面的代码。所有学分都归他所有。TLDR:代码不起作用,因为 ListView 已被弃用,如果我将其更改为 FlatList,则 cloneWithRows 不起作用。不确定如何使用 Flatlist 对其进行重组,如果可以,请提供帮助。
import React from 'react';
import { StyleSheet, Text, View, StatusBar} from 'react-native';
import { Container, Content, Header, Form, Input, Item, Button, Label, Icon, List } from 'native-base'
import firebase from 'firebase';
import { Permissions, Notifications } from 'expo';
import { FlatList } from 'react-native';
import { ListView } from 'react-native';
var data = []
export default class App extends React.Component {
static navigationOptions = {
header: null
}
constructor(props) {
super(props);
this.ds = new ListView({ rowHasChanged: (r1, r2) => r1 !== r2 })
this.state = {
listViewData: data,
newContact: "",
currentUser: ""
}
}
componentDidMount() {
var currentUser
var that = this
listener = firebase.auth().onAuthStateChanged(function (user) {
if (user != null) {
currentUser = user
that.registerForPushNotificationsAsync(currentUser)
}
listener();
});
firebase.database().ref('/contacts').on('child_added', function (data) {
var newData = [...that.state.listViewData]
newData.push(data)
that.setState({ listViewData: newData })
})
}
loadSubscribers = () => {
var messages = []
//return the main promise
return firebase.database().ref('/subscribers').once('value').then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var childKey = childSnapshot.key;
messages.push({
"to": childKey,
"sound": "default",
"body": "New Note Added"
});
});
//firebase.database then() respved a single promise that resolves
//once all the messages have been resolved
return Promise.all(messages)
}).catch(error => {
console.log(error)
})
}
registerForPushNotificationsAsync = async (currentUser) => {
const { existingStatus } = await Permissions.getAsync(Permissions.NOTIFICATIONS);
let finalStatus = existingStatus;
// only ask if permissions have not already been determined, because
// iOS won't necessarily prompt the user a second time.
if (existingStatus !== 'granted') {
// Android remote notification permissions are granted during the app
// install, so this will only ask on iOS
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
// Stop here if the user did not grant permissions
if (finalStatus !== 'granted') {
return;
}
// Get the token that uniquely identifies this device
let token = await Notifications.getExpoPushTokenAsync();
// POST the token to our backend so we can use it to send pushes from there
var updates = {}
updates['/expoToken'] = token
await firebase.database().ref('/users/' + currentUser.uid).update(updates)
//call the push notification
}
addRow(data) {
var key = firebase.database().ref('/contacts').push().key
firebase.database().ref('/contacts').child(key).set({ name: data })
}
async deleteRow(secId, rowId, rowMap, data) {
await firebase.database().ref('contacts/' + data.key).set(null)
rowMap[`${secId}${rowId}`].props.closeRow();
var newData = [...this.state.listViewData];
newData.splice(rowId, 1)
this.setState({ listViewData: newData });
}
render() {
return (
<Container style={styles.container} >
<Header style={{ marginTop: StatusBar.currentHeight }}>
<Content>
<Item>
<Input
onChangeText={(newContact) => this.setState({ newContact })}
placeholder="Add Note"
/>
<Button onPress={() => this.addRow(this.state.newContact)}>
<Icon name="add" />
</Button>
</Item>
</Content>
</Header>
<Content>
<List
enableEmptySections
dataSource={this.ds.cloneWithRows(this.state.listViewData)}
renderRow={data =>
<ListItem>
<Text> {data.val().name}</Text>
</ListItem>
}
renderLeftHiddenRow={data =>
<Button full onPress={() => this.addRow(data)} >
<Icon name="information-circle" />
</Button>
}
renderRightHiddenRow={(data, secId, rowId, rowMap) =>
<Button full danger onPress={() => this.deleteRow(secId, rowId, rowMap, data)}>
<Icon name="trash" />
</Button>
}
leftOpenValue={-75}
rightOpenValue={-75}
/>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
解决方案
推荐阅读
- discord.py - 如何从审计日志中获取特定信息 discord py
- amazon-web-services - 需要帮助从 AWS Cognito 提供的 URL 访问访问代码
- c# - 在 Blazor 中,我如何: 1:预览我在内存中上传的视频,以及 2:通过 API 上传?
- c++ - VS2017 开发人员命令提示符仅构建到 x86 - 需要 x64
- python - 为什么有时节点包安装会抛出 python not found 错误?
- javascript - 从 Windows 环境调用 javascript 函数生成 myfile.svg?
- list - Pyspark 列不可迭代
- python - 如何找到任何集群上下边界以循环方式检测虹膜和瞳孔?
- mongodb - 获取附近餐厅的配送半径(如 UberEats 和 Zomato)
- docker - 有没有办法从 docker 容器向本地 IIS 上托管的站点发出请求?