反应本机警报通知:警报设置成功,但通知仅针对多个警报发出一次

时间:2021-07-27 05:29:38

标签: javascript reactjs react-native

基本上,我正在开发一个应用程序,它提醒患者滴眼药水的时间表。用户可以为给定的一天或多天设置多个闹钟。警报应该被称为 noOfDays*howOftenPerDay 次。在我的代码中

  • 当用户设置一个闹钟时,我们可以从 ReactNativeAN.getScheduledAlarms() 中获取它,闹钟响了,它工作正常
  • 当用户设置两个闹钟时,我们可以从 ReactNativeAN.getScheduledAlarms() 中获取,第二个闹钟只会响,第一个不会响
  • 当用户设置三个闹钟时,我们可以从 ReactNativeAN.getScheduledAlarms() 中获取,第 3 个闹钟只响,前两个不响
  • 我尝试使用
<块引用>

通道:Math.floor(Math.random() * (i + 1)),

我认为可能是频道问题,但没有用

有人可以帮我解决这个问题吗?任何帮助将不胜感激,这里是完整的代码:

import React, { Component } from 'react'
import { Picker, Text, View, Image, Button, Alert } from 'react-native'
import CheckBox from '@react-native-community/checkbox'
import DatePicker from 'react-native-datepicker'
import { v4 as uuidv4 } from 'uuid';
import DateTimePickerModal from "react-native-modal-datetime-picker";
import ReactNativeAN from 'react-native-alarm-notification';
import moment from 'moment'

import styles from './style'

export default class AddDropForm extends Component {
    constructor(props) {
        super(props)
        this.state = {
            date: new Date(),
            mode: 'date',
            show: false,
            alarmComponent: [],
            isDatePickerVisible: false,
            time: new Date(),
            dayPickerShow: false,
            oftenPickerShow: false,
            taperPickerShow: false,
            noOfDays: 1,
            howOften: 1,
            taper: 1,
            isLeftSelected: false,
            isRightSelected: false,
            isBothSelected: false,
            timeArray: []
        }
    }


    updateNoOfDays = (count) => {
        this.setState({ noOfDays: count })
    }
    updateHowOften = (count) => {
        this.setState({ howOften: count })
    }
    updateTaper = (count) => {
        this.setState({ taper: count })
    }

    showDatePicker = () => {
        this.setState({ isDatePickerVisible: true })
    };

    hideDatePicker = () => {
        this.setState({ isDatePickerVisible: false })
    };

    handleConfirm = (date) => {
        console.log("A date has been picked: ", date);
        this.setState({ timeArray: [...this.state.timeArray, date] })
        this.setState({ time: date })
        this.hideDatePicker();
    };

    async setAlarm(name) {
        let setTime = ''
        for (let i = 0; i < this.state.noOfDays; i++) {
            this.state.timeArray.forEach(async t => {
                let alarmData = {
                    title: `${name}`,
                    message: `Reminder for ${name}`,
                    channel: Math.floor(Math.random() * (i + 1)),
                    small_icon: "ic_launcher",
                    auto_cancel: true,
                    schedule_type: "repeat",
                    sound_name: 'alarm_quartz.mp3',
                    has_button: true
                };
                console.log("The set time is: " + setTime)
                setTime = moment(t).set({ second: 0, millisecond: 0 }).add(i, 'days').format('DD-MM-yyyy HH:mm:ss')
                await ReactNativeAN.scheduleAlarm({ ...alarmData, fire_date: setTime });
            })
        }
        Alert.alert('Alarms Set')
        this.props.navigation.navigate('Schedule')
    }

    formatDate() {
        let date = this.state.time
        var hours = date.getHours();
        var minutes = date.getMinutes();
        var ampm = hours >= 12 ? 'pm' : 'am';
        hours = hours % 12;
        hours = hours ? hours : 12;
        minutes = minutes < 10 ? '0' + minutes : minutes;
        var strTime = hours + ':' + minutes + ' ' + ampm;
        return strTime;
    }

