プロダクト ニュース

Android Vitals の wake lock 指標を使用してアプリのバッテリーを最適化する

所要時間: 7 分
Alice Yuan のプロフィールを表示
Alice Yuan Android デベロッパー リレーションズ エンジニア

バッテリー駆動時間はユーザー エクスペリエンスの重要な側面であり、wake lock はその点で大きな役割を果たします。過度に使用していませんか?このブログ投稿では、ウェイクロックとは何か、ウェイクロックを使用する際のベスト プラクティス、Google Play Console の指標を使用してアプリの動作をより深く理解する方法について説明します。

Android Vitals での過度の部分的な wake lock の使用

Google Play Console では、バッテリーの消耗をモニタリングするようになりました。特に、過度の部分的な wake lock の使用を重要なパフォーマンス指標として重視しています。

この機能により、既存の主要な指標である「ユーザーが認識する過度のクラッシュと ANR」に加えて、バッテリー効率の重要性が高まります。過度の wake lock の不正な動作のしきい値を定義しました。2026 年 3 月 1 日より、タイトルがこの品質のしきい値を満たしていない場合、おすすめなどの目立つ検索面にタイトルが表示されないことがあります。場合によっては、アプリがバッテリーを過剰に消耗する可能性があることをユーザーに知らせる警告がストアの掲載情報に表示されることがあります。

warning.png

Android Vitals の概要の過度の wake lock に関する警告。

モバイル デバイスの場合、Android バイタル指標は、画面がオフでアプリがバックグラウンドにあるかフォアグラウンド サービスを実行しているときに取得された、除外されていない wake lock に適用されます。Android Vitals は、次の場合に部分的な wake lock の使用量が過度であると判断します。

  • ウェイクロックが 24 時間以内に 2 時間以上保持されている。
  • アプリのセッションの 5% 以上に影響している(28 日間の平均)。

音声、位置情報、JobScheduler ユーザー開始 API によって作成されたウェイクロックは、ウェイクロックの計算から除外されます。

wake lock について

wake lock は、ユーザーがデバイスを操作していないときでも、アプリがデバイスの CPU を動作させ続けることができるメカニズムです。

部分的な wake lock は、画面がオフの場合でも CPU を動作させ続け、CPU が低消費電力の「サスペンド」状態になるのを防ぎます。完全な wake lock では、画面と CPU の両方が動作し続けます。

部分ウェイクロックを取得する方法は 2 つあります。

  • アプリは、特定のユースケースで PowerManager API を使用して wake lock を手動で取得および解放します。多くの場合、これはユーザーが認識できるオペレーションを目的としたプラットフォーム ライフサイクル API である Foreground Service と組み合わせて取得されます。
  • また、別の API によってウェイクロックが取得され、その API の使用によりアプリに起因することもあります。詳しくは、ベスト プラクティスのセクションをご覧ください。

ウェイクロックは、ユーザーが開始した大容量ファイルのダウンロードを完了するなどのタスクに必要ですが、過度または不適切な使用はバッテリーの著しい消耗につながる可能性があります。アプリがウェイクロックを数時間保持したり、適切に解放しなかったりするケースが確認されています。これにより、ユーザーがアプリを操作していないにもかかわらず、バッテリーの消耗が著しいという苦情が寄せられています。

ウェイクロックの使用に関するベスト プラクティス

過剰なウェイクロックの使用をデバッグする方法を説明する前に、ウェイクロックのベスト プラクティスに沿って対応していることを確認してください。

次の 4 つの重要な質問について検討します。


1. 代替のウェイクロック オプションを検討しましたか?

手動部分 wake lock の取得を検討する前に、次の意思決定フローチャートに従ってください。

wakelock.png

wake lock を手動で取得するタイミングを決定するフローチャート

  1. 画面をオンのままにする必要がありますか?
    • はい: 代わりに Keep Screen On のドキュメントを参照してください
  2. アプリケーションがフォアグラウンド サービスを実行しているか?
    • いいえ: ウェイクロックを手動で取得する必要はありません。
  3. デバイスが一時停止すると、ユーザー エクスペリエンスに悪影響がありますか?
    • 不要: たとえば、デバイスが起動した後に通知を更新する場合、wake lock は必要ありません。
    • はい: 外部デバイスとの通信が継続しているなど、デバイスが一時停止しないようにすることが重要な場合は、続行します。
  4. デバイスを代わりに起動状態に保つ API がすでに存在しますか?
  5. これらの質問にすべて回答し、代替手段がないと判断した場合は、手動でウェイクロックを取得する手順に進む必要があります。

