wake lock を使用すると、デバイスのパフォーマンスが低下する可能性があります。wake lock を使用する必要がある場合は、適切に使用することが重要です。このドキュメントでは、一般的な wake lock の落とし穴を回避するのに役立つベスト プラクティスについて説明します。
wake lock に適切な名前を付ける
wake lock タグにパッケージ名、クラス名、またはメソッド名を含めることをおすすめします。そうすることで、エラーが発生した場合に、wake lock が作成されたソースコード内の場所を簡単に見つけることができます。その他のヒントは次のとおりです。
- 名前にメールアドレスなどの個人を特定できる情報(PII)を含めないようにします。デバイスが wake lock タグで PII を検出すると、指定したタグではなく
_UNKNOWNがログに記録されます。 getName()の呼び出しなどによって、クラス名やメソッド名をプログラムで取得しないでください。プログラムで名前を取得しようとすると、Proguard などのツールによって難読化される可能性があります。代わりに、ハードコードされた文字列を使用します。- wake lock タグにカウンタまたは一意の識別子を追加しないでください。wake lock を作成するコードは、実行するたびに同じタグを使用する必要があります。 この方法により、システムは各メソッドの wake lock の使用状況を集計できます。
アプリがフォアグラウンドに表示されるようにする
wake lock がアクティブな間、デバイスは電力を消費しています。デバイスのユーザーは、このことを認識している必要があります。そのため、wake lock を使用している場合は、ユーザーに通知を表示する必要があります。 実際には、 フォアグラウンド サービスで 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() 呼び出しに到達しません。その結果、wake lock は取得されますが解放されず、非常に悪い状態になります。
修正されたコードでは、例外がスローされた場合でも doSomethingAndRelease() が wake lock を解放します。
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();
}
}