Flutter开发之iOS后台定位开发详解
Posted Xiao冰同学
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter开发之iOS后台定位开发详解相关的知识,希望对你有一定的参考价值。
Flutter开发之ios后台定位开发详解
需求目的
开发一个功能持续获取用户的位置发送给后端,PC端会根据后端传来的移动端发送的位置信息,来绘制使用者的运动轨迹。
实现需求 | 是否实现 |
---|---|
后台定位 | ✅ |
持续定位 | ✅ |
后台正常运行 | ✅ |
前言
因为笔者使用的是Flutter 来跨端开发,并不是专门的iOS开发人员,所以对iOS的技术不是非常的了解,因此走了很多弯路,本文会以一个 非专业的iOS 兼容开发者角度来记录笔者遇到的问题及解决方案。
出现的问题
- 定位权限 :按部就班申请定位权限,但是发现在设置中,应用跟别的应用(高德地图,滴滴出行)等少了 “始终” 使用位置
- 定位失效 :息屏或者按Home键 ,就立即或者在一定时间后无法正常定位
查询资料
根据 各方面资料及开发者文档中,得出以下结论:
iOS 7以前:永不、始终 选项的位置权限
iOS 8-10:永不、始终 选项 ,可以通过配置NSLocationWhenInUseUsageDescription 可出现 使用App期间 选项
iOS 11 - 12:
不用配置NSLocationAlwaysUsageDescription,就会出现永不、始终、使用App期间
iOS 13:增加 允许一次 选项
Allow Once 提出了 Temporary authorization 的概念。当用户选择 Allow Once 后,我们的 App 就获得了 Temporary authorization ,也就是临时权限
该权限有以下特点:
- 实际的权限类型是:WhenInUse;
- App 重启后,定位权限会重新变成 NotDetermined,下次开启定位时再申请定位权限会重新弹框让用户确认;
- 在 iOS 13 系统,申请 WhenInUse 或 Always 权限时,系统都会先弹出来下面的弹框让用户选择:
“使用app时允许、允许一次、不允许”
用户选择 Allow While In Use
如果用户选择 Allow While In Use ,我们的 App 会获得 WhenInUse 权限。
如果之前申请的是 WhenInUse 权限,那么就跟 iOS 13 之前版本的系统表现没什么区别;
系统会在某个时间再弹出一个弹框询问用户是继续给我们的 App WhenInUse 权限,还是切换成 Always 权限,iOS 13 中,没法直接向用户要 Always 权限了,必须要经过一个二次确认。
备注:系统确认弹窗弹出时,为打断状态(UIApplicationStateInactive)。
开发实现
解决权限问题
Flutter 提供了对应的权限插件,可以在pubspec.yaml文件中引入
permission_handler
还需要在 info.plist 文件中声明权限
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>需要您提供定位信息,才能使用xxx功能记录您的正确工作轨迹</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>需要您提供后台定位信息,才能使用xx功能记录您的正确工作轨迹</string>
<key>NSLocationUsageDescription</key>
<string>需要您提供定位信息,才能使用xx功能记录您的正确工作轨迹</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要您提供定位信息,才能使用xx功能记录您的正确工作轨迹</string>
iOS审核有一个明确的规定:申请像拍照、相册、位置这些敏感权限时,必须在 info.plist文件中详细说明 什么功能,或者为什么要使用该权限,像
需要你提供相机,才能拍照 这些类似 描述是会影响上架的。
至于 Flutter 权限管理具体建议请参考笔者这篇文章 Flutter Android权限问题
都是使用了Flutter 框架,并且也是提到了 permission_handler 插件的封装使用。
if (await PermissionHelper.check(PermissionType.locationAlways))
// 这里写应用获取权限之后的业务逻辑
这里强调一下,建议用 PermissionType.locationAlways,对应的是 permission_handler插件的 Permission.locationAways,这样双管齐下才能出现 始终获去 位置的 选项。
最后的结果如下图所示
后台保活问题
尽管解决了定位问题,但是用户反馈熄灭屏幕一段时间之后 位置轨迹就不准确了,还有用户反馈 移动过程中,接听了一次电话或者使用Home键切换后台之后(并未杀死进程)位置轨迹不准确了。根据用户描述,判断应该是在这些条件出现之后,程序无法执行代码,后台进程并未存活。所以接下来 面对的就是 iOS 后台保活。
根据苹果开发者文档:
iOS与android 的后台机制不同,Android一般采用的是真后台机制,iOS采用的墓碑机制来管理 后台应用进程。
在Android系统中, 它允许APP留存在后台, 依靠着Service服务组件继续运行,抢占前台CPU资源, 这是Android手机使用时间长后卡顿的主要原因
iOS中,系统会对非前台应用,实施墓碑冻结进程,CPU将资源让出,但是仍在内存中保留
iOS 7以前 ,应用在后台最多存活10分钟,
iOS 7 - 9,应用在后台最多存活 180秒
iOS 10-13,
墓碑机制在不同的版本会有不同的表现,大致就是应用无法长期在后台存活,会被系统冻结进程,最后当内存不足的时候随机会被系统强行回收内存。
当下的目的就是必要要保证应用能在“无限运行”。
解决后台保活
如图1,在 Mac OS 下以Flutter项目为例,进入 /$项目根路径/ios 目录,双击 Runner.xcodepro ,进入图3。
如图 2 可以在Android Studio里面 右键点击项目 ,然后依次选中 Flutter -> Open iOS module in Xcode 然后也能打开 XCode编辑 项目中的iOS模块。
如下图,打开Xcode之后,点击Runner 就可以弹出 配置面板。首先点击 Signing & Capabilities ,
如下图所示
点击 Change All
iOS为我们提供了 几种场景下 可以使用 无限后台的能力
比如 下图所示,分别提供了 :音频、定位更新、基于IP的网络通话、外部必要的访问、使用蓝牙访问、后台拉取、远程通知、后台运行 等这么几项场景下可以做到 无限后台的能力。当然笔者所遇到的场景应该属于 后台定位,再加上需要不断发送位置信息给服务端,所以 再勾上 后台运行,就可以了(注意的是可以利用这种方式可以实现后台常驻,但是AppStore会对应用非常严格的审核,防止开发者滥用权限)
结果
最终效果如下图所示
代码虽然写完了,还剩下最后一步的最重要的上架环节,在上架申请页面中一定要表述清楚自己的目的,否则很容易被审核拒绝。
码字不易,如果对您有帮助,可以一键三连。有遗漏的地方,我会后续在本文中补充添加。
以上是关于Flutter开发之iOS后台定位开发详解的主要内容,如果未能解决你的问题,请参考以下文章
iOS开发简单的实现后台任务(诸如后台播放音乐,定时器,后台定位等)