Android SDK: バッテリーマネージャーを使いこなす
Android は、バックグラウンド サービスを積極的に停止することで悪名高いです。中国の OEM (Xiaomi、Huawei など) には、標準の Android バックグラウンド実行制限を完全に破るカスタム電源マネージャーさえあります。
このページでは、Android がアプリを強制終了する 理由 と、現実世界で Tracelet の特定の Android 設定がそれを解決する 方法 について説明します。
オプションの依存関係: 高精度 GMS 位置情報
Tracelet の Android SDK は Google Play サービスの場所 を使用できます — 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 のない Huawei、または Google から除外された 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 Integrity の判定が必要です。を参照してください。
デバイス認証ガイド
完全なワークフローとサーバー側の検証については、
compileOnly ではなく、implementation である必要があります。 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 以降では非表示になります。サービスは引き続き実行されます。 |
| 非トランスレート | 安全。 OS からバッテリー最適化の除外をリクエストすることはできません。 |
FOREGROUND_SERVICE / FOREGROUND_SERVICE_LOCATION | ジオフェンス専用/定期専用アプリにとって安全です。 それらを削除すると、継続的な前景追跡 (start()) が無効になりますが、標準のジオフェンスと定期モードは引き続き動作します。 継続的なバックグラウンド追跡には必須。 |
ACCESS_FINE_LOCATION / COARSE | 安全ではありません。 位置情報の許可がなければ、Tracelet は位置を取得できません。 |
Google Play フォアグラウンド サービス ポリシー (2026 年 10 月 28 日発効)。 ジオフェンシングは
フォアグラウンド サービスの場所の使用例は許可されなくなりました。アプリが
フォアグラウンド サービス ジオフェンシング専用のため、削除する必要があります
マージされたものからの FOREGROUND_SERVICE_LOCATION (および FOREGROUND_SERVICE)
マニフェストします。 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 バインディングなど) が圧縮後も存続することを保証します。
シナリオ 1: 配送ドライバー (継続的追跡)
検討した概念: Doze モード、フォアグラウンド サービス、ウェイロック
問題
ユーザーはピザの配達ドライバーです。彼らは携帯電話をポケットに入れ、画面をオフにしました。 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 では、Doze モードの制限を回避して、Tracelet を無期限に実行できるようになります。
通知の外観をカスタマイズする
永続的な通知をアプリのブランドと一致させるには、アイコンと色をカスタマイズできます。
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 プロジェクトの描画可能フォルダー (
android/app/src/main/res/drawable/ic_tracelet_icon.png) に配置する必要があります。 - 小さいアイコンの制約: Android では、
notificationSmallIconが完全にフラット、透明、白のみである必要があります。色付きのロゴを使用すると、Android はそれを単純にグレーまたは白の単色の正方形としてレンダリングします。 - 色のプロパティ:
notificationColorプロパティは、ブランドに合わせて小さなアイコンの背景に色を付けます。
Android 13+ 注: サービスを開始する前に POST_NOTIFICATIONS 権限をリクエストする必要があります。そうしないと、通知は OS によってサイレントに抑制されます。 Dart コードからこれをリクエストする正確な方法については、Flutter SDK: 権限 ページを参照してください。
追跡中の通知の更新 (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 では、代わりに実行中の ライブ アクティビティ が更新されます (liveActivityConfig 経由でオプトインした場合)。 Web では何も操作しません。そのため、同じ呼び出しはどのプラットフォームでも安全です。
シナリオ 2: 天気アプリ (定期的な追跡)
検討した概念: WorkManager と正確なアラームの比較
問題
ユーザーはローカル天気予報アプリをダウンロードしました。 4 時間ごとにバックグラウンドで起動し、位置情報を取得して、地域の天気予報をダウンロードしたいと考えています。
永続的なフォアグラウンド サービス通知は「必要ありません」。ユーザーは、引き出しに「天気追跡」通知が永続的に表示されるのを嫌がるでしょう。
Tracelet による問題の解決方法: 定期モード
Tracelet は、継続的なサービスの代わりに、Android のジョブ スケジューラを使用して、一時的に起動し、修正を取得してからスリープに戻ることができます。
android: tl.AndroidConfig(
periodicUseForegroundService: false,
periodicUseExactAlarms: true, // Uses AlarmManager instead of WorkManager
)2 つのスケジューラ
-
ワークマネージャー (
periodicUseExactAlarms: false) デフォルト。バッテリーに非常に優しいです。ただし、Android を「いつ」実行するかは 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
問題
あなたはすべてを正しく行いました。フォアグラウンド サービスがあります。しかし、ユーザーはXiaomiの携帯電話を所有しています。 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 に実装する方法の詳細な例については、診断ツールと電源管理 ページを参照してください。