feat: 集成expo-background-task和expo-task-manager,重构后台任务管理,添加健康提醒功能,优化任务执行逻辑
This commit is contained in:
14
app.json
14
app.json
@@ -79,6 +79,20 @@
|
|||||||
"drink_water": "./assets/images/icons/IconGlass.png"
|
"drink_water": "./assets/images/icons/IconGlass.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"expo-background-task",
|
||||||
|
{
|
||||||
|
"minimumInterval": 15
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"expo-task-manager",
|
||||||
|
{
|
||||||
|
"taskManagers": [
|
||||||
|
"background-health-reminders"
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"experiments": {
|
"experiments": {
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ PODS:
|
|||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoAsset (11.1.7):
|
- ExpoAsset (11.1.7):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
|
- ExpoBackgroundTask (0.2.8):
|
||||||
|
- ExpoModulesCore
|
||||||
- ExpoBlur (14.1.5):
|
- ExpoBlur (14.1.5):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoCamera (16.1.11):
|
- ExpoCamera (16.1.11):
|
||||||
@@ -102,6 +104,9 @@ PODS:
|
|||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoWebBrowser (14.2.0):
|
- ExpoWebBrowser (14.2.0):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
|
- EXTaskManager (13.1.6):
|
||||||
|
- ExpoModulesCore
|
||||||
|
- UMAppLoader
|
||||||
- fast_float (6.1.4)
|
- fast_float (6.1.4)
|
||||||
- FBLazyVector (0.79.5)
|
- FBLazyVector (0.79.5)
|
||||||
- fmt (11.0.2)
|
- fmt (11.0.2)
|
||||||
@@ -1741,8 +1746,6 @@ PODS:
|
|||||||
- RevenueCat (5.34.0)
|
- RevenueCat (5.34.0)
|
||||||
- RNAppleHealthKit (1.7.0):
|
- RNAppleHealthKit (1.7.0):
|
||||||
- React
|
- React
|
||||||
- RNBackgroundFetch (4.2.8):
|
|
||||||
- React-Core
|
|
||||||
- RNCAsyncStorage (2.2.0):
|
- RNCAsyncStorage (2.2.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNCMaskedView (0.3.2):
|
- RNCMaskedView (0.3.2):
|
||||||
@@ -1984,6 +1987,7 @@ PODS:
|
|||||||
- SDWebImage/Core (~> 5.17)
|
- SDWebImage/Core (~> 5.17)
|
||||||
- Sentry/HybridSDK (8.53.2)
|
- Sentry/HybridSDK (8.53.2)
|
||||||
- SocketRocket (0.7.1)
|
- SocketRocket (0.7.1)
|
||||||
|
- UMAppLoader (5.1.3)
|
||||||
- Yoga (0.0.0)
|
- Yoga (0.0.0)
|
||||||
- ZXingObjC/Core (3.6.9)
|
- ZXingObjC/Core (3.6.9)
|
||||||
- ZXingObjC/OneD (3.6.9):
|
- ZXingObjC/OneD (3.6.9):
|
||||||
@@ -2001,6 +2005,7 @@ DEPENDENCIES:
|
|||||||
- Expo (from `../node_modules/expo`)
|
- Expo (from `../node_modules/expo`)
|
||||||
- ExpoAppleAuthentication (from `../node_modules/expo-apple-authentication/ios`)
|
- ExpoAppleAuthentication (from `../node_modules/expo-apple-authentication/ios`)
|
||||||
- ExpoAsset (from `../node_modules/expo-asset/ios`)
|
- ExpoAsset (from `../node_modules/expo-asset/ios`)
|
||||||
|
- ExpoBackgroundTask (from `../node_modules/expo-background-task/ios`)
|
||||||
- ExpoBlur (from `../node_modules/expo-blur/ios`)
|
- ExpoBlur (from `../node_modules/expo-blur/ios`)
|
||||||
- ExpoCamera (from `../node_modules/expo-camera/ios`)
|
- ExpoCamera (from `../node_modules/expo-camera/ios`)
|
||||||
- ExpoFileSystem (from `../node_modules/expo-file-system/ios`)
|
- ExpoFileSystem (from `../node_modules/expo-file-system/ios`)
|
||||||
@@ -2018,6 +2023,7 @@ DEPENDENCIES:
|
|||||||
- ExpoSymbols (from `../node_modules/expo-symbols/ios`)
|
- ExpoSymbols (from `../node_modules/expo-symbols/ios`)
|
||||||
- ExpoSystemUI (from `../node_modules/expo-system-ui/ios`)
|
- ExpoSystemUI (from `../node_modules/expo-system-ui/ios`)
|
||||||
- ExpoWebBrowser (from `../node_modules/expo-web-browser/ios`)
|
- ExpoWebBrowser (from `../node_modules/expo-web-browser/ios`)
|
||||||
|
- EXTaskManager (from `../node_modules/expo-task-manager/ios`)
|
||||||
- fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`)
|
- fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`)
|
||||||
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
||||||
- fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`)
|
- fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`)
|
||||||
@@ -2091,7 +2097,6 @@ DEPENDENCIES:
|
|||||||
- ReactCodegen (from `build/generated/ios`)
|
- ReactCodegen (from `build/generated/ios`)
|
||||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||||
- RNAppleHealthKit (from `../node_modules/react-native-health`)
|
- RNAppleHealthKit (from `../node_modules/react-native-health`)
|
||||||
- RNBackgroundFetch (from `../node_modules/react-native-background-fetch`)
|
|
||||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||||
- "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)"
|
- "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)"
|
||||||
- "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
|
- "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
|
||||||
@@ -2104,6 +2109,7 @@ DEPENDENCIES:
|
|||||||
- RNScreens (from `../node_modules/react-native-screens`)
|
- RNScreens (from `../node_modules/react-native-screens`)
|
||||||
- "RNSentry (from `../node_modules/@sentry/react-native`)"
|
- "RNSentry (from `../node_modules/@sentry/react-native`)"
|
||||||
- RNSVG (from `../node_modules/react-native-svg`)
|
- RNSVG (from `../node_modules/react-native-svg`)
|
||||||
|
- UMAppLoader (from `../node_modules/unimodules-app-loader/ios`)
|
||||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
@@ -2144,6 +2150,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/expo-apple-authentication/ios"
|
:path: "../node_modules/expo-apple-authentication/ios"
|
||||||
ExpoAsset:
|
ExpoAsset:
|
||||||
:path: "../node_modules/expo-asset/ios"
|
:path: "../node_modules/expo-asset/ios"
|
||||||
|
ExpoBackgroundTask:
|
||||||
|
:path: "../node_modules/expo-background-task/ios"
|
||||||
ExpoBlur:
|
ExpoBlur:
|
||||||
:path: "../node_modules/expo-blur/ios"
|
:path: "../node_modules/expo-blur/ios"
|
||||||
ExpoCamera:
|
ExpoCamera:
|
||||||
@@ -2178,6 +2186,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/expo-system-ui/ios"
|
:path: "../node_modules/expo-system-ui/ios"
|
||||||
ExpoWebBrowser:
|
ExpoWebBrowser:
|
||||||
:path: "../node_modules/expo-web-browser/ios"
|
:path: "../node_modules/expo-web-browser/ios"
|
||||||
|
EXTaskManager:
|
||||||
|
:path: "../node_modules/expo-task-manager/ios"
|
||||||
fast_float:
|
fast_float:
|
||||||
:podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec"
|
:podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec"
|
||||||
FBLazyVector:
|
FBLazyVector:
|
||||||
@@ -2320,8 +2330,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/react-native/ReactCommon"
|
:path: "../node_modules/react-native/ReactCommon"
|
||||||
RNAppleHealthKit:
|
RNAppleHealthKit:
|
||||||
:path: "../node_modules/react-native-health"
|
:path: "../node_modules/react-native-health"
|
||||||
RNBackgroundFetch:
|
|
||||||
:path: "../node_modules/react-native-background-fetch"
|
|
||||||
RNCAsyncStorage:
|
RNCAsyncStorage:
|
||||||
:path: "../node_modules/@react-native-async-storage/async-storage"
|
:path: "../node_modules/@react-native-async-storage/async-storage"
|
||||||
RNCMaskedView:
|
RNCMaskedView:
|
||||||
@@ -2346,6 +2354,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/@sentry/react-native"
|
:path: "../node_modules/@sentry/react-native"
|
||||||
RNSVG:
|
RNSVG:
|
||||||
:path: "../node_modules/react-native-svg"
|
:path: "../node_modules/react-native-svg"
|
||||||
|
UMAppLoader:
|
||||||
|
:path: "../node_modules/unimodules-app-loader/ios"
|
||||||
Yoga:
|
Yoga:
|
||||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||||
|
|
||||||
@@ -2359,6 +2369,7 @@ SPEC CHECKSUMS:
|
|||||||
Expo: c9e30ab79606b3800733594a961528bc4abb0ffe
|
Expo: c9e30ab79606b3800733594a961528bc4abb0ffe
|
||||||
ExpoAppleAuthentication: 4d2e0c88a4463229760f1fbb9a937a810efb6863
|
ExpoAppleAuthentication: 4d2e0c88a4463229760f1fbb9a937a810efb6863
|
||||||
ExpoAsset: ef06e880126c375f580d4923fdd1cdf4ee6ee7d6
|
ExpoAsset: ef06e880126c375f580d4923fdd1cdf4ee6ee7d6
|
||||||
|
ExpoBackgroundTask: 6c1990438e45b5c4bbbc7d75aa6b688d53602fe8
|
||||||
ExpoBlur: 3c8885b9bf9eef4309041ec87adec48b5f1986a9
|
ExpoBlur: 3c8885b9bf9eef4309041ec87adec48b5f1986a9
|
||||||
ExpoCamera: e1879906d41184e84b57d7643119f8509414e318
|
ExpoCamera: e1879906d41184e84b57d7643119f8509414e318
|
||||||
ExpoFileSystem: 7f92f7be2f5c5ed40a7c9efc8fa30821181d9d63
|
ExpoFileSystem: 7f92f7be2f5c5ed40a7c9efc8fa30821181d9d63
|
||||||
@@ -2376,6 +2387,7 @@ SPEC CHECKSUMS:
|
|||||||
ExpoSymbols: c5612a90fb9179cdaebcd19bea9d8c69e5d3b859
|
ExpoSymbols: c5612a90fb9179cdaebcd19bea9d8c69e5d3b859
|
||||||
ExpoSystemUI: 433a971503b99020318518ed30a58204288bab2d
|
ExpoSystemUI: 433a971503b99020318518ed30a58204288bab2d
|
||||||
ExpoWebBrowser: dc39a88485f007e61a3dff05d6a75f22ab4a2e92
|
ExpoWebBrowser: dc39a88485f007e61a3dff05d6a75f22ab4a2e92
|
||||||
|
EXTaskManager: 280143f6d8e596f28739d74bf34910300dcbd4ea
|
||||||
fast_float: 23278fd30b349f976d2014f4aec9e2d7bc1c3806
|
fast_float: 23278fd30b349f976d2014f4aec9e2d7bc1c3806
|
||||||
FBLazyVector: d2a9cd223302b6c9aa4aa34c1a775e9db609eb52
|
FBLazyVector: d2a9cd223302b6c9aa4aa34c1a775e9db609eb52
|
||||||
fmt: b85d977e8fe789fd71c77123f9f4920d88c4d170
|
fmt: b85d977e8fe789fd71c77123f9f4920d88c4d170
|
||||||
@@ -2456,7 +2468,6 @@ SPEC CHECKSUMS:
|
|||||||
ReactCommon: 7eb76fcd5133313d8c6a138a5c7dd89f80f189d5
|
ReactCommon: 7eb76fcd5133313d8c6a138a5c7dd89f80f189d5
|
||||||
RevenueCat: eb2aa042789d9c99ad5172bd96e28b96286d6ada
|
RevenueCat: eb2aa042789d9c99ad5172bd96e28b96286d6ada
|
||||||
RNAppleHealthKit: 86ef7ab70f762b802f5c5289372de360cca701f9
|
RNAppleHealthKit: 86ef7ab70f762b802f5c5289372de360cca701f9
|
||||||
RNBackgroundFetch: e44c9e85d7fb3122c37d8a806278f62c7682d7ea
|
|
||||||
RNCAsyncStorage: b44e8a4e798c3e1f56bffccd0f591f674fb9198f
|
RNCAsyncStorage: b44e8a4e798c3e1f56bffccd0f591f674fb9198f
|
||||||
RNCMaskedView: d4644e239e65383f96d2f32c40c297f09705ac96
|
RNCMaskedView: d4644e239e65383f96d2f32c40c297f09705ac96
|
||||||
RNCPicker: da0f1c9411208c1ca52bc98383db54a06e0a3862
|
RNCPicker: da0f1c9411208c1ca52bc98383db54a06e0a3862
|
||||||
@@ -2475,6 +2486,7 @@ SPEC CHECKSUMS:
|
|||||||
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
||||||
Sentry: 59993bffde4a1ac297ba6d268dc4bbce068d7c1b
|
Sentry: 59993bffde4a1ac297ba6d268dc4bbce068d7c1b
|
||||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||||
|
UMAppLoader: 55159b69750129faa7a51c493cb8ea55a7b64eb9
|
||||||
Yoga: adb397651e1c00672c12e9495babca70777e411e
|
Yoga: adb397651e1c00672c12e9495babca70777e411e
|
||||||
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
|
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
|
||||||
|
|
||||||
|
|||||||
@@ -268,12 +268,12 @@
|
|||||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/EXTaskManager/ExpoTaskManager_privacy.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/PurchasesHybridCommon/PurchasesHybridCommon.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/PurchasesHybridCommon/PurchasesHybridCommon.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/QCloudCOSXML/QCloudCOSXML.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/QCloudCOSXML/QCloudCOSXML.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNBackgroundFetch/TSBackgroundFetchPrivacy.bundle",
|
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage/RNCAsyncStorage_resources.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage/RNCAsyncStorage_resources.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo/RNDeviceInfoPrivacyInfo.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo/RNDeviceInfoPrivacyInfo.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
|
||||||
@@ -293,12 +293,12 @@
|
|||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoTaskManager_privacy.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PurchasesHybridCommon.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PurchasesHybridCommon.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QCloudCOSXML.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QCloudCOSXML.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TSBackgroundFetchPrivacy.bundle",
|
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCAsyncStorage_resources.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCAsyncStorage_resources.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNDeviceInfoPrivacyInfo.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNDeviceInfoPrivacyInfo.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import Expo
|
import Expo
|
||||||
import React
|
import React
|
||||||
import ReactAppDependencyProvider
|
import ReactAppDependencyProvider
|
||||||
import TSBackgroundFetch
|
|
||||||
|
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
public class AppDelegate: ExpoAppDelegate {
|
public class AppDelegate: ExpoAppDelegate {
|
||||||
@@ -22,8 +21,6 @@ public class AppDelegate: ExpoAppDelegate {
|
|||||||
reactNativeFactory = factory
|
reactNativeFactory = factory
|
||||||
bindReactNativeFactory(factory)
|
bindReactNativeFactory(factory)
|
||||||
|
|
||||||
TSBackgroundFetch.sharedInstance().didFinishLaunching();
|
|
||||||
|
|
||||||
#if os(iOS) || os(tvOS)
|
#if os(iOS) || os(tvOS)
|
||||||
window = UIWindow(frame: UIScreen.main.bounds)
|
window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
factory.startReactNative(
|
factory.startReactNative(
|
||||||
|
|||||||
40
package-lock.json
generated
40
package-lock.json
generated
@@ -23,6 +23,7 @@
|
|||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"expo": "53.0.22",
|
"expo": "53.0.22",
|
||||||
"expo-apple-authentication": "~7.2.4",
|
"expo-apple-authentication": "~7.2.4",
|
||||||
|
"expo-background-task": "~0.2.8",
|
||||||
"expo-blur": "~14.1.5",
|
"expo-blur": "~14.1.5",
|
||||||
"expo-camera": "^16.1.11",
|
"expo-camera": "^16.1.11",
|
||||||
"expo-constants": "~17.1.7",
|
"expo-constants": "~17.1.7",
|
||||||
@@ -39,13 +40,13 @@
|
|||||||
"expo-status-bar": "~2.2.3",
|
"expo-status-bar": "~2.2.3",
|
||||||
"expo-symbols": "~0.4.5",
|
"expo-symbols": "~0.4.5",
|
||||||
"expo-system-ui": "~5.0.11",
|
"expo-system-ui": "~5.0.11",
|
||||||
|
"expo-task-manager": "~13.1.6",
|
||||||
"expo-web-browser": "~14.2.0",
|
"expo-web-browser": "~14.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lottie-react-native": "^7.3.4",
|
"lottie-react-native": "^7.3.4",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-native": "0.79.5",
|
"react-native": "0.79.5",
|
||||||
"react-native-background-fetch": "^4.2.8",
|
|
||||||
"react-native-cos-sdk": "^1.2.1",
|
"react-native-cos-sdk": "^1.2.1",
|
||||||
"react-native-device-info": "^14.0.4",
|
"react-native-device-info": "^14.0.4",
|
||||||
"react-native-exit-app": "^2.0.0",
|
"react-native-exit-app": "^2.0.0",
|
||||||
@@ -7125,6 +7126,18 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-background-task": {
|
||||||
|
"version": "0.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-background-task/-/expo-background-task-0.2.8.tgz",
|
||||||
|
"integrity": "sha512-dePyskpmyDZeOtbr9vWFh+Nrse0TvF6YitJqnKcd+3P7pDMiDr1V2aT6zHdNOc5iV9vPaDJoH/zdmlarp1uHMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"expo-task-manager": "~13.1.6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-blur": {
|
"node_modules/expo-blur": {
|
||||||
"version": "14.1.5",
|
"version": "14.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/expo-blur/-/expo-blur-14.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/expo-blur/-/expo-blur-14.1.5.tgz",
|
||||||
@@ -7455,6 +7468,19 @@
|
|||||||
"integrity": "sha512-0v2/ruY7eeKun4BeKu+GcfO+SHBdl0LJn4ZFzTzjHdWES0Cn+ONqKljYaIv8p9MV2Hx/kcdEvbY4lWI34jC/mQ==",
|
"integrity": "sha512-0v2/ruY7eeKun4BeKu+GcfO+SHBdl0LJn4ZFzTzjHdWES0Cn+ONqKljYaIv8p9MV2Hx/kcdEvbY4lWI34jC/mQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-task-manager": {
|
||||||
|
"version": "13.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-task-manager/-/expo-task-manager-13.1.6.tgz",
|
||||||
|
"integrity": "sha512-sYNAftpIeZ+j6ur17Jo0OpSTk9ks/MDvTbrNCimXMyjIt69XXYL/kAPYf76bWuxOuN8bcJ8Ef8YvihkwFG9hDA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"unimodules-app-loader": "~5.1.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-web-browser": {
|
"node_modules/expo-web-browser": {
|
||||||
"version": "14.2.0",
|
"version": "14.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-14.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-14.2.0.tgz",
|
||||||
@@ -11435,12 +11461,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-background-fetch": {
|
|
||||||
"version": "4.2.8",
|
|
||||||
"resolved": "https://mirrors.tencent.com/npm/react-native-background-fetch/-/react-native-background-fetch-4.2.8.tgz",
|
|
||||||
"integrity": "sha512-vKPumvhBuxr3oI1L7cNunYIsKV8jD4Xz2A9JT/FW5yvn7GAAct184FAZ9dFef75auBxixinaCjRBlip53xGWmQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/react-native-cos-sdk": {
|
"node_modules/react-native-cos-sdk": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://mirrors.tencent.com/npm/react-native-cos-sdk/-/react-native-cos-sdk-1.2.1.tgz",
|
"resolved": "https://mirrors.tencent.com/npm/react-native-cos-sdk/-/react-native-cos-sdk-1.2.1.tgz",
|
||||||
@@ -13884,6 +13904,12 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/unimodules-app-loader": {
|
||||||
|
"version": "5.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/unimodules-app-loader/-/unimodules-app-loader-5.1.3.tgz",
|
||||||
|
"integrity": "sha512-nPUkwfkpJWvdOQrVvyQSUol93/UdmsCVd9Hkx9RgAevmKSVYdZI+S87W73NGKl6QbwK9L1BDSY5OrQuo8Oq15g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/unique-string": {
|
"node_modules/unique-string": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
|
||||||
|
|||||||
@@ -43,13 +43,13 @@
|
|||||||
"expo-status-bar": "~2.2.3",
|
"expo-status-bar": "~2.2.3",
|
||||||
"expo-symbols": "~0.4.5",
|
"expo-symbols": "~0.4.5",
|
||||||
"expo-system-ui": "~5.0.11",
|
"expo-system-ui": "~5.0.11",
|
||||||
|
"expo-task-manager": "~13.1.6",
|
||||||
"expo-web-browser": "~14.2.0",
|
"expo-web-browser": "~14.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lottie-react-native": "^7.3.4",
|
"lottie-react-native": "^7.3.4",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-native": "0.79.5",
|
"react-native": "0.79.5",
|
||||||
"react-native-background-fetch": "^4.2.8",
|
|
||||||
"react-native-cos-sdk": "^1.2.1",
|
"react-native-cos-sdk": "^1.2.1",
|
||||||
"react-native-device-info": "^14.0.4",
|
"react-native-device-info": "^14.0.4",
|
||||||
"react-native-exit-app": "^2.0.0",
|
"react-native-exit-app": "^2.0.0",
|
||||||
@@ -69,7 +69,8 @@
|
|||||||
"react-native-web": "~0.20.0",
|
"react-native-web": "~0.20.0",
|
||||||
"react-native-webview": "13.13.5",
|
"react-native-webview": "13.13.5",
|
||||||
"react-native-wheel-picker-expo": "^0.5.4",
|
"react-native-wheel-picker-expo": "^0.5.4",
|
||||||
"react-redux": "^9.2.0"
|
"react-redux": "^9.2.0",
|
||||||
|
"expo-background-task": "~0.2.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { store } from '@/store';
|
import { store } from '@/store';
|
||||||
import { StandReminderHelpers, WaterNotificationHelpers } from '@/utils/notificationHelpers';
|
import { StandReminderHelpers, WaterNotificationHelpers } from '@/utils/notificationHelpers';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import BackgroundFetch from 'react-native-background-fetch';
|
import * as BackgroundTask from 'expo-background-task';
|
||||||
|
import * as TaskManager from 'expo-task-manager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后台任务标识符
|
* 后台任务标识符
|
||||||
@@ -9,11 +10,148 @@ import BackgroundFetch from 'react-native-background-fetch';
|
|||||||
export const BACKGROUND_TASK_IDS = {
|
export const BACKGROUND_TASK_IDS = {
|
||||||
WATER_REMINDER: 'water-reminder-task',
|
WATER_REMINDER: 'water-reminder-task',
|
||||||
STAND_REMINDER: 'stand-reminder-task',
|
STAND_REMINDER: 'stand-reminder-task',
|
||||||
|
HEALTH_REMINDERS: 'background-health-reminders',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
// 定义后台任务
|
||||||
|
TaskManager.defineTask(BACKGROUND_TASK_IDS.HEALTH_REMINDERS, async () => {
|
||||||
|
try {
|
||||||
|
console.log('[BackgroundTask] 后台任务执行');
|
||||||
|
await executeBackgroundTasks();
|
||||||
|
return BackgroundTask.BackgroundTaskResult.Success;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[BackgroundTask] 任务执行失败:', error);
|
||||||
|
return BackgroundTask.BackgroundTaskResult.Failed;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 检查通知权限
|
||||||
|
async function checkNotificationPermissions(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const Notifications = await import('expo-notifications');
|
||||||
|
const { status } = await Notifications.getPermissionsAsync();
|
||||||
|
return status === 'granted';
|
||||||
|
} catch (error) {
|
||||||
|
console.error('检查通知权限失败:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行喝水提醒后台任务
|
||||||
|
async function executeWaterReminderTask(): Promise<void> {
|
||||||
|
try {
|
||||||
|
console.log('执行喝水提醒后台任务...');
|
||||||
|
|
||||||
|
// 获取当前状态
|
||||||
|
const state = store.getState();
|
||||||
|
const waterStats = state.water.todayStats;
|
||||||
|
const userProfile = state.user.profile;
|
||||||
|
|
||||||
|
// 检查是否有喝水目标设置
|
||||||
|
if (!waterStats || !waterStats.dailyGoal || waterStats.dailyGoal <= 0) {
|
||||||
|
console.log('没有设置喝水目标,跳过喝水提醒');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查时间限制(避免深夜打扰)
|
||||||
|
const currentHour = new Date().getHours();
|
||||||
|
if (currentHour < 9 || currentHour >= 21) {
|
||||||
|
console.log(`当前时间${currentHour}点,不在提醒时间范围内,跳过喝水提醒`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户名
|
||||||
|
const userName = userProfile?.name || '朋友';
|
||||||
|
|
||||||
|
// 构造今日统计数据
|
||||||
|
const todayWaterStats = {
|
||||||
|
totalAmount: waterStats.totalAmount || 0,
|
||||||
|
dailyGoal: waterStats.dailyGoal,
|
||||||
|
completionRate: waterStats.completionRate || 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// 调用喝水通知检查函数
|
||||||
|
const notificationSent = await WaterNotificationHelpers.checkWaterGoalAndNotify(
|
||||||
|
userName,
|
||||||
|
todayWaterStats,
|
||||||
|
currentHour
|
||||||
|
);
|
||||||
|
|
||||||
|
if (notificationSent) {
|
||||||
|
console.log('后台喝水提醒通知已发送');
|
||||||
|
// 记录后台任务执行时间
|
||||||
|
await AsyncStorage.setItem('@last_background_water_check', Date.now().toString());
|
||||||
|
} else {
|
||||||
|
console.log('无需发送后台喝水提醒通知');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('执行喝水提醒后台任务失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行站立提醒后台任务
|
||||||
|
async function executeStandReminderTask(): Promise<void> {
|
||||||
|
try {
|
||||||
|
console.log('执行站立提醒后台任务...');
|
||||||
|
|
||||||
|
// 获取当前状态
|
||||||
|
const state = store.getState();
|
||||||
|
const userProfile = state.user.profile;
|
||||||
|
|
||||||
|
// 检查时间限制(工作时间内提醒,避免深夜或清晨打扰)
|
||||||
|
const currentHour = new Date().getHours();
|
||||||
|
if (currentHour < 9 || currentHour >= 21) {
|
||||||
|
console.log(`当前时间${currentHour}点,不在站立提醒时间范围内,跳过站立提醒`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户名
|
||||||
|
const userName = userProfile?.name || '朋友';
|
||||||
|
|
||||||
|
// 调用站立提醒检查函数
|
||||||
|
const notificationSent = await StandReminderHelpers.checkStandStatusAndNotify(userName);
|
||||||
|
|
||||||
|
if (notificationSent) {
|
||||||
|
console.log('后台站立提醒通知已发送');
|
||||||
|
// 记录后台任务执行时间
|
||||||
|
await AsyncStorage.setItem('@last_background_stand_check', Date.now().toString());
|
||||||
|
} else {
|
||||||
|
console.log('无需发送后台站立提醒通知');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('执行站立提醒后台任务失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后台任务执行函数
|
||||||
|
async function executeBackgroundTasks(): Promise<void> {
|
||||||
|
console.log('开始执行后台任务...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 检查应用权限和用户设置
|
||||||
|
const hasPermission = await checkNotificationPermissions();
|
||||||
|
if (!hasPermission) {
|
||||||
|
console.log('没有通知权限,跳过后台任务');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行喝水提醒检查任务
|
||||||
|
await executeWaterReminderTask();
|
||||||
|
|
||||||
|
// 执行站立提醒检查任务
|
||||||
|
await executeStandReminderTask();
|
||||||
|
|
||||||
|
console.log('后台任务执行完成');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('执行后台任务失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后台任务管理器
|
* 后台任务管理器
|
||||||
* 负责配置和管理 iOS 应用的后台任务执行
|
* 负责配置和管理应用的后台任务执行
|
||||||
*/
|
*/
|
||||||
export class BackgroundTaskManager {
|
export class BackgroundTaskManager {
|
||||||
private static instance: BackgroundTaskManager;
|
private static instance: BackgroundTaskManager;
|
||||||
@@ -36,194 +174,32 @@ export class BackgroundTaskManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 配置后台获取
|
// 注册后台任务
|
||||||
const status = await BackgroundFetch.configure({
|
const status = await BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDS.HEALTH_REMINDERS, {
|
||||||
minimumFetchInterval: 15, // 最小间隔15分钟(单位:秒)
|
minimumInterval: 15, // 15分钟
|
||||||
}, async (taskId) => {
|
|
||||||
console.log('[BackgroundFetch] 后台任务执行:', taskId);
|
|
||||||
await this.executeBackgroundTasks();
|
|
||||||
// 完成任务
|
|
||||||
BackgroundFetch.finish(taskId);
|
|
||||||
}, (error) => {
|
|
||||||
console.error('[BackgroundFetch] 配置失败:', error);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('[BackgroundFetch] 配置状态:', status);
|
console.log('[BackgroundTask] 配置状态:', status);
|
||||||
|
|
||||||
this.isInitialized = true;
|
this.isInitialized = true;
|
||||||
console.log('后台任务管理器初始化完成');
|
console.log('后台任务管理器初始化完成');
|
||||||
|
|
||||||
// 初始化完成后自动启动后台任务
|
|
||||||
await this.start();
|
|
||||||
console.log('后台任务已自动启动');
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化后台任务管理器失败:', error);
|
console.error('初始化后台任务管理器失败:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行后台任务
|
|
||||||
*/
|
|
||||||
private async executeBackgroundTasks(): Promise<void> {
|
|
||||||
console.log('开始执行后台任务...');
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 检查应用权限和用户设置
|
|
||||||
const hasPermission = await this.checkNotificationPermissions();
|
|
||||||
if (!hasPermission) {
|
|
||||||
console.log('没有通知权限,跳过后台任务');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取用户名
|
|
||||||
const state = store.getState();
|
|
||||||
const userName = state.user.profile?.name || '朋友';
|
|
||||||
|
|
||||||
// 发送测试通知
|
|
||||||
const Notifications = await import('expo-notifications');
|
|
||||||
|
|
||||||
await Notifications.scheduleNotificationAsync({
|
|
||||||
content: {
|
|
||||||
title: '测试通知',
|
|
||||||
body: `你好 ${userName}!这是一条测试消息,用于验证通知功能是否正常工作。`,
|
|
||||||
data: { type: 'test_notification', timestamp: Date.now() },
|
|
||||||
sound: true,
|
|
||||||
priority: Notifications.AndroidNotificationPriority.HIGH,
|
|
||||||
},
|
|
||||||
trigger: null, // 立即发送
|
|
||||||
});
|
|
||||||
|
|
||||||
// 执行喝水提醒检查任务
|
|
||||||
await this.executeWaterReminderTask();
|
|
||||||
|
|
||||||
// 执行站立提醒检查任务
|
|
||||||
await this.executeStandReminderTask();
|
|
||||||
|
|
||||||
console.log('后台任务执行完成');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('执行后台任务失败:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行喝水提醒后台任务
|
|
||||||
*/
|
|
||||||
private async executeWaterReminderTask(): Promise<void> {
|
|
||||||
try {
|
|
||||||
console.log('执行喝水提醒后台任务...');
|
|
||||||
|
|
||||||
// 获取当前状态
|
|
||||||
const state = store.getState();
|
|
||||||
const waterStats = state.water.todayStats;
|
|
||||||
const userProfile = state.user.profile;
|
|
||||||
|
|
||||||
// 检查是否有喝水目标设置
|
|
||||||
if (!waterStats || !waterStats.dailyGoal || waterStats.dailyGoal <= 0) {
|
|
||||||
console.log('没有设置喝水目标,跳过喝水提醒');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查时间限制(避免深夜打扰)
|
|
||||||
const currentHour = new Date().getHours();
|
|
||||||
if (currentHour < 9 || currentHour >= 21) {
|
|
||||||
console.log(`当前时间${currentHour}点,不在提醒时间范围内,跳过喝水提醒`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取用户名
|
|
||||||
const userName = userProfile?.name || '朋友';
|
|
||||||
|
|
||||||
// 构造今日统计数据
|
|
||||||
const todayWaterStats = {
|
|
||||||
totalAmount: waterStats.totalAmount || 0,
|
|
||||||
dailyGoal: waterStats.dailyGoal,
|
|
||||||
completionRate: waterStats.completionRate || 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// 调用喝水通知检查函数
|
|
||||||
const notificationSent = await WaterNotificationHelpers.checkWaterGoalAndNotify(
|
|
||||||
userName,
|
|
||||||
todayWaterStats,
|
|
||||||
currentHour
|
|
||||||
);
|
|
||||||
|
|
||||||
if (notificationSent) {
|
|
||||||
console.log('后台喝水提醒通知已发送');
|
|
||||||
// 记录后台任务执行时间
|
|
||||||
await AsyncStorage.setItem('@last_background_water_check', Date.now().toString());
|
|
||||||
} else {
|
|
||||||
console.log('无需发送后台喝水提醒通知');
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('执行喝水提醒后台任务失败:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行站立提醒后台任务
|
|
||||||
*/
|
|
||||||
private async executeStandReminderTask(): Promise<void> {
|
|
||||||
try {
|
|
||||||
console.log('执行站立提醒后台任务...');
|
|
||||||
|
|
||||||
// 获取当前状态
|
|
||||||
const state = store.getState();
|
|
||||||
const userProfile = state.user.profile;
|
|
||||||
|
|
||||||
// 检查时间限制(工作时间内提醒,避免深夜或清晨打扰)
|
|
||||||
const currentHour = new Date().getHours();
|
|
||||||
if (currentHour < 9 || currentHour >= 21) {
|
|
||||||
console.log(`当前时间${currentHour}点,不在站立提醒时间范围内,跳过站立提醒`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取用户名
|
|
||||||
const userName = userProfile?.name || '朋友';
|
|
||||||
|
|
||||||
// 调用站立提醒检查函数
|
|
||||||
const notificationSent = await StandReminderHelpers.checkStandStatusAndNotify(userName);
|
|
||||||
|
|
||||||
if (notificationSent) {
|
|
||||||
console.log('后台站立提醒通知已发送');
|
|
||||||
// 记录后台任务执行时间
|
|
||||||
await AsyncStorage.setItem('@last_background_stand_check', Date.now().toString());
|
|
||||||
} else {
|
|
||||||
console.log('无需发送后台站立提醒通知');
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('执行站立提醒后台任务失败:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查通知权限
|
|
||||||
*/
|
|
||||||
private async checkNotificationPermissions(): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
const Notifications = await import('expo-notifications');
|
|
||||||
const { status } = await Notifications.getPermissionsAsync();
|
|
||||||
return status === 'granted';
|
|
||||||
} catch (error) {
|
|
||||||
console.error('检查通知权限失败:', error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动后台任务
|
* 启动后台任务
|
||||||
*/
|
*/
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
BackgroundFetch.scheduleTask({
|
await BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDS.HEALTH_REMINDERS, {
|
||||||
taskId: 'com.anonymous.digitalpilates.backgroundfetch',
|
minimumInterval: 15,
|
||||||
delay: 15 * 60 * 1000
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await BackgroundFetch.start();
|
|
||||||
console.log('后台任务已启动');
|
console.log('后台任务已启动');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('启动后台任务失败:', error);
|
console.error('启动后台任务失败:', error);
|
||||||
@@ -235,7 +211,7 @@ export class BackgroundTaskManager {
|
|||||||
*/
|
*/
|
||||||
async stop(): Promise<void> {
|
async stop(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await BackgroundFetch.stop();
|
await BackgroundTask.unregisterTaskAsync(BACKGROUND_TASK_IDS.HEALTH_REMINDERS);
|
||||||
console.log('后台任务已停止');
|
console.log('后台任务已停止');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('停止后台任务失败:', error);
|
console.error('停止后台任务失败:', error);
|
||||||
@@ -245,12 +221,13 @@ export class BackgroundTaskManager {
|
|||||||
/**
|
/**
|
||||||
* 获取后台任务状态
|
* 获取后台任务状态
|
||||||
*/
|
*/
|
||||||
async getStatus(): Promise<number> {
|
async getStatus(): Promise<BackgroundTask.BackgroundTaskStatus> {
|
||||||
try {
|
try {
|
||||||
return await BackgroundFetch.status();
|
const status = await BackgroundTask.getStatusAsync();
|
||||||
|
return status || BackgroundTask.BackgroundTaskStatus.Restricted;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取后台任务状态失败:', error);
|
console.error('获取后台任务状态失败:', error);
|
||||||
return BackgroundFetch.STATUS_DENIED;
|
return BackgroundTask.BackgroundTaskStatus.Restricted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,11 +238,9 @@ export class BackgroundTaskManager {
|
|||||||
const status = await this.getStatus();
|
const status = await this.getStatus();
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case BackgroundFetch.STATUS_AVAILABLE:
|
case BackgroundTask.BackgroundTaskStatus.Available:
|
||||||
return '可用';
|
return '可用';
|
||||||
case BackgroundFetch.STATUS_DENIED:
|
case BackgroundTask.BackgroundTaskStatus.Restricted:
|
||||||
return '被拒绝';
|
|
||||||
case BackgroundFetch.STATUS_RESTRICTED:
|
|
||||||
return '受限制';
|
return '受限制';
|
||||||
default:
|
default:
|
||||||
return '未知';
|
return '未知';
|
||||||
@@ -280,7 +255,7 @@ export class BackgroundTaskManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 手动触发后台任务执行
|
// 手动触发后台任务执行
|
||||||
await this.executeBackgroundTasks();
|
await executeBackgroundTasks();
|
||||||
console.log('后台任务测试完成');
|
console.log('后台任务测试完成');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('后台任务测试失败:', error);
|
console.error('后台任务测试失败:', error);
|
||||||
@@ -396,7 +371,7 @@ export class BackgroundTaskManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 手动触发站立提醒任务执行
|
// 手动触发站立提醒任务执行
|
||||||
await this.executeStandReminderTask();
|
await executeStandReminderTask();
|
||||||
console.log('站立提醒后台任务测试完成');
|
console.log('站立提醒后台任务测试完成');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('站立提醒后台任务测试失败:', error);
|
console.error('站立提醒后台任务测试失败:', error);
|
||||||
|
|||||||
Reference in New Issue
Block a user