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

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

wake lock に適切な名前を付ける

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

  • 名前にメールアドレスなどの個人を特定できる情報(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();
    }
}