feat(mobile): ios background upload bridge (compile-gated at G3)
Swift 侧(协议与 Android UploadPlugin.kt 逐字一致,编译/真机留 G3): - UploadBridge.swift:通道/方法/事件/失败码常量 + registerTask 参数解析 (镜像 UploadProtocol.kt) - UploadEventBus.swift:单调 seq + 终态 ack 缓存重放(镜像 UploadEventBus.kt),iOS 增强——未 ack 终态落盘(系统后台拉起投递的 回调在进程重启后同样重放,技术方案 §6.2 持久化原生回调) - UploadTaskStore.swift:taskId→URLSession taskIdentifier 映射 plist 持久化 (Application Support;对应 Android WorkManager 自持映射) - UploadPlugin.swift:URLSession background (com.photolive.photo_live.uploads)+ delegate 失败分类(2xx→completed+etag / 403→needsRenew / 4xx→HTTP_4XX / 网络→重试上限后 NETWORK,镜像 UploadPutExecutor/UploadWorker)、原生重试(5 次上限、10s 指数退避)、 进度 500ms 节流、queryTask/cancelTask/ackEvents、静默取消 - AppDelegate.swift:implicit engine 通道注册 + 启动重建会话 + handleEventsForBackgroundURLSession completionHandler 暂存 - Info.plist:UIBackgroundModes 有意不声明(background URLSession 无需; 计划措辞按技术方案 §6.2 修正,见 README-ios.md) - project.pbxproj 登记新 Swift 文件;README-ios.md(Xcode 步骤 + G3 验证 清单:实际文件上传/持久化回调窗口/服务端补偿/重启重联校准/强制退出/ 低电量延迟/100 张批量) Dart:NativeTransport 选择矩阵并入 iOS(Platform.isAndroid || isIOS, FORCE_DART_TRANSPORT 覆盖不变)——协议两侧一致,无新通道代码。 flutter analyze 0 issue;flutter test 219 全绿。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -6,8 +6,8 @@
|
||||
/// (progress/completed/needsRenew/failed×码表)、终态 ack、取消联动、
|
||||
/// 注册失败归一、多任务路由;
|
||||
/// - DartHttpTransport:dio 异常 → 传输异常归一(403→renew、取消、网络);
|
||||
/// - 传输选择:Android 默认原生、FORCE_DART_TRANSPORT 覆盖、VM 缺省
|
||||
/// DartHttp。
|
||||
/// - 传输选择:Android/iOS 默认原生(Task 8 起 iOS 并入同一矩阵)、
|
||||
/// FORCE_DART_TRANSPORT 覆盖、VM 缺省 DartHttp。
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
@@ -405,22 +405,39 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('传输选择(Android 原生 / FORCE_DART_TRANSPORT)', () {
|
||||
test('选择矩阵:Android→native;强制 Dart / 非 Android→dart', () {
|
||||
expect(preferNativeTransport(isAndroid: true), isTrue);
|
||||
expect(preferNativeTransport(isAndroid: false), isFalse);
|
||||
group('传输选择(Android/iOS 原生 / FORCE_DART_TRANSPORT)', () {
|
||||
test('选择矩阵:Android/iOS→native;强制 Dart / 桌面→dart', () {
|
||||
// Android / iOS:原生桥接(Task 7 / Task 8——协议一致,同一通道)。
|
||||
expect(
|
||||
preferNativeTransport(isAndroid: true, forceDartTransport: true),
|
||||
isFalse,
|
||||
reason: 'FORCE_DART_TRANSPORT 覆盖',
|
||||
preferNativeTransport(isAndroid: true, isIOS: false),
|
||||
isTrue,
|
||||
reason: 'Android → WorkManager 原生',
|
||||
);
|
||||
expect(
|
||||
preferNativeTransport(isAndroid: true, forceDartTransport: false),
|
||||
preferNativeTransport(isAndroid: false, isIOS: true),
|
||||
isTrue,
|
||||
reason: 'iOS → URLSession background 原生(编译留 G3)',
|
||||
);
|
||||
// 桌面 / 测试 VM:Dart dio。
|
||||
expect(preferNativeTransport(isAndroid: false, isIOS: false), isFalse);
|
||||
// FORCE_DART_TRANSPORT 覆盖原生选择。
|
||||
expect(
|
||||
preferNativeTransport(isAndroid: true, isIOS: false, forceDartTransport: true),
|
||||
isFalse,
|
||||
reason: 'FORCE_DART_TRANSPORT 覆盖(Android)',
|
||||
);
|
||||
expect(
|
||||
preferNativeTransport(isAndroid: false, isIOS: true, forceDartTransport: true),
|
||||
isFalse,
|
||||
reason: 'FORCE_DART_TRANSPORT 覆盖(iOS)',
|
||||
);
|
||||
expect(
|
||||
preferNativeTransport(isAndroid: true, isIOS: false, forceDartTransport: false),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('缺省解析:VM 测试环境(非 Android)→ DartHttpTransport', () {
|
||||
test('缺省解析:VM 测试环境(非 Android/iOS)→ DartHttpTransport', () {
|
||||
final resolved = defaultUploadTransport();
|
||||
expect(resolved, isA<DartHttpTransport>());
|
||||
resolved.dispose();
|
||||
|
||||
Reference in New Issue
Block a user