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();
}
}