Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

停止した部分的な wake lock

部分的な wake lock は PowerManager API のメカニズムです。これにより、デベロッパーはデバイスのディスプレイがオフになった後も(システム タイムアウトが原因であっても、ユーザーが電源ボタンを押したことが原因であっても)CPU を動作させ続けられます。PARTIAL_WAKE_LOCK フラグを指定して acquire() を呼び出すと、アプリで部分的な wake lock が取得されます。アプリをバックグラウンドで実行しているときに部分的な wake lock を長時間保持すると、停止します(アプリのどの部分もユーザーに表示されません)。この状態ではデバイスが省電力状態にならないため、デバイスの電池が消耗します。部分的な wake lock は必要なときにのみ使用し、不要になったらすぐに解放する必要があります。

アプリで部分的な wake lock が停止している場合、このページのガイダンスが問題の診断と解決に役立ちます。

問題を検出する

アプリの部分的な wake lock が停止したこと常に把握できるとは限りません。 アプリをすでに公開している場合は、Android Vitals が問題の発見に役立ちます。

Android Vitals

Android Vitals は、アプリが部分的な wake lock を停止しているときに Play Console を介して警告を発することで、アプリのパフォーマンスを改善します。 Android Vitals では、次のいずれかで 1 時間以上の部分的な wake lock が発生した場合に、部分的な wake lock が停止したと報告されます。

  • バッテリ セッション全体の少なくとも 0.70%。
  • または

  • バックグラウンドでのみ実行中のバッテリー セッションの少なくとも 0.10%。

バッテリー セッションとは、2 回のフル充電の間隔のことです。表示されるバッテリー セッション数は、アプリの測定対象ユーザー全員の集計値です。Google Play が Android Vitals のデータを収集する方法については、Play Console のドキュメントをご覧ください。

アプリが部分的な wake lock を過度に停止していることがわかったら、問題に対処することが次のステップになります。

問題を解決する

wake lock は Android プラットフォームの初期のバージョンで導入されましたが、時間の経過とともに、以前は wake lock が必要だったユースケースでも、WorkManager のような新しい機能を使用する方が適切になっています。

このセクションでは wake lock を修正するためのヒントを紹介しますが、長期的には、おすすめの方法セクションにある推奨事項に沿ってアプリを移行することを検討してください。

newWakeLock(int, String)WakefulBroadcastReceiver など、コード内で wake lock を取得する場所を特定して修正します。ヒントをいくつかご紹介します。

  • wake lock が作成されたソース内の場所を特定しやすくするために、wake lock のタグ名にパッケージ名、クラス名、またはメソッド名を含めることをおすすめします。その他のヒントは次のとおりです。

    • 名前にメールアドレスなどの個人を特定できる情報(PII)を含めないようにします。そうしないと、デバイスは wake lock 名ではなく _UNKNOWN をログに記録します。
    • getName() の呼び出しなどによって、クラス名やメソッド名をプログラムで取得しないでください。Proguard で難読化される可能性があるためです。代わりに、ハードコードされた文字列を使用します。
    • wake lock タグにカウンタまたは一意の識別子を追加しないでください。同じメソッドで作成された wake lock はすべて一意の識別子を持っているため、システムで集計できません。
  • コードの中で取得したすべての wake lock が解放されていることを確認します。これは、acquire() の呼び出しすべてに release() の呼び出しが対応するようにするより複雑です。捕捉されない例外のために解放されない wake lock の例を次に示します。

    Kotlin

        @Throws(MyException::class)
        fun doSomethingAndRelease() {
            wakeLock.apply {
                acquire()
                doSomethingThatThrows()
                release()  // does not run if an exception is thrown
            }
        }

    Java

            void doSomethingAndRelease() throws MyException {
                wakeLock.acquire();
                doSomethingThatThrows();
                wakeLock.release();  // does not run if an exception is thrown
            }

    正しいコードは次のとおりです。

    Kotlin

        @Throws(MyException::class)
        fun doSomethingAndRelease() {
            wakeLock.apply {
                try {
                    acquire()
                    doSomethingThatThrows()
                } finally {
                    release()
                }
            }
        }

    Java

            void doSomethingAndRelease() throws MyException {
                try {
                    wakeLock.acquire();
                    doSomethingThatThrows();
                } finally {
                    wakeLock.release();
                }
            }
  • wake lock は不要になったらすぐに解放するようにしてください。たとえば、バックグラウンド タスクの終了を許可するために wake lock を使用している場合は、タスクが終了したときに解放されるようにします。wake lock が解放されずに予想よりも長く保持された場合、バックグラウンド タスクに予想よりも時間がかかっている可能性があります。

コードの問題を解決したら、次の Android ツールを使用して、アプリが wake lock を正しく解放することを確認します。

  • dumpsys - デバイス上でシステム サービスのステータスに関する情報を提供するツール。 wake lock のリストを含む電源サービスのステータスを確認するには、adb shell dumpsys power を実行します。

  • Battery Historian - Android バグレポートの出力を解析して、電源関連のイベントを視覚的に表示するツール。

運用ガイド

一般的に、アプリは電池を消耗しやすいため、部分的な wake lock は避ける必要があります。Android には、以前は部分的な wake lock が必要だったほぼすべてのユースケースについて代替 API が用意されています。部分的な wake lock の残りのユースケースの 1 つは、画面がオフになっても音楽アプリの再生を続けるようにすることです。wake lock を使用してタスクを実行する場合は、バックグラウンド処理ガイドに記載されている代替の方法を検討してください。

部分的な wake lock を使用する必要がある場合は、次の推奨事項に従ってください。

  • アプリの一部がフォアグラウンドに残っていることを確認します。たとえば、サービスを実行する必要がある場合は、フォアグラウンド サービスを開始します。これにより、アプリがまだ実行中であることが視覚的に示されます。
  • wake lock の取得と解放のロジックが可能な限り単純であることを確認します。wake lock のロジックが、複雑なステートマシン、タイムアウト、エグゼキュータ プール、コールバック イベントに関連付けられている場合、そのロジックにわずかでもバグがあると、wake lock が予想よりも長く保持される可能性があります。そのようなバグは、診断とデバッグが困難です。