プロダクト ニュース

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

7 分で読了
Alice Yuan
デベロッパー リレーションズ エンジニア

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

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

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

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

warning.png

Android Vitals の概要に表示される過度の wake lock の警告。

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

  • 24 時間以内に 2 時間以上 wake lock が保持されている。
  • 28 日間の平均で、アプリのセッションの 5% を超えるセッションに影響している。

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

wake lock について

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

部分的な wake lock は、画面がオフの場合でも CPU を動作させ続け、CPU が低電力の「一時停止」状態になるのを防ぎます。完全な wake lock は、画面と CPU の両方を動作させ続けます。

部分的な wake lock を取得する方法は 2 つあります。

  • アプリが特定のユースケースで PowerManager API を使用して wake lock を手動で取得して解放します。多くの場合、これは フォアグラウンド サービス(ユーザーが認識できる操作を目的としたプラットフォーム ライフサイクル API)と組み合わせて取得されます。
  • または、wake lock は別の API によって取得され、API の使用によりアプリに帰属します。詳細については、ベスト プラクティスのセクションをご覧ください。

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

wake lock の使用に関するベスト プラクティス

wake lock の過剰な使用をデバッグする方法について説明する前に、wake lock のベスト プラクティスに準拠していることを確認してください。

次の 4 つの重要な質問について考えてみましょう。


1. wake lock の代替オプションを検討しましたか?

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

wakelock.png

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

  1. 画面をオンにしておく必要がありますか?
  2. アプリがフォアグラウンド サービスを実行していますか?
    • いいえ: wake lock を手動で取得する必要はありません。
  3. デバイスが一時停止すると、ユーザー エクスペリエンスに悪影響がありますか?
    • いいえ: たとえば、デバイスの復帰後に通知を更新する場合、wake lock は必要ありません。
    • はい: 外部デバイスとの継続的な通信など、デバイスの一時停止を防ぐことが重要な場合は、続行します。
  4. デバイスをスリープさせないようにする API がすでにありますか?
    • 他の API によって作成された wake lock を特定するのドキュメント Identify wake locks created by other APIs を活用して、他の API によって作成された wake lock を特定するシナリオ(LocationManager など)を特定できます。
    • API が存在しない場合は、最後の質問に進みます。
  5. これらの質問にすべて回答し、代替手段がないと判断した場合は、wake lock を手動で取得する必要があります。

**2. wake lock の名前を正しく付けていますか?

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

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

3. 取得した wake lock は常に解放されますか?

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

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

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

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

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

定期的なデータ リクエストの場合、アプリがデバイスを起動する頻度を減らすことがバッテリーの最適化の鍵となります。wakeup の頻度を減らす例をいくつか示します。

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

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

wake lock の過剰な使用をデバッグする

最善の意図を持っていても、wake lock の過剰な使用が発生する可能性があります。Google Play Console でアプリにフラグが設定された場合は、次の方法でデバッグします。

Google Play Console での初期特定

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

breakdowns2.png

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

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

ワーカーによって保持されている wake lock は、次の wake lock 名で識別できます。

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

ワーカーによって保持されている wake lock 名のバリエーションの完全なリストは、ドキュメントで確認できます。これらの 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

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

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

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

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

他の種類の過度の wake lock をデバッグする

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

システム トレース収集

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

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

powermgmt.png

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

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

Perfetto UI の検査と SQL 分析

システム トレースはPerfetto UI で開いて検査できます。トレースを開くと、タイムライン上にさまざまなプロセスの視覚化が表示されます。このガイドでは、「Device State」の下にあるトラックに焦点を当てます。

perfetto.png


[Top app]、[Screen state]、[Long Wake locks]、[Jobs] などの [Device State] のトラックを固定して、長時間実行されている wake lock スライスを視覚的に識別します。

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

複数のトレースをスケーラブルに分析するには、Perfetto の SQL 分析 を使用します。SQL クエリを使用すると、期間で並べ替えられたすべての wake lock を見つけることができ、過剰な使用の主な原因を特定できます。

システム トレースで発生したすべての 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 でアプリを成功させるための鍵となります。

作成者:

続きを読む