2. ウェイクロックに正しい名前を付けていますか?

ウェイクロックを手動で取得する場合は、デバッグのために適切な名前を付けることが重要です。

  • 名前にメールアドレスなどの個人を特定できる情報(PII)を含めないようにします。PII が検出されると、wake lock は _UNKNOWN としてログに記録され、デバッグの妨げになります。
  • クラス名やメソッド名を使用してウェイクロックをプログラムで命名しないでください。Proguard などのツールによって難読化される可能性があるためです。代わりに、ハードコードされた文字列を使用します。
  • wake lock タグにカウンタまたは一意の識別子を追加しないでください。ウェイクロックが実行されるたびに同じタグを使用することで、システムが名前別に使用状況を集計できるようになり、異常な動作を検出しやすくなります。

3. 取得したウェイクロックは常に解放されますか?

wake lock を手動で取得する場合は、wake lock の解放が常に実行されるようにしてください。ウェイクロックを解放しないと、バッテリーの消耗が著しくなる可能性があります。

たとえば、processingWork() の処理中にキャッチされない例外がスローされると、release() 呼び出しが発生しないことがあります。代わりに、try-finally ブロックを使用して、例外が発生した場合でも wake lock が確実に解放されるようにすることができます。

また、ウェイクロックにタイムアウトを追加して、一定期間後に解放されるようにし、無期限に保持されないようにすることもできます。

fun processingWork() {
    wakeLock.apply {
        try {
            acquire(60 * 10 * 1000) // timeout after 10 minutes
            doTheWork()
        } finally {
            release()
        }
    }
}

4. 起動頻度を減らすことはできますか?

定期的なデータ リクエストの場合、バッテリーの最適化には、アプリがデバイスを起動する頻度を減らすことが重要です。ウェイクアップ頻度を減らす例としては、次のようなものがあります。

  • WorkManager: PeriodicWorkRequest の定期的な間隔を増やします。
  • SensorManager: リスナーを登録する際に maxReportLatencyMs を指定してバッチ処理を活用します。
  • Fused Location Provider:
    • 最新のキャッシュに保存された位置情報に getLastLocation を使用して、位置情報の取得頻度を減らします。
    • バッテリー消費量の少ない更新方法には、setPriority(PRIORITY_PASSIVE) を使用します。
    • また、setMinUpdateIntervalMillis で最小更新間隔を設定することで、位置情報のバッチ処理メカニズムを活用できます。

詳しくは、wake lock のベスト プラクティスに関するドキュメントをご覧ください。

過度の wake lock 使用のデバッグ

最善の意図があっても、ウェイクロックの過剰な使用が発生する可能性があります。Google Play Console でアプリにフラグが設定された場合のデバッグ方法は次のとおりです。

Google Play Console での初回確認

Android Vitals の過度の部分的な wake lock のダッシュボードには、アプリに関連付けられている除外されていない wake lock 名の内訳が表示され、影響を受けたセッションと期間を確認できます。ドキュメントを使用して、ウェイクロック名がアプリによって保持されているか、別の API によって保持されているかを確認するよう促すリマインダー。

breakdowns2.png

Android Vitals の過度の部分的な wake lock ダッシュボードを下にスクロールして、内訳セクションで過度の wake lock タグを表示します。

ワーカー/ジョブによって保持されている過度の wake lock のデバッグ

ワーカーが保持するウェイクロックは、次のウェイクロック名で識別できます。

*job*/<package_name>/androidx.work.impl.background.systemjob.SystemJobService

Worker が保持する wake lock 名のバリエーションの完全なリストは、ドキュメントで確認できます。これらのウェイクロックをデバッグするには、Background Task Inspector を使用してローカルでデバッグするか、getStopReason を利用してフィールドの問題をデバッグします。

Android Studio の Background Task Inspector

taskinspector.png


Background Task Inspector のスクリーン キャプチャ。頻繁に再試行して失敗したワーカー「WeatherSyncWorker」を特定できたことが示されています。

WorkManager の問題をローカルでデバッグするには、エミュレータまたは接続されたデバイス(API レベル 26 以上)でこのツールを使用します。ワーカーとそのステータス(完了、実行中、キューに登録済み)のリストが表示され、詳細を調べたり、ワーカー チェーンを理解したりできます。

たとえば、システム制限に達したためにワーカーが頻繁に失敗したり再試行したりしているかどうかを確認できます。

