Flutter开发之iOS后台定位开发详解

Posted Xiao冰同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter开发之iOS后台定位开发详解相关的知识,希望对你有一定的参考价值。

Flutter开发之ios后台定位开发详解

需求目的

开发一个功能持续获取用户的位置发送给后端,PC端会根据后端传来的移动端发送的位置信息,来绘制使用者的运动轨迹。

实现需求是否实现
后台定位
持续定位
后台正常运行

前言

因为笔者使用的是Flutter 来跨端开发,并不是专门的iOS开发人员,所以对iOS的技术不是非常的了解,因此走了很多弯路,本文会以一个 非专业的iOS 兼容开发者角度来记录笔者遇到的问题及解决方案。

出现的问题

  1. 定位权限 :按部就班申请定位权限,但是发现在设置中,应用跟别的应用(高德地图,滴滴出行)等少了 “始终” 使用位置
  2. 定位失效 :息屏或者按Home键 ,就立即或者在一定时间后无法正常定位

查询资料

根据 各方面资料及开发者文档中,得出以下结论:
iOS 7以前:永不始终 选项的位置权限
iOS 8-10:永不始终 选项 ,可以通过配置NSLocationWhenInUseUsageDescription 可出现 使用App期间 选项
iOS 11 - 12:
不用配置NSLocationAlwaysUsageDescription,就会出现永不始终使用App期间
iOS 13:增加 允许一次 选项
Allow Once 提出了 Temporary authorization 的概念。当用户选择 Allow Once 后,我们的 App 就获得了 Temporary authorization ,也就是临时权限
该权限有以下特点:

  1. 实际的权限类型是:WhenInUse;
  2. App 重启后,定位权限会重新变成 NotDetermined,下次开启定位时再申请定位权限会重新弹框让用户确认;
  3. 在 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。

图1

如图 2 可以在Android Studio里面 右键点击项目 ,然后依次选中 Flutter -> Open iOS module in Xcode 然后也能打开 XCode编辑 项目中的iOS模块。

图2

如下图,打开Xcode之后,点击Runner 就可以弹出 配置面板。首先点击 Signing & Capabilities ,

图3

如下图所示


点击 Change All

iOS为我们提供了 几种场景下 可以使用 无限后台的能力
比如 下图所示,分别提供了 :音频、定位更新、基于IP的网络通话、外部必要的访问、使用蓝牙访问、后台拉取、远程通知、后台运行 等这么几项场景下可以做到 无限后台的能力。当然笔者所遇到的场景应该属于 后台定位,再加上需要不断发送位置信息给服务端,所以 再勾上 后台运行,就可以了(注意的是可以利用这种方式可以实现后台常驻,但是AppStore会对应用非常严格的审核,防止开发者滥用权限)

结果

最终效果如下图所示


代码虽然写完了,还剩下最后一步的最重要的上架环节,在上架申请页面中一定要表述清楚自己的目的,否则很容易被审核拒绝。

码字不易,如果对您有帮助,可以一键三连。有遗漏的地方,我会后续在本文中补充添加。

以上是关于Flutter开发之iOS后台定位开发详解的主要内容,如果未能解决你的问题,请参考以下文章

Flutter开发之iOS后台定位开发详解

Flutter开发之iOS后台定位开发详解

Flutter开发百度地图之定位,保姆级教程

Flutter工程化之iOS混编集成

iOS开发简单的实现后台任务(诸如后台播放音乐,定时器,后台定位等)

Flutter完整开发实战详解(十九 Android 和 iOS 打包提交审核指南)