Да !!! Это возможно. У вас есть много вариантов, которые включают в себя:
1) Используйте background-fetch для iOS и HeadlessTask в Android, вот достойная библиотека
https://github.com/jamesisaac/react-native-background-task
2) Отправка уведомлений с сервера, чтобы детерминистически убедиться, что приложение запускает приложение (за исключением того, что оно было убито ОС). В iOS убедитесь, что вы вызываете уведомление.finish (), чтобы избежать дискриминации алгоритмом обработчика задач.
Простой пример для no 1 выглядит следующим образом (НЕ ИСПЫТАНО !!):
import React from 'react'
import { Text } from 'react-native'
import BackgroundTask from 'react-native-background-task'
import { Notifications, Permissions, Constants } from 'expo';
BackgroundTask.define(async () => {
// if time is 12pm, fire off a request with axios to fetch the pills info
const response = await fetch('http://pills-server')
const text = await response.text()
// Data persisted to AsyncStorage can later be accessed by the foreground app
await AsyncStorage.setItem('@MyApp:key', text)
// Notification configuration object
const localNotification = {
title: text,
body: 'msg',
data: data,
ios: {
sound: true
}
}
// trigger notification, note that on ios if the app is open(in foreground) the notification will not show so you will need to find some ways to handling it which is discribed here https://docs.expo.io/versions/latest/guides/push-notifications
Notifications
.presentLocalNotificationAsync(localNotification)
.catch((err) => {
console.log(err)
})
BackgroundTask.finish()
})
class MyApp extends React.Component {
async componentDidMount() {
// allows the app to recieve notifications (permission stuff)
this.registerForPushNotificationsAsync().then(() => {
BackgroundTask.schedule()
});
}
registerForPushNotificationsAsync = async () => {
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
if (status !== 'granted') {
return;
}
let deviceToken = await Notifications.getExpoPushTokenAsync()
}
render() {
return <Text>Hello world</Text>
}
}
Что касается второго, идея заключается в том, что сервер должен как задание cron, которое периодически отправляет уведомления всем пользовательским устройствам на основе их различных временных параметров / даты и информации о таблетках, хранящихся в базе данных.
N.B для реализации на стороне сервера для выставки вы можете использовать https://github.com/expo/expo-server-sdk-node для проектов node.js, другие sdks перечислены здесь: https://docs.expo.io/versions/latest/guides/push-notifications/
import React from 'react';
import { Notifications, Permissions, Constants } from 'expo';
import { Text, View } from 'react-native'
class App extends React.Component {
registerForPushNotificationsAsync = async () => {
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
// prevent device from registering more than once
if (status !== 'granted') {
return;
}
// get unique token of the device that the server can use to push notification to
the device
let deviceToken = await Notifications.getExpoPushTokenAsync();
// call a method that sends the device token to the server, in which server stores somewhere and uses in the future
this.props.registerToken({ deviceToken }).then(() => {
// the listener here, is called whenever a push notification comes from the server or when the user clicks on the notification at the device tray
this.notificationSubscription =
Notifications.addListener(this.handleNotification);
})
}
handleNotification = (notification) => {
if (notification.origin === 'selected') {
// The notification was clicked from the tray by the user i.e selected
// do stuff to handle selection
} else {
// The notification originated from the server
const localNotification = {
title: notification.title,
body: notification.message,
data: data,
ios: {
sound: true
}
}
Notifications.presentLocalNotificationAsync(localNotification).catch((err) => {
console.log(err)
})
}
}
async componentDidMount() {
this.registerForPushNotificationsAsync().then(() => {
});
}
render() {
return (
<View>
<Text>Helllo world</Text>
</View>
);
}
}
Обратите внимание, что эти решения не были протестированы и могут содержать некоторые ошибки, но общая идея остается прежней и может быть изменена:).
Надеюсь, это поможет.