    render() {
        const { dropName } = this.props.route.params
        let array = []
        for (let i = 1; i <= this.state.howOften; i++) {
            array.push(
                <View style={{ flex: 7 }}>
                    <Button title={"Set Time"} onPress={() => this.showDatePicker()} />
                    <DateTimePickerModal
                        isVisible={this.state.isDatePickerVisible}
                        mode="time"
                        onConfirm={this.handleConfirm}
                        onCancel={this.hideDatePicker}
                    />
                </View>
            )
        }
        // const { dropName } = this.props
        return (
            <View style={styles.container}>
                <View style={styles.topTitleContainer}>
                    <View style={{ flex: 2 }}>
                        <Image style={{ width: 70, height: 60 }} source={require('../../../assets/addDrop.png')} />
                    </View>
                    <View style={{ flex: 7 }}>
                        <Text style={styles.titleText}>
                            {dropName.name}
                        </Text>
                    </View>
                </View>
                <View style={styles.tilesContainer}>
                    <View style={{ flex: 2 }}>
                        <Text style={styles.subTitle}>Which Eye?</Text>
                    </View>
                    <View style={styles.checkBoxContainer}>
                        <Text style={styles.subTitle}>Left</Text>
                        <CheckBox
                            value={this.state.isLeftSelected}
                            onValueChange={(newValue) => this.setState({ isLeftSelected: newValue, isBothSelected: false, isRightSelected: false })
                            }
                            style={styles.checkbox}
                        />
                        <Text style={styles.subTitle}>Both</Text>
                        <CheckBox
                            value={this.state.isBothSelected}
                            onValueChange={(newValue) => this.setState({
                                isBothSelected: newValue, isLeftSelected: false,
                                isRightSelected: false
                            })
                            }
                            style={styles.checkbox}
                        />
                        <Text style={styles.subTitle}>Right</Text>
                        <CheckBox
                            value={this.state.isRightSelected}
                            onValueChange={(newValue) => this.setState({ isRightSelected: newValue, isLeftSelected: false, isBothSelected: false })
                            }
                            style={styles.checkbox}
                        />
                    </View>
                </View>
                <View style={styles.tilesContainer}>
                    <View style={{ flex: 2 }}>
                        <Text style={styles.subTitle}>Start Date?</Text>
                    </View>
                    <View style={{ flex: 7 }}>
                        <DatePicker
                            style={{ width: '100%' }}
                            date={this.state.date}
                            mode="date"
                            placeholder="select date"
                            format="YYYY-MM-DD"
                            minDate={new Date()}
                            confirmBtnText="Confirm"
                            cancelBtnText="Cancel"
                            customStyles={{
                                dateIcon: {
                                    position: 'absolute',
                                    left: 0,
                                    top: 4,
                                    marginLeft: 0
                                },
                                dateInput: {
                                    marginLeft: 36
                                }
                            }}
                            onDateChange={(date) => { this.setState({ date: date }) }}
                        />
                    </View>
                </View>
                <View style={styles.tilesContainer}>
                    <View style={{ flex: 2 }}>
                        <Text style={styles.subTitle}>Number of Days?</Text>
                    </View>
                    <View style={{ flex: 7 }}>
                        <Picker selectedValue={this.state.noOfDays} onValueChange={this.updateNoOfDays}>
                            ...
                        </Picker>
                    </View>
                </View>
                <View style={styles.tilesContainer}>
                    <View style={{ flex: 2 }}>
                        <Text style={styles.subTitle}>How Often?</Text>
                    </View>
                    <View style={{ flex: 7 }}>
                        <Picker selectedValue={this.state.howOften} onValueChange={this.updateHowOften}>
                           ...
                        </Picker>
                    </View>
                </View>
                <View style={styles.tilesContainer}>
                    <View style={{ flex: 2 }}>
                        <Text style={styles.subTitle}>Taper Drops?</Text>
                    </View>
                    <View style={{ flex: 7 }}>
                        <Picker selectedValue={this.state.taper} onValueChange={this.updateTaper}>
                           ...
                           
                        </Picker>
                    </View>
                </View>
                <View style={styles.tilesContainer}>
                    <View style={{ flex: 2 }}>
                        <Text style={styles.subTitle}>Alarm</Text>
                    </View>
                    {array}
                </View>
                <View style={{ justifyContent: 'center', alignItems: 'center' }}>
                    <View style={{ width: 260 }}>
                        <Button title={"Add"} color='#57E874' onPress={() => this.setAlarm(dropName.name)} />
                    </View>

                </View>
            </View>
        )
    }
}

3 个答案:

答案 0 :(得分:1)

我想问题出在您的频道上,您确定每个闹钟都不同吗

答案 1 :(得分:0)

我不认为您使用 async await 的方式是最佳的,这可能是它导致您出现问题的原因,您需要使用 Promise.all 方法来获取一组承诺并返回一个带有预定警报的数组一次ReactNativeAN.scheduleAlarm 的每个单独调用结束。

this example

我也同意另一条评论,我不确定文档中的每个警报的频道是否应该不同指定应该发送通知的频道..所以如果通知是针对同一个用户的,我认为应该是同一个 ID。

答案 2 :(得分:0)

我相信我已经发现了问题。您使用的库将 alarmId 设置为时间戳。

当您运行 for loop 并调用 ReactNativeAN.scheduleAlarm 并且本机函数运行时,NSDate.date.timeIntervalSince1970 为每次迭代返回相同的值,这意味着每个(前一个)警报都将被覆盖。< /p>

这里有一个简单的函数来模拟这个理论。

const items = [1,2,3,4,5];

items.forEach(item => {
  console.log(Date.now()); // Same timestamp logged and therefore alarmId is not unique.
});

令人沮丧的是,该库不支持 alarmId 作为属性,您可以强行添加等待以使时间戳不同。

const items = [1,2,3,4,5];

items.forEach((item, index) => {
  setTimeout(() => {
    console.log(Date.now()); // alarmId will now be unique.
    // Code to call ReactNativeAN.scheduleAlarm
  }, index + 1);
});

为了理智起见,您可以将 ReactNativeAN.scheduleAlarm 的值分配给一个变量并将其注销以确保它是您期望的值。

const alarm = await ReactNativeAN.scheduleAlarm(...);

console.log(alarm);