需求说明:

一个web页面,需要嵌入到App进行文件上传,可是App在一段时刻就会息屏,息屏类似于进入后台,会中止App的一些活动。上传大型文件时需要很长时刻,常常息屏,所以看下App能不能实现在不改动web代码的前提下让web在后台上传文件。

问题处理的思路。

  1. 首要是让App进入后台不被挂起(杀死),可以在后台进行网络恳求。
  2. 阻拦需要上传的文件,再阻拦web的文件上传的链接(网络恳求阻拦),App在本地进行文件上传,上传成功之后告知网页上传成功了。
  3. 补充办法,让屏幕坚持常亮[[UIApplication sharedApplication] setIdleTimerDisabled: YES]不过要记得在dealloc中设置为 NO.

在iOS16下,即使App一向在后台存活,WKWebView会中止网络恳求,所以有必要进行阻拦,然后App进行文件上传操作,然后及时回来给网页,这样就可以确保WKWebView的网络恳求存活.

在iOS17beta3中,不进行阻拦的情况下,只要确保App在后台存活,WKWebView可以进行网络恳求。后续再iOS17正式版发布之后在进行测试是否真的支持。

阻拦后文件上传有两种计划,

计划一
由于阻拦到的文件formData丢掉,可是可以阻拦到上传的 range,也便是文件范围,App对文件进行分段,然后自己组装formData数据进行实时上传。

截取部分文件代码

NSFileHandle * readFileHandle;
//offset偏移量  size长度
[readFileHandle seekToFileOffset:offset];
NSData * fileFragmentData = [fileModel.readFileHandle readDataOfLength:size];

计划二:
App经过AFNetworking进行文件上传,并通知记载上传进展,在阻拦到网页的接口时获取网页当前进展,假如App进展超越网页进展,那么直接回来网页,告知他当前已经上传成功,形成一个“伪同步”。

例如一个文件10M,经过表单分成10段上传, App假如网速很快,1秒上传了8M, 那么在阻拦的网页中,前八次恳求都回来成功。 第九次上传,进入地道,App信号不好了。上传了20秒,那么阻拦到web第九次恳求就一向等候,直到App恳求成功,在进行web接口的呼应。

需要处理的技术点

问题一:如何让App在一向在后台存活。
处理:经过让App在后台播映无声响乐的办法可以做到让App理论上的无限存活。 问题二:怎样阻拦要上传的文件。 处理:运用Runtime办法交流,Hook到上传的文件。 问题三:怎样阻拦文件上传链接(网络恳求)。 处理:运用WKURLSchemeHandler

下面详细介绍这些问题的处理过程。

一、如何让App在一向在后台存活。

iOS7今后提供的后台接口形式

1、Background Audio,这是后台的音频,类似于各种音乐播映器。

2、Location Services,这是后台的定位,类似于各种地图导航应用。

3、VoIP,后台语音服务,类似于各种聊天软件

4、Newsstand,报刊杂志后台自动下载更新,其可以自动实时更新。

我选择的是第一种,可以做到无感知。简而言之便是在后台循环播映一段无声地音乐。

代码:

/// 创建音乐播映器
- (**void**)creatAVAudioSessionObject{
 //设置后台形式和锁屏形式下依然可以播映
 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:**nil**];
 [[AVAudioSession sharedInstance] setActive: **YES** error: **nil**];
 //初始化音频播映器
 NSError *playerError;
 NSURL *urlSound = [[NSURL alloc]initWithString:[[NSBundle mainBundle]pathForResource:@"laojie" ofType:@"mp3"]];
 _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:urlSound error:&playerError];
 _audioPlayer.numberOfLoops = -1;//无限播映
 _audioPlayer.volume = 0;
}
/// 开始播映声响
- (**void**)startPlayAudioSession{
 **BOOL** isPlay = [_audioPlayer play];
  NSLog(@"isPlay===%id", isPlay);
}
/// 中止播映声响
- (**void**)stopPlayAudioSession{
 [_audioPlayer stop];
}

运用办法。

首要,打开后台播映音乐开关。

iOS WKWebView中网络请求拦截(拦截Web中的文件上传接口和文件,然后进行本地后台上传)

1.在didFinishLaunchingWithOptions中 调用 creatAVAudioSessionObject

2.在 applicationDidEnterBackground中 调用 startPlayAudioSession

3.在 applicationWillEnterForeground中 调用 stopPlayAudioSession

进入后台时,可以写一个倒计时,经过下面代码后台剩余活泼时刻。
[UIApplication sharedApplication].backgroundTimeRemaining

怎样阻拦(Hook)要上传的文件

增加分类办法,在内部经过Runtime更换掉体系的获取文件的办法。然后阻拦从文件体系/相机相册获取的文件。

详细代码看文件:
阻拦UIImagePickerController
阻拦UIDocumentPickerViewController
阻拦PHPickerViewController(iOS14之后从文件办理里面获取文件运用这个)。

运用办法:

1、在viewDidLoadhookDelegate 例如 [UIImagePickerController hookDelegate] 2、在deallocunHookDelegate

由于文件过大,所以文件办理运用了 NSFileHandle

怎样阻拦文件上传链接(网络恳求)

iOS11之后体系提供了:WKURLSchemeHandler来阻拦WKWenView中的网络恳求。

首要创建一个对象遵守WKURLSchemeHandler署理,用于进行恳求的阻拦处理。
.h代码检查
.m代码检查

运用办法

WKWebViewConfiguration * con = [[WKWebViewConfiguration alloc] init];
con.allowsInlineMediaPlayback = YES;
con.allowsPictureInPictureMediaPlayback = YES;
GSKHFURLSchemeHandler *Scheme = [GSKHFURLSchemeHandler new];
[con setURLSchemeHandler:Scheme forURLScheme:@"https"];
_webview = [[WKWebView alloc] initWithFrame:CGRectZero configuration:con];

这儿阻拦 https 会 crash,由于体系不支持,所以还需要做一下处理。

给WkWebView增加一个分类,在分类里面经过Runtime,把handlesURLScheme替换成自己的办法,对阻拦的https进行独自的处理。

代码如下:

#import "WKWebView+SchemeHandle.h"
#import <objc/runtime.h>
@implementation WKWebView (SchemeHandle)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method originalMethod1 = class_getClassMethod(self, @selector(handlesURLScheme:));
        Method swizzledMethod1 = class_getClassMethod(self, @selector(yyhandlesURLScheme:));
        method_exchangeImplementations(originalMethod1, swizzledMethod1);
    });
}
+ (BOOL)yyhandlesURLScheme:(NSString *)urlScheme {
    if ([urlScheme isEqualToString:@"http"] || [urlScheme isEqualToString:@"https"] || [urlScheme isEqualToString:@"file"]) {
        return NO;  //这儿让回来NO,应该是默许不走体系断语或许其他判断啥的
    } else {
        return [self handlesURLScheme:urlScheme];
    }
}
@end

到这儿就根本结束了。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。