ウェイクロックのベスト プラクティスに従う

ウェイクロックを使用すると、デバイスのパフォーマンスが低下する可能性があります。ウェイクロックを使用する必要がある場合は、適切に行うことが重要です。このドキュメントでは、一般的なウェイクロックの落とし穴を回避するためのベスト プラクティスについて説明します。

ウェイクロックに適切な名前を付ける

wakelock タグにはパッケージ名、クラス名、またはメソッド名を含めることをおすすめします。これにより、エラーが発生した場合に、ウェイクロックが作成されたソースコード内の場所を簡単に見つけることができます。その他のヒントは次のとおりです。

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

アプリがフォアグラウンドに表示されていることを確認する

ウェイクロックが有効になっている間、デバイスは電力を消費します。デバイスのユーザーは、この処理が行われていることを認識する必要があります。そのため、wake lock を使用する場合は、ユーザーに通知を表示する必要があります。つまり、フォアグラウンド サービスでウェイクロックを取得して保持する必要があります。通知を表示するには、フォアグラウンド サービスが必要です。

フォアグラウンド サービスがアプリに適していない場合は、ウェイクロックも使用しないでください。アプリがフォアグラウンドにない場合に処理を行うその他の方法については、デバイスをスリープ状態にしない適切な API を選択するをご覧ください。

ロジックをシンプルに保つ

wake lock の取得と解放のロジックが可能な限り単純であることを確認します。wake lock のロジックが、複雑なステートマシン、タイムアウト、エグゼキュータ プール、コールバック イベントに関連付けられている場合、そのロジックにわずかでもバグがあると、wake lock が予想よりも長く保持される可能性があります。このようなバグは、診断とデバッグが困難です。

wake lock が常に解放されることを確認する

wake lock を使用する場合は、取得したすべての wake lock が適切に解放されるようにする必要があります。これが思ったほど簡単とは限りません。たとえば、次のコードには問題があります。

Kotlin

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

Java

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

ここでの問題は、メソッド doTheWork() が例外 MyException をスローする可能性があることです。例外が発生すると、doSomethingAndRelease() メソッドは例外を外側に伝播し、release() 呼び出しに到達することはありません。その結果、ウェイクロックは取得されるものの解放されず、非常に悪い状態になります。

修正されたコードでは、doSomethingAndRelease() は例外がスローされた場合でも必ずウェイクロックを解除します。

Kotlin

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

Java

void doSomethingAndRelease() throws MyException {
    try {
        wakeLock.acquire();
        doTheWork();
    } finally {
        wakeLock.release();
    }
}