Android SDK:驯服电池管理器
Android 因主动终止后台服务而臭名昭著。中国 OEM 厂商(如小米、华为)甚至拥有自定义电源管理器,完全突破了标准 Android 后台执行限制。
本页解释为什么Android 会杀死您的应用程序以及如何Tracelet 的特定 Android 配置在现实世界中解决它。
可选依赖:高精度GMS定位
Tracelet 的 Android SDK 可以使用 Google Play Services Location — FusedLocationProviderClient
(更好的准确性和电池),硬件活动识别(步行/驾驶/静止),
和硬件地理围栏。为了保持 SDK 的轻量级并可在无 Google 的设备上使用,这
依赖关系未捆绑。仅当您想要高精度路径时才添加它:
// android/app/build.gradle.kts
dependencies {
implementation("com.google.android.gms:play-services-location:21.3.0")
}它是可选的,SDK 会正常降级。 没有 play-services-location、Tracelet
退回到标准 AOSP LocationManager(普通 GPS)。追踪仍然有效——你只需
失去融合提供商的准确性/电池优势、硬件活动识别和硬件
地理围栏。 推荐: 添加它,除非您专门针对无 Google / AOSP 设备
(例如没有 GMS 的华为,或去谷歌的 ROM)。
最低版本:21.2.0。 Tracelet的Android代码调用基于接口
FusedLocationProviderClient 和 ActivityRecognitionClient API,仅成为
play-services-location 21.2.0 中的接口。较旧的版本(例如 19.0.0)提供了这些
作为具体的类,所以调用它们会抛出
运行时 java.lang.IncompatibleClassChangeError。 Tracelet 发布 Gradle
依赖约束,如果满足以下条件,则自动将 play-services-location 提升为 21.2.0+
另一个依赖项会引入旧版本,但如果您自己固定版本,请将其保留在
21.2.0 或更新版本(我们推荐 21.3.0)。
与 play-services-location | 没有它(AOSP 后备) |
|---|---|
| 融合定位(最佳精度+电池) | 原始 GPS/网络通过 LocationManager |
硬件活动识别(onActivityChange) | 仅加速度计运动检测 |
| 硬件地理围栏 | 软件(SDK 内)地理围栏评估 |
可选依赖项:Play Integrity(设备证明)
如果您使用 Tracelet 的 设备证明 功能 (AttestationConfig),则 Android
一方通过 Google Play Integrity 生成其加密令牌。一样
play-services-location,此依赖项未捆绑 - 仅当您添加它时
启用认证:
// android/app/build.gradle.kts
dependencies {
implementation("com.google.android.play:integrity:1.6.0")
}它是可选的,并且证明会优雅地降级。 没有 Play Integrity
依赖关系,Tracelet 中的其他所有内容都正常工作 - 只有证明受到影响:
AttestationConfig(enabled: true) 记录警告和 Tracelet.getAttestationToken()
返回 null 而不是令牌,而不是崩溃。仅当您满足以下条件时才添加依赖项
启用证明并需要在 Android 上进行 Play 完整性判定。请参阅
设备认证指南
用于完整的工作流程和服务器端验证。
必须是 implementation,而不是 compileOnly。 里面的 Play Integrity 是 compileOnly
Tracelet SDK(因此永远不会在不使用证明的应用程序上提供或强制使用它)。如果
您无需将依赖项添加到 app 模块即可启用证明,如下所示
implementation,类在运行时不存在,并且证明会默默返回 null。
权限和清单设置
当您编译应用程序时,Tracelet 会自动将必要的权限注入到 AndroidManifest.xml 中。默认情况下,它要求:
ACCESS_COARSE_LOCATION和ACCESS_FINE_LOCATION(跟踪所需)ACCESS_BACKGROUND_LOCATION(应用程序关闭时跟踪所需)FOREGROUND_SERVICE&FOREGROUND_SERVICE_LOCATION(连续后台执行所需)ACTIVITY_RECOGNITION(智能运动检测引擎所需)POST_NOTIFICATIONS(Android 13+ 前台服务 UI 必需)SCHEDULE_EXACT_ALARM(精确周期模式跟踪所需)
删除未使用的权限(清单合并)
如果您的应用不需要特定功能(例如,您的客户端不需要运动检测,或者您不使用周期模式),您可以在 应用级别 AndroidManifest.xml (android/app/src/main/AndroidManifest.xml) 中使用 Android 清单合并 tools:node="remove" 指令强制删除权限。
Tracelet 的本机代码受到 checkSelfPermission() 的完全保护。 缺少权限将触发正常回退,而不是崩溃。
| 许可 | 删除后的效果 (tools:node="remove") |
|---|---|
| 不翻译迟到 | 安全。 回到基本的仅加速度计运动检测。 onActivityChange 流不会触发(无步行/跑步/驾驶分类)。 |
| 不翻译迟到 | 安全。 当应用程序完全后台运行或滑开时,Android 10+ 将限制跟踪。 |
| 不翻译迟到 | 安全。 定期模式退回到使用电池友好型但不精确的 WorkManager 计时器。 |
| 不翻译迟到 | 安全。 前台服务持久通知在 Android 13+ 上隐藏。服务仍在运行。 |
| 不翻译迟到 | 安全。 您将无法向操作系统请求电池优化豁免。 |
| 不传输迟到 / 不传输迟到 | 对于仅地理围栏/仅定期应用程序是安全的。 删除它们会禁用连续前景跟踪 (start()),但标准地理围栏和定期模式继续工作。 连续后台跟踪所需。 |
| 不传输迟到 / 不传输迟到 | 不安全。 没有任何位置权限,Tracelet 无法获取位置。 |
Google Play 前台服务政策(2026 年 10 月 28 日生效)。 地理围栏 不再是前台服务位置允许的用例。如果您的应用程序使用 前台服务仅用于地理围栏,您必须删除
显现。 Tracelet 的标准地理围栏模式使用本机地理围栏 API 并执行
不启动前台服务,因此仅地理围栏的应用程序是兼容的 - 只是
删除以下权限并保留 foregroundService.enabled = false。请参阅
地理围栏指南
了解详情。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Geofence-only / periodic-only app: no continuous foreground tracking -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" tools:node="remove" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" tools:node="remove" />
</manifest>示例:删除运动和后台权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Client doesn't want Activity/Motion tracking -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" tools:node="remove" />
<!-- Client only wants foreground tracking -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" tools:node="remove" />
<!-- Remove Exact Alarms -->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" tools:node="remove" />
</manifest>自动 ProGuard / R8 规则
Tracelet 大量利用后台 Kotlin 服务、Rust 核心的 JNA 绑定以及反射 Pigeon 通道。如果这些被错误地混淆或缩小,当您的应用程序编译发布时,后台跟踪将默默失败。
您不需要为 Tracelet 手动配置 ProGuard。
tracelet_android 插件自动附带嵌入式 consumer-rules.pro。当您在发布模式下构建 Flutter 应用程序时,Android 的 R8 收缩器会自动提取这些规则,并确保所有必要的类(例如 HeadlessTaskService、BootReceiver 和 Rust uniffi 绑定)在收缩后仍然存在。
场景一:送货司机(持续追踪)
探索的概念: 打瞌睡模式、前台服务、唤醒锁
问题
您的用户是披萨送货司机。他们把手机放进口袋,关掉屏幕。 15 分钟后,Android 进入 Doze 模式。它会关闭网络访问、推迟后台作业并严格限制 CPU 唤醒以节省电池。如果您的应用程序依赖于简单的计时器来获取 GPS,Android 将拒绝运行您的计时器。
Tracelet 如何解决:前台服务
前台服务告诉 Android:“嘿,我现在正在做一些非常重要的事情,用户完全意识到了这一点。不要杀我。”
android: tl.AndroidConfig(
foregroundService: tl.ForegroundServiceConfig(
enabled: true,
channelName: 'Delivery Tracking',
notificationText: 'Tracking your route to the customer',
notificationOngoing: true, // User cannot swipe it away
showNotificationOnPauseOnly: false, // Auto-hides when app is open
actions: ['Pause', 'Complete'], // Adds interactive buttons to the notification
),
)通过在状态栏中显示持久通知,Tracelet 将应用程序的优先级提升到几乎与前台 UI 的级别。 Android 将让 Tracelet 无限期运行,绕过 Doze 模式限制。
自定义通知外观
要使持久通知与您的应用程序的品牌相匹配,您可以自定义图标和颜色:
android: tl.AndroidConfig(
foregroundService: tl.ForegroundServiceConfig(
enabled: true,
notificationTitle: 'Delivery Mode',
notificationText: 'Tracking your route...',
notificationColor: '#0F9D58', // Your brand hex color
notificationSmallIcon: 'ic_tracelet_icon', // The icon name
notificationLargeIcon: 'ic_large_logo',
),
)重要图标规则:
- 文件位置: 图像文件必须放置在您的Android项目的drawable文件夹中(
android/app/src/main/res/drawable/ic_tracelet_icon.png)。 - 小图标限制: Android 要求
notificationSmallIcon完全平坦、透明且纯白色。如果您使用彩色徽标,Android 只会将其呈现为纯灰色或白色方块。 - 颜色属性:
notificationColor属性将为小图标的背景着色以匹配您的品牌。
Android 13+ 注意: 您必须在启动服务之前请求 POST_NOTIFICATIONS 权限,否则通知将被操作系统静默抑制。请参阅 Flutter SDK:权限 页面,了解如何从 Dart 代码中请求此权限。
跟踪时刷新通知 (updateNotification())
在跟踪开始后需要更改通知 - 例如将标题从“途中”更新为“到达”、交换文本或在旅途中更改操作按钮?使用新的 ForegroundServiceConfig 调用 setConfig() 会保留这些值,但仅通知更改不会重新发布 Android 已显示的通知 - 新内容只会在不相关的服务重新启动或前台转换后出现。
自 v3.6.8 起,Tracelet.updateNotification() 会刷新实时通知,无需重新启动跟踪管道:
// 1. Apply the new notification content.
await Tracelet.setConfig(
const tl.Config(
android: tl.AndroidConfig(
foregroundService: tl.ForegroundServiceConfig(
notificationTitle: 'Arriving',
notificationText: 'Your driver is 2 minutes away',
),
),
),
);
// 2. Repost the active notification with the new content.
await Tracelet.updateNotification();设计上安全。 updateNotification() 永远不会重新启动跟踪,并且当前台服务当前未运行时(无需刷新),它是无操作。在 iOS 上,它会刷新正在运行的 Live Activity(当您通过 liveActivityConfig 选择加入一项时);在网络上,它是无操作的 - 因此相同的调用在每个平台上都是安全的。
场景 2:天气应用程序(定期跟踪)
概念探索: WorkManager 与 Exact Alarms
问题
您的用户下载了您当地的天气应用程序。您希望每 4 小时在后台唤醒一次,获取他们的位置,并下载本地天气预报。
您不想要持久的前台服务通知。用户会讨厌在抽屉里看到永久的“天气跟踪”通知。
Tracelet 如何解决这个问题:周期模式
Tracelet 可以使用 Android 的作业调度程序来短暂唤醒、修复并返回睡眠状态,而不是持续的服务。
android: tl.AndroidConfig(
periodicUseForegroundService: false,
periodicUseExactAlarms: true, // Uses AlarmManager instead of WorkManager
)两个调度程序
-
工作管理器(未翻译) 默认。它对电池非常友好。然而,Android 决定何时运行它。如果您要求它每 15 分钟运行一次,Android 可能会等待 45 分钟,并在用户解锁手机查看 Instagram 时运行它(称为“批处理”)。这是非常不精确的。
-
警报管理器(
periodicUseExactAlarms: true) 如果您绝对必须在特定时间准确唤醒设备,请使用此功能。它要求您在android/app/src/main/AndroidManifest.xml中声明SCHEDULE_EXACT_ALARM权限:<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
注意:Google Play 严格审查此权限。仅当您的应用程序是闹钟、日历或绝对需要精确计时时才使用它。
场景 3:OEM 的侵略
探索的概念: 设置健康 API
问题
你做的一切都是对的。您有一个前台服务。但用户拥有一部小米手机。 MIUI 有一个专有的“电池保护程序”,可以在屏幕关闭 5 分钟后强制终止前台服务。
Tracelet 如何解决这个问题:自动缓解和提示
Tracelet 会在可能的情况下自动应用内部缓解措施,但有时用户必须在 OEM 的专有设置菜单中将您的应用程序列入白名单。
final health = await tl.Tracelet.getSettingsHealth();
if (health['isAggressiveOem'] == true) {
// Automatically opens the manufacturer-specific settings screen
// (e.g. Xiaomi Autostart, Huawei App Launch, Samsung Sleeping Apps)
await tl.Tracelet.showPowerManager();
}有关如何在 Flutter UI 中实现此功能的详细示例,请参阅诊断工具和电源管理 页面。