diff --git a/app.json b/app.json index f1fb0fb..b8aa3fc 100644 --- a/app.json +++ b/app.json @@ -49,7 +49,7 @@ "plugins": [ "expo-router", "expo-secure-store", [ - "expo-background-fetch", + "expo-background-task", { "minimumInterval": 15 } diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index a8f83c8..4b739e8 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -101,7 +101,7 @@ export default function HomeScreen() { isLoggedIn ? : {/* 标题区域 */} - + {t('auth.welcomeAwaken.awaken', { ns: 'login' })} {"\n"} diff --git a/components/file-upload/backgroundUploader.ts b/components/file-upload/backgroundUploader.ts index 46f9a8e..39683c4 100644 --- a/components/file-upload/backgroundUploader.ts +++ b/components/file-upload/backgroundUploader.ts @@ -1,5 +1,35 @@ +/** + * @file backgroundUploader.ts + * @description + * 本模块为基于 Expo 的 React Native 应用提供了一个健壮的后台媒体上传系统。 + * 其核心职责是在用户不感知的情况下,高效地将用户设备上指定时间范围内的照片和视频静默上传到服务器, + * 即使应用处于后台或被终止也能正常工作。 + * + * @features + * - 后台任务处理: 利用 `expo-task-manager` 和 `expo-background-fetch` 注册一个后台任务, + * 该任务可以周期性(例如每15分钟)运行,即使用户退出应用或设备重启也能被激活。 + * - 媒体文件检索: 使用 `expo-media-library` 访问用户相册,能够获取指定日期范围内的所有媒体文件, + * 并包含其 EXIF 元数据(如GPS位置、拍摄时间等)。 + * - 文件处理与压缩: + * - 图片压缩: 通过 `expo-image-manipulator` 调整图片尺寸并进行压缩,以生成用于预览的缩略图。 + * - HEIC 格式转换: 自动将苹果设备上常见的 HEIC/HEIF 格式图片转换为通用的 JPEG 格式再上传。 + * - 视频缩略图: 提取视频的第一帧作为预览图进行上传。 + * - 高效并发上传: 使用 `p-limit` 库限制并发上传的数量(默认为10),以防止网络拥堵并保证上传过程的稳定性。 + * - 手动触发机制: 提供 `triggerManualUpload` 函数,允许应用在需要时(例如用户在设置页面点击“立即同步”)主动触发上传流程。 + * + * @workflow + * 1. 触发: 上传流程可以通过两种方式启动:由后台任务调度器自动唤醒,或由应用内代码手动调用。 + * 2. 查询媒体文件: 根据指定的日期范围,从用户设备相册中查询需要上传的图片和视频列表。 + * 3. 处理单个文件 (循环处理列表中的每个文件): + * a. 权限检查: 确保应用拥有访问媒体库的权限。 + * b. 上传原始文件: 首先上传完整分辨率的原始文件。此过程包括处理 HEIC 转换、从后端获取预签名上传URL、 + * 通过 XMLHttpRequest 上传文件,以及在上传成功后向后端确认。 + * c. 上传派生文件: 接着,生成并上传一个压缩版的图片或视频缩略图,流程与上传原始文件类似。 + * d. 关联素材: 当原始文件和派生文件(压缩图/缩略图)都成功上传后,调用后端API将两者进行关联。 + * 4. 完成: 所有文件处理完毕后,任务结束,等待下一次调度或手动触发。 + */ import { fetchApi } from '@/lib/server-api-util'; -import * as BackgroundFetch from 'expo-background-fetch'; +import * as BackgroundFetch from 'expo-background-task'; import * as FileSystem from 'expo-file-system'; import * as ImageManipulator from 'expo-image-manipulator'; import * as MediaLibrary from 'expo-media-library'; @@ -8,6 +38,7 @@ import pLimit from 'p-limit'; import { Alert } from 'react-native'; import { transformData } from '../utils/objectFlat'; + type ExtendedAsset = MediaLibrary.Asset & { exif?: Record; }; @@ -524,7 +555,7 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { if (media.length === 0) { console.log('No media files to upload'); - return BackgroundFetch.BackgroundFetchResult.NoData; + return BackgroundFetch.BackgroundTaskResult.Success; } // 处理媒体文件上传 @@ -534,11 +565,11 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { console.log(`Background upload completed. Success: ${successCount}/${results.length}`); return successCount > 0 - ? BackgroundFetch.BackgroundFetchResult.NewData - : BackgroundFetch.BackgroundFetchResult.NoData; + ? BackgroundFetch.BackgroundTaskResult.Success + : BackgroundFetch.BackgroundTaskResult.Failed; } catch (error) { console.error('Background task error:', error); - return BackgroundFetch.BackgroundFetchResult.Failed; + return BackgroundFetch.BackgroundTaskResult.Failed; } }); diff --git a/package-lock.json b/package-lock.json index 6070e55..77c2f16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@types/react-redux": "^7.1.34", "expo": "~53.0.12", "expo-audio": "~0.4.7", - "expo-background-fetch": "^13.1.6", + "expo-background-task": "^0.2.8", "expo-blur": "~14.1.5", "expo-clipboard": "~7.1.5", "expo-constants": "~17.1.6", @@ -7801,10 +7801,10 @@ "react-native": "*" } }, - "node_modules/expo-background-fetch": { - "version": "13.1.6", - "resolved": "https://registry.npmjs.org/expo-background-fetch/-/expo-background-fetch-13.1.6.tgz", - "integrity": "sha512-hl4kR32DaxoHFYqNsILLZG2mWssCkUb4wnEAHtDGmpxUP4SCnJILcAn99J6AGDFUw5lF6FXNZZCXNfcrFioO4Q==", + "node_modules/expo-background-task": { + "version": "0.2.8", + "resolved": "http://192.168.31.115:8081/repository/npm/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" diff --git a/package.json b/package.json index 268a95e..479da80 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@types/react-redux": "^7.1.34", "expo": "~53.0.12", "expo-audio": "~0.4.7", - "expo-background-fetch": "^13.1.6", + "expo-background-task": "^0.2.8", "expo-blur": "~14.1.5", "expo-constants": "~17.1.6", "expo-dev-client": "~5.2.1", @@ -92,4 +92,4 @@ } } } -} \ No newline at end of file +}