首页 > 解决方案 > 将 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',

    },
});

标签: react-nativepush-notification

解决方案


推荐阅读