Skip to Content
中心となる概念フォアグラウンドサービスの健全性

フォアグラウンドサービスの健全性

Android では、永続的なフォアグラウンド サービスがバックグラウンドで位置情報を保持します。 追跡は生きています。ただし、追跡を依頼する (Tracelet.start()) ことは、 OS がフォアグラウンド サービスの実行を 許可します。 Android 12 以降では アプリの実行中であっても、フォアグラウンド サービスの開始は 遅延 または 拒否 される可能性があります 追跡が有効になっていると考えられます。

Tracelet.getForegroundServiceHealth() はそのギャップを埋めます。それは、 フォアグラウンド サービスの権限のあるネイティブ状態「追跡が要求されました」「追跡は実際に行われます」の違い running” — それらが発散したときに反応します。

3.6.6 の新機能 これは、フォアグラウンド サービスの信頼性に関する修正を補完します。 3.6.5 (#253 ) および 3.6.6 (#254 ) サービスの Dartから観察できる実際の状態。


enabled では不十分な理由

Tracelet.getState().enabled望ましい 状態です。つまり、永続的な意図です。 追跡。 「アプリは追跡を要求しましたか?」 ではなく、実際に OS であると答えます。 今フォアグラウンド サービスを実行していますか?”*。

特に Android 12 以降 (API 31 以降) では異なる場合があります。 バックグラウンドからの location フォアグラウンド サービスは制限されています。

  • 開始は 延期できます — アプリの実行中は Android が開始を拒否します。 アプリが次にバックグラウンドに戻ったときに、Tracelet が自動的に再試行します。 前景。
  • 開始は完全に失敗する可能性があります — 例:権限が不足している、または 翻訳されません。
  • サービスはシステムによって プロモートされてから停止できます。

これらすべてのケースで、enabledtrue のままですが、バックグラウンド追跡はありません 稼働中。ロケーションタイムスタンプウォッチドッグは最終的には古いことに気づく可能性がありますが、 理由 はわかりません。プロモーションが失敗したか、サービスが停止したか、または プロバイダーは新しい修正を待っているだけです。非トランスレート 実際の権威ある理由を示します。


API

final health = await Tracelet.getForegroundServiceHealth();

次のキーを含む Map<String, Object?> を返します。

キータイプ意味
非トランスレート翻訳1遅れ永続化された 望ましい 追跡状態 (getState().enabled と同じ)。
非トランスレート翻訳1遅れアクティブな構成がフォアグラウンド サービスを実行しているかどうか。
非トランスレート翻訳1遅れネイティブ位置情報サービスプロセスが稼働しているかどうか。
非トランスレート翻訳1遅れサービスが現在フォアグラウンドに昇格しているかどうか (最後の startForeground() が成功し、それ以降降格/停止されていない)。
非トランスレート翻訳1遅れ昇格中の通知 ID。それ以外の場合は null
非トランスレート翻訳1遅れsuccessdeferred、または failed — 最新のプロモーション試行の結果 (試行前の null)。
非トランスレート翻訳1遅れ最後に失敗または延期されたプロモーションの例外クラス (例: ForegroundServiceStartNotAllowedException)。
非トランスレート翻訳1遅れ例外メッセージ。
非トランスレート翻訳1遅れ最後のプロモーション遷移のエポックミリ秒。
非トランスレート翻訳1遅れandroidios、または web

マップの形状はすべてのプラットフォームで意図的に同じであるため、クロスプラットフォーム コード 均一に読み取れます。 のみがプラットフォームごとに異なります (下記を参照)。


昇格結果の見方

serviceForegroundlastForegroundPromotionResult を組み合わせると、 全話:

非トランスレート翻訳1遅れlastForegroundPromotionResult解釈
非トランスレート翻訳1遅れ任意追跡はオフになっていますので、心配する必要はありません。
非トランスレート翻訳1遅れsuccess正常 — フォアグラウンド サービスは実行されており、昇格されています。
非トランスレート翻訳1遅れdeferred延期 — Android はバックグラウンドでの起動を拒否しました。アプリがフォアグラウンドに戻ったときに、Tracelet が再試行します。
非トランスレート翻訳1遅れfailed失敗 — 昇格は失敗しました。バックグラウンド追跡は機能しません。失敗クラス/メッセージを検査します。
非トランスレート翻訳1遅れnull⌛ リクエストされましたが、まだ確認されていません (一時的 - すぐに再度ポーリングします)。

追跡健全性インジケーター

最も一般的な用途: 正直なステータスをユーザー (またはテレメトリ) に明らかにする enabled を盲目的に信頼するのではなく。

Future<String> describeTrackingHealth() async { final h = await Tracelet.getForegroundServiceHealth(); if (h['desiredEnabled'] != true) return 'Tracking off'; // iOS/web have no foreground service — enabled tracking is as good as it gets. if (h['platform'] != 'android') return 'Tracking active'; if (h['serviceForeground'] == true) return 'Tracking active'; switch (h['lastForegroundPromotionResult']) { case 'deferred': return 'Waiting to start — reopen the app to resume background tracking'; case 'failed': final reason = h['lastForegroundPromotionFailureMessage'] ?? 'unknown'; return 'Background tracking failed to start: $reason'; default: return 'Starting…'; } }

回復ウォッチドッグ

ヘルスチェックと定期タイマーを組み合わせて、障害を検出して回復します。 プロモーション — たとえば、ユーザーにアプリを再度開くか、再リクエストするように促します。 許可がありません。

Timer.periodic(const Duration(minutes: 1), (_) async { final h = await Tracelet.getForegroundServiceHealth(); final desired = h['desiredEnabled'] == true; final foreground = h['serviceForeground'] == true; final result = h['lastForegroundPromotionResult']; if (desired && !foreground && result == 'failed') { // Background tracking is not operational. Log it, alert your backend, // or guide the user to fix permissions / battery settings. await reportTrackingDegraded( failureClass: h['lastForegroundPromotionFailureClass'], failureMessage: h['lastForegroundPromotionFailureMessage'], ); } });

serviceForeground は、ライブ投票ではなく、最後のプロモーション結果を反映します。 OS をミリ秒ごとに監視します。 start()の直後にプロモーションが始まります 後で — 最新の値が必要な場合は、短い遅延 (1 ~ 2 秒) 後に再度ポーリングします。


プラットフォームの動作

プラットフォーム行動
アンドロイドライブのフォアグラウンド サービスの状態とプロモーション履歴が完全に入力されます。
iOS事後に失敗する可能性のあるフォアグラウンド サービスはないため、serviceForegroundfalseforegroundServiceEnabledfalse、プロモーション フィールドは null になります。 desiredEnabledserviceRunning は、追跡がアクティブかどうかを反映します。 platformiosです。
ウェブフォアグラウンドサービスはありません。目的の状態を反映する最小限のマップを返します。 platformwebです。

これが、iOS がフォアグラウンド サービスの推進競争の影響を受けない理由です。 #253  で Android 向けに修正されました。 #254 : iOS には個別の機能がありません 昇格させてから破棄できるフォアグラウンド サービス プロセス。


Tracelet Doctor で

「見る」ためにこれを自分で構築する必要はありません。の tracelet_doctor オーバーレイに Foreground が含まれるようになりました まさにこの情報をレンダリングするサービス カード (望ましい情報と実際の情報、 昇格結果と失敗クラス/メッセージ — 色分けされたステータス付き (正常/遅延/失敗/非アクティブ)。

tracelet_doctor開発依存関係 (flutter pub add dev:tracelet_doctor) であるため、 kDebugMode でガードします。

import 'package:flutter/foundation.dart' show kDebugMode; import 'package:tracelet_doctor/tracelet_doctor.dart'; if (kDebugMode) { TraceletDoctor.show(context); // includes the Foreground Service card }

同じフィールドが バグ レポート (TraceletBugReport.build()) にもキャプチャされます。 したがって、貼り付けられたレポートには、フォアグラウンド サービスが実際に実行されていたかどうかが示されます。 問題の発生時刻 — 多くの場合、「追跡が停止している」という手がかりが欠けています。 背景」が報じた。


知っておいてよかった

  • 読み取り専用で安価。 呼び出しはメモリ内のネイティブ状態を読み取るだけです。それは決してありません 追跡を開始、停止、または変更します。
  • ready() より前は安全です。 スナップショットではなく、適切なデフォルトのスナップショットを返します。 SDK が初期化されていない場合にスローされます。
  • 望ましい対実際が重要です。 getState().enabled を使用し続けてください。 アプリの意図。 getForegroundServiceHealth() を使用して OS が その意図を尊重します。
Last updated on