后台下载移动平台调试及iOS开发介绍
关于后台下载Unity插件的整体设计架构以及主要功能分析详情请见另一篇开发文档[1],这里对安卓与iOS后台下载功能修复调试过程中遇到的问题进行总结并对iOS平台的后台下载实现进行基本说明。
1.安卓平台调试
此节将分析批量测试中的一个异常并提供解决方法,同时周知正在设计安卓后台下载功能架构的开发者如何选择合适的任务类型。
在进行大规模的安卓多机型测试后,关于后台下载功能反馈回来的崩溃及异常中,
Exception Name: android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException
Error Message: Context.startForegroundService() did not then call Service.startForeground()
在Android13以上的机型中占比较高,在展开说明原因之前,先看以下出自安卓开发文档[2]的逻辑流程图确定如何选择用户启动任务的类型,

当前开发的下载组件中创建并使用了两个服务,一个是DownloadService,用于管理下载状态栏和多个下载任务,另一个是LiveService,简单的用于展示下载完成或下载失败的状态提示栏,启用这两个服务时会调用Service.startForeground来声明并指定该服务为前台服务,但在此之前需要先调用Context.startForegroundService来启动服务本身,以上提到的崩溃问题就出自这里。
通常此类异常原因是两接口调用的时间间隔过大导致,结合相关文档和宕机日志,并通过多次不同机型的测试,本次测试案例不仅与Service.startForeground是否成功调用有关,还与Context.stopService或者Service.stopSelf的调用位置是否合理有关。通常情况下,Context.startForegroundService后没有调用Service.startForeground就直接调用Context.StopService终止服务便会复现此问题,或者在没有调用Service.startForeground之后的数秒(不同机型可能时间不同)就会抛出相同的异常。
此类问题的解决办法有很多,首先关于停止服务调用位置的两种处理方式如下:
- 在Service.onCreate中调用Service.startForeground,在Service.onStartCommand函数中使用Service.stopSelf来取代外部Context.stopService接口,何时调用可以通过intent的扩展数据来传入,如:Intent.putExtra("STOP_SERVICE", true);等,因为onStartCommand一定在onCreate之后调用,保证了不会出现终止前还没有指定前台服务的情况。
- 因为DownloadService需要绑定到组件进行请求的发送和接收,因此可以通过Service.onBind监听到是否绑定完成来判断是否已经onCreate结束,然后自行记录一个命令队列,如果绑定成功,自定义指令如终止服务等,便可插入到命令队列中,如果还未绑定或者意外解除绑定,那么命令将会被排除在队列之外,是否缓存指令将根据需求来定。
关于没有成功调用Service.startForeground的可能性在此项目案例中是存在的,在某些平台包上是能够复现的,问题出在了Notification是否成功创建的判断上(因为startForeground需要传入Notification并且不能为空),而在一些平台上,由于API使用的问题,比如PendingIntent的FLAG_UPDATE_CURRENT标识在目标SDK版本31以上就会导致异常,进而影响后续通知栏的创建,从而导致未能成功调用Service.startForeground,以下是一些解决方法:
- 因为前序测试大部分机型对使用FLAG_UPDATE_CURRENT的使用不会抛出异常,所以为了不影响这些机型,需要对SDK版本进行适配判断,在某些环境下使用FLAG_IMMUTABLE或者FLAG_MUTABLE来代替FLAG_UPDATE_CURRENT,某些环境下保留,并对此段代码进行TryCatch捕获(使用Throwable代替Exception),保证不影响后续的通知栏创建。
- 或者可以对Notification创建函数外层进行TryCatch捕获,如果创建失败抛出异常,那么就使用一套默认的最简化的Notification(目前使用的通知栏功能较多,调用API不能保证在所有环境下适配),这样可以保证前台能够成功启用,不会导致宕机问题。
或者不使用以上方案,采用以下方法来规避杜绝此类问题:
- 使用Context.startService代替Context.startForegroundService在前台启动前台服务,但有一些限制[3],如:
目标SDK版本O(26)以上,不允许后台启动后台服务
目标SDK版本S(31)以上,不允许后台启动前台服务
这样会规避掉Context.startForegroundService引起的问题,但是修改后不会再有批量测试验证,因此暂未使用此方法。
结合以上流程图,关于后台下载任务的实现,使用前台服务处理的方式其实并不是最佳的,因为前台服务将会占用更多系统资源,并且系统限制也相当多,适合且能性能最大化的做法是采用backgroundWork或者JobService的方式,因为处于项目后期,不能再有较大变动,所以实践并测试高效后台下载方法将会留在之后的迭代中。
2. iOS平台实现相关
此节将提供iOS平台上实现后台下载相关的基础内容,主要从功能点出发介绍一下底层API的选择和创建流程
2.1 文件后台下载
- 配置Background Session
- 首先通过

2288

被折叠的 条评论
为什么被折叠?



