バッテリーの過剰な消耗が Android ユーザーにとって最も重要な問題であると認識し、Google はデベロッパーがより省電力なアプリを構築できるよう、さまざまな対策を講じてきました。2026 年 3 月 1 日より、Google Play ストアはバッテリーの消耗を改善するために、wake lock の技術的な品質処理のロールアウトを開始しました。この対応は、今後数週間にわたって影響を受けるアプリに段階的に展開されます。Android Vitals の [過度の部分的な Wake Lock] のしきい値を継続的に超えているアプリは、ストアでの表示に影響を受ける可能性があります。たとえば、ストアの掲載情報に警告が表示される、おすすめなどの検索サーフェスから除外されるなどです。
アプリが不正な動作のしきい値を超えると、ユーザーに対しストアの掲載情報に警告が表示されることがあります。
この取り組みにより、バッテリー効率はクラッシュや ANR などの安定性指標と並ぶ重要な指標となりました。「不正な動作のしきい値」は、過去 28 日間のユーザー セッションの 5% 超で、画面がオフのときに平均で 2 時間以上、除外されていない部分的な wake lock を保持していると定義されます。ウェイクロックがシステム保持のウェイクロックであり、音声再生、位置情報へのアクセス、ユーザーが開始したデータ転送など、明確なユーザーメリットがあり、それ以上最適化できない場合は、ウェイクロックは免除されます。過度の wake lock の定義については、Android Vitals のドキュメントをご覧ください。
Android エコシステム全体でバッテリー寿命を改善するための継続的な取り組みの一環として、Google は数千ものアプリと、それらのアプリが部分的なウェイクロックをどのように使用しているかを分析しました。ウェイクロックは必要な場合もありますが、より効率的な解決策があるにもかかわらず、アプリが非効率的または不必要にウェイクロックを保持していることがよくあります。このブログでは、過剰なウェイクロックが発生する最も一般的なシナリオと、ウェイクロックを最適化するための推奨事項について説明します。WHOOP などのパートナーは、これらの推奨事項を活用してバックグラウンド動作を最適化し、すでに目覚ましい成果を上げています。
フォアグラウンド サービスと部分的なウェイクロックの使用
バックグラウンド実行を行う際に、フォアグラウンド サービスと部分的なウェイクロックという 2 つのコンセプトの違いを理解するのに苦労しているデベロッパーをよく見かけます。
フォアグラウンド サービスは、アプリがユーザーに認識可能な作業を行っており、メモリを再利用するために強制終了すべきではないことをシステムに通知するライフサイクル API ですが、画面がオフになったときに CPU がスリープ状態になるのを自動的に防ぐことはありません。一方、部分的な wake lock は、画面がオフになっている間も CPU を実行し続けるように特別に設計されたメカニズムです。
フォアグラウンド サービスはユーザー アクションを継続するために必要なことが多いですが、部分的な wake lock の手動取得は、CPU アクティビティの期間中、フォアグラウンド サービスと組み合わせて使用する場合にのみ必要です。また、デバイスをスリープ状態にしない API をすでに使用している場合は、ウェイクロックを使用する必要はありません。
デバイスを起動状態に保つための適切な API を選択するのフローチャートを参照して、不要な場合にウェイクロックを取得しないようにするための適切なツールを理解してください。
wake lock を取得するサードパーティ ライブラリ
アプリが、サードパーティの SDK またはシステム API がアプリに代わって保持している過剰なウェイクロックについてフラグが設定されていることを検出することはよくあります。これらのウェイクロックを特定して解決するには、次の手順をおすすめします。
- Android Vitals を確認する: 過度の部分的な wake lock のダッシュボードで、問題のある wake lock の正確な名前を確認します。この名前を 他の API によって作成されたウェイクロックを特定するのガイダンスと相互参照して、既知のシステム API または Jetpack ライブラリによって作成されたものかどうかを確認します。その場合は、API の使用量を最適化する必要があるため、推奨されるガイダンスを参照してください。
- システム トレースをキャプチャする: ウェイクロックを簡単に特定できない場合は、システム トレースを使用してウェイクロックの問題をローカルで再現し、Perfetto UI で検査します。この方法について詳しくは、こちらのブログ投稿の他のタイプの過剰なウェイクロックのデバッグのセクションをご覧ください。
- 代替手段を評価する: 効率の悪いサードパーティ ライブラリが原因で、バッテリー寿命を尊重するように構成できない場合は、SDK の所有者に問題を伝え、代替の SDK を見つけるか、機能を自社で構築することを検討してください。
一般的な wake lock のシナリオ
以下に、レビューした具体的なユースケースと、wake lock の実装を最適化するための推奨パスを示します。
ユーザーが開始したアップロードまたはダウンロード
ユースケースの例:
- ユーザーがオフライン アクセス用に大容量ファイルのダウンロードをトリガーする動画ストリーミング アプリ。
- ユーザーが通知プロンプトから最近の写真のアップロードをトリガーするメディア バックアップ アプリ。
wake lock を減らす方法:
- 手動 wake lock を取得しないでください。代わりに、ユーザーが開始したデータ転送(UIDT)API を使用してください。これは、ユーザーが開始した長時間実行されるデータ転送タスクの指定パスであり、過剰な wake lock の計算から除外されます。
1 回限りのバックグラウンド同期または定期的なバックグラウンド同期
ユースケースの例:
- アプリは定期的にバックグラウンド同期を実行して、オフライン アクセス用のデータを取得します。
- 歩数を定期的に取得する歩数計アプリ。
wake lock を減らす方法:
- 手動 wake lock を取得しないでください。1 回限りの処理または定期的な処理用に構成された WorkManager を使用します。
WorkManagerは、タスクをバッチ処理することでシステムの健全性を維持し、最小定期間隔(15 分)を設定します。これは通常、バックグラウンド更新に十分な間隔です。 WorkManagerまたは JobScheduler によって作成されたウェイクロックの使用率が高いことが判明した場合、特定のシナリオで完了しないように Worker が誤って構成されている可能性があります。STOP_REASON_TIMEOUT の発生頻度が高い場合は、ワーカーの停止理由の分析を検討してください。
workManager.getWorkInfoByIdFlow(syncWorker.id)
.collect { workInfo ->
if (workInfo != null) {
val stopReason = workInfo.stopReason
logStopReason(syncWorker.id, stopReason)
}
}- ワーカーの停止理由のロギングに加えて、ワーカーのデバッグに関するドキュメントもご覧ください。また、システム トレース を収集して分析し、ウェイクロックの取得と解放のタイミングを把握することも検討してください。
- 最後に、WHOOP のケーススタディをご覧ください。このケーススタディでは、WHOOP が Worker の構成に関する問題を発見し、wake lock の影響を大幅に軽減することができました。
Bluetooth 通信
ユースケースの例:
- コンパニオン デバイスアプリが、Bluetooth 外部デバイスをペア設定するようユーザーに促します。
- コンパニオン デバイスアプリは、外部デバイスのハードウェア イベントと、ユーザーに表示される通知の変更をリッスンします。
- コンパニオン デバイス アプリのユーザーが、モバイル デバイスと Bluetooth デバイス間のファイル転送を開始します。
- コンパニオン デバイス アプリが、Bluetooth 経由で外部デバイスのファームウェアを定期的に更新します。
wake lock を減らす方法:
- コンパニオン デバイスのペア設定を使用して Bluetooth デバイスをペア設定し、Bluetooth のペア設定中に手動 wake lock を取得しないようにします。
- バックグラウンドで Bluetooth 通信を行う方法については、 バックグラウンドで通信するのガイダンスを参照してください。
- 遅延したコミュニケーションがユーザーに影響しない場合は、
WorkManagerを使用すれば十分なことがよくあります。手動ウェイクロックが必要と判断された場合は、Bluetooth アクティビティまたはアクティビティ データの処理の期間のみウェイクロックを保持します。
位置情報追跡
ユースケースの例:
- ランニング ルートのプロットなど、後でアップロードするために位置情報をキャッシュに保存するフィットネス アプリ
- 位置情報を高頻度で取得して、通知やウィジェットの UI で配達状況を更新するフード デリバリー アプリ。
wake lock を減らす方法:
- 位置情報の使用を最適化するに関するガイダンスをご覧ください。バッテリー効率を確保するため、タイムアウトの実装、位置情報リクエストのバッチ処理の活用、パッシブな位置情報の更新の利用を検討してください。
- FusedLocationProvider API または LocationManager API を使用して位置情報の更新をリクエストすると、位置情報イベントのコールバック中にデバイスのウェイクアップが自動的にトリガーされます。この短いシステム管理の wake lock は、過度の部分的な wake lock の計算から除外されます。
- 位置情報をキャッシュに保存するために、別の連続的な wake lock を取得することは避けてください。これは冗長です。代わりに、位置情報イベントをメモリまたはローカル ストレージに保存し、WorkManager を利用して定期的に処理します。
override fun onCreate(savedInstanceState: Bundle?) {
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
// System wakes up CPU for short duration
for (location in locationResult.locations){
// Store data in memory to process at another time
}
}
}
}高頻度センサー モニタリング
ユースケースの例:
- 歩数や移動距離をパッシブに収集する歩数計アプリ。
- デバイスのセンサーをリアルタイムでモニタリングして急激な変化を検出し、衝突検出や転倒検出などの機能を提供する緊急情報サービス アプリ。
wake lock を減らす方法:
- SensorManager を使用する場合は、使用頻度を定期的な間隔に減らし、ユーザーが UI 操作を通じて明示的にアクセスを許可した場合のみ使用します。高頻度のセンサー モニタリングでは、CPU のウェイクアップと処理の回数が多くなるため、バッテリーの消耗が激しくなる可能性があります。
- SensorManager を使用するのではなく、歩数や移動距離をトラッキングする場合は、Recording API を活用するか、ヘルスコネクトを利用してデバイスの過去の歩数と集計された歩数にアクセスし、バッテリー効率の良い方法でデータを取得することを検討してください。
- SensorManager でセンサーを登録する場合は、センサー バッチ処理を活用して CPU 割り込みの頻度を最小限に抑えるため、30 秒以上の maxReportLatencyUs を指定します。その後、ユーザー インタラクション、位置情報の取得、スケジュールされたジョブなどの別のトリガーによってデバイスが起動されると、システムはキャッシュに保存されたセンサーデータを直ちにディスパッチします。
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) sensorManager.registerListener(this, accelerometer, samplingPeriodUs, // How often to sample data maxReportLatencyUs // Key for sensor batching )
- アプリで位置情報とセンサーデータの両方が必要な場合は、イベントの取得と処理を同期します。位置情報の更新のためにシステムが保持する短い wake lock にセンサーの読み取り値を相乗りさせることで、CPU を起動状態に保つための wake lock が不要になります。この結合データのアップロードと処理を処理するには、Worker または短時間の wake lock を使用します。
リモート メッセージング
ユースケースの例:
- ローカル ネットワークを使用して接続された外部デバイスで発生するイベントをモニタリングする必要がある、動画または音声モニタリング コンパニオン アプリ。
- デスクトップ バリアントとのネットワーク ソケット接続を維持するメッセージ アプリ。
wake lock を減らす方法:
- ネットワーク イベントをサーバーサイドで処理できる場合は、FCM を使用してクライアントで情報を受け取ります。FCM データの追加処理が必要な場合は、高速ワーカーのスケジュールを設定できます。
- イベントをソケット接続経由でクライアント側で処理する必要がある場合、イベント割り込みをリッスンするためにウェイクロックは必要ありません。データパケットが Wi-Fi またはモバイル無線に到達すると、無線ハードウェアはカーネル wake lock の形式でハードウェア割り込みをトリガーします。その後、Worker のスケジュールを設定するか、wake lock を取得してデータを処理するかを選択できます。
- たとえば、ktor-network を使用してネットワーク ソケットでデータ パケットをリッスンしている場合、パケットがクライアントに配信され、処理が必要になったときにのみウェイクロックを取得する必要があります。
val readChannel = socket.openReadChannel()
while (!readChannel.isClosedForRead) {
// CPU can safely sleep here while waiting for the next packet
val packet = readChannel.readRemaining(1024)
if (!packet.isEmpty) {
// Data Arrived: The system woke the CPU and we should keep it awake via manual wake lock (urgent) or scheduling a worker (non-urgent)
performWorkWithWakeLock {
val data = packet.readBytes()
// Additional logic to process data packets
}
}
}概要
バックグラウンド同期、位置情報の追跡、センサー モニタリング、ネットワーク通信などの一般的なユースケースに推奨されるソリューションを採用することで、デベロッパーは不要なウェイクロックの使用を減らすことができます。さらに詳しく知りたい場合は、他の技術ブログ投稿を読むか、技術動画(Android Vitals の wake lock 指標を使用してアプリのバッテリーを最適化する)で wake lock を検出してデバッグする方法をご覧ください。また、更新されたウェイクロックに関するドキュメントもご覧ください。技術リソースの改善を継続するため、ガイダンスに関する追加のフィードバックは、ドキュメントのフィードバック アンケートにご記入ください。
続きを読む
-
ハウツー
パフォーマンス レベリング ガイドには 5 つのレベルがあります。レベル 1 から始めます。レベル 1 では、導入の労力が最小限で済むパフォーマンス ツールが導入されます。レベル 5 は、カスタム パフォーマンス フレームワークを維持するためのリソースがあるアプリに最適です。
Alice Yuan • 所要時間: 9 分
-
ハウツー
オンデバイス モデルとクラウドモデルの両方を使用する AI 対応機能の例をご紹介し、ユーザーに喜ばれるエクスペリエンスの作成に役立てていただきたいと考えています。
Thomas Ezan, Ivy Knight • 所要時間: 2 分
-
ハウツー
プロファイルに基づく最適化、Jetpack Compose のパフォーマンスの改善、舞台裏での作業に関する考慮事項について説明します。
Ben Weiss, Breana Tate, Jossi Wolf • 所要時間: 8 分
メールを受け取る
Android 開発に関する最新の分析情報を毎週メールでお届けします。