詳しくは、Background Task Inspector のドキュメントをご覧ください。

WorkManager getStopReason

過剰なウェイクロックがあるワーカーのフィールド内デバッグには、WorkManager 2.9.0 以降では WorkInfo.getStopReason() を、JobScheduler では SDK 31 以降で利用可能な JobParameters.getStopReason() を使用します。

この API は、ワーカーが停止した理由(STOP_REASON_TIMEOUT、STOP_REASON_QUOTA など)をログに記録し、ランタイム期間の超過による頻繁なタイムアウトなどの問題を特定するのに役立ちます。

backgroundScope.launch {
    WorkManager.getInstance(context)
        .getWorkInfoByIdFlow(workRequest.id)
        .collect { workInfo ->
            logStopReason(workRequest.id, workInfo?.stopReason)
        }
}

詳しくは、タスク スケジューリング API のバッテリー使用量を最適化するをご覧ください。

その他の種類の過度の wake lock のデバッグ

手動で保持されたウェイクロックやウェイクロックを保持する API を含む、より複雑なシナリオでは、システム トレース収集を使用してデバッグすることをおすすめします。

システム トレースの収集

システム トレース は、一定期間のシステム アクティビティの詳細な記録をキャプチャする強力なデバッグツールです。CPU 状態、スレッド アクティビティ、ネットワーク アクティビティ、ジョブの所要時間やウェイクロックの使用量などのバッテリー関連の指標に関する分析情報を提供します。

システム トレースは、次の方法でキャプチャできます。

powermgmt.png

Perfetto UI の [Android apps & svcs] タブで [power:PowerManagement] Atrace カテゴリを有効にします。 

選択した方法に関係なく、デバイスの状態トラックを表示できるように、「power:PowerManagement」Atrace カテゴリを収集していることを確認することが重要です。

Perfetto UI の検査と SQL 分析

システム トレースは Perfetto UI で開いて検査できます。トレースを開くと、タイムライン上にさまざまなプロセスの可視化が表示されます。このガイドで取り上げるトラックは、「デバイスの状態」にあります。

perfetto.png


[デバイスの状態] の [上位のアプリ]、[画面の状態]、[長時間実行中の Wake Lock]、[ジョブ] などのトラックを固定して、長時間実行中の Wake Lock スライスを視覚的に特定します。

各ブロックには、イベントの名前、開始時刻、終了時刻が一覧表示されます。Perfetto では、これをスライスと呼びます。

複数のトレースのスケーラブルな分析には、Perfetto の SQL 分析を使用できます。SQL クエリを使用すると、持続時間で並べ替えられたすべてのウェイクロックを見つけることができ、過剰な使用の主な原因を特定するのに役立ちます。

次のクエリの例では、システム トレースで発生したすべての wake lock タグを合計し、合計時間で並べ替えています。

SELECT slice.name as name, track.name as track_name,SUM(dur / 100000) as total_dur_ms
FROM slice
JOIN track ON slice.track_id = track.id
WHERE track.name = 'WakeLocks'GROUP BY slice.name, track.name
ORDER BY total_dur_ms DESC

フィールドでのトレース収集に ProfilingManager を使用する

再現が難しい問題については、ProfilingManager(SDK 35 で追加)は、デベロッパーが開始トリガーと終了トリガーを使用してフィールドでシステム トレースを収集できるプログラム API です。プロファイル収集の開始トリガー ポイントと終了トリガー ポイントをより細かく制御でき、デバイスのパフォーマンスへの影響を防ぐためにシステムレベルのレート制限が適用されます。

フィールド システム トレース収集の実装方法(トレースのプログラムによるキャプチャ、プロファイリング データの分析、ローカル デバッグ コマンドの使用など)の詳細な手順については、ProfilingManager のドキュメントをご覧ください。

ProfilingManager を使用して収集されたシステム トレースは、手動で収集されたものと似ていますが、システム プロセスと他のアプリ プロセスはトレースから削除されます。

まとめ

Android Vitals の過度の部分的な wake lock の指標は、バッテリーの消耗を抑え、アプリの品質を向上させるためのデベロッパーのサポートに対する Google の継続的な取り組みのほんの一部にすぎません。

wake lock を理解して適切に実装することで、アプリのバッテリー パフォーマンスを大幅に最適化できます。代替 API の活用、wake lock のベスト プラクティスの遵守、Background Task Inspector、システム トレース、ProfilingManager などの強力なデバッグツールの使用は、Google Play でアプリを成功させるための鍵となります。

作成者:
続きを読む