スクリーンロック解除を検知できるようになるまでの道のり(Android版)


Android初心者がスクリーンロックの解除を検知できるようになるまでの道のりを簡単にメモしておきます。
ググると色々とやり方が出てくるのですが、一番わかりやすかった方法を。
以前にiOSでやったときは一筋縄ではいかなくて色々大変だったのですが、Androidはその辺わかりやすくていいですね。

はじめに

ざっくりいうと、スクリーンロックを解除(とか画面のON/OFFとか)されたときに送られるintentをBroadcastReceiverで受け取ってよしなに処理する、という流れです。

BroacastReceiverの準備

まずはBroadcastReceiverクラスを作成します。AndroidStudioのメニューから追加すれば簡単。
とりあえずBackgroundBroadcastReceiverというファイル名で作って、onReceiveメソッドをoverrideします。
受け取ったintentによって処理を変えます。
スクリーンロック関係で言うと、
- ACTION_SCREEN_ON: 画面点灯したとき
- ACTION_SCREEN_OFF: 画面が消えた時
- ACTION_USER_PRESENT: スクリーンロックが解除されたとき
でいけそうです。

BackgroundBroadcastReceiver.kt

class BackgroundBroadcastReceiver: BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        // This method is called when the BroadcastReceiver is receiving an Intent broadcast.
        //TODO("backgroundBroadcastReceiver.onReceive() is not implemented")
        var action: String? = intent.getAction()
        if(action.equals(Intent.ACTION_SCREEN_ON)){
            //画面ON時の処理

        }else if(action.equals(Intent.ACTION_SCREEN_OFF)){
            //画面OFF時の処理

        }else if(action.equals(Intent.ACTION_USER_PRESENT)){
            //スクリーンロック解除時の処理

        }
    }
}

BroadcastReceiverの登録

次に、MainActivityなり、自作クラスなりでBroadcastReceiverを登録します。
ここでは、onCreate()時に登録してしまっています。
それぞれのintent毎にレシーバを登録するイメージですかね。

xxxxxx.kt

    var bbr: BackgroundBroadcastReceiver = BackgroundBroadcastReceiver()

    override fun onCreate() {
        super.onCreate()

        //レシーバーの登録
        registerReceiver(bbr, IntentFilter(Intent.ACTION_SCREEN_ON))
        registerReceiver(bbr, IntentFilter(Intent.ACTION_SCREEN_OFF))
        registerReceiver(bbr, IntentFilter(Intent.ACTION_USER_PRESENT))
    }

これで、とりあえずスクリーンロックを検知して処理をすることができました?
…といけばよかったのですが、これだけだと例えば、ACTION_SCREEN_OFFを受け取ったときにxxxxx.kt上で何かをする、というのができません。
ということで、自作リスナーを作ってその辺の処理をすることにします。
イメージとしては、スクリーンロック関係のintentを受け取ると自作リスナーのメソッドを呼ぶことにして、xxxxxx.ktからはこのリスナーを使って処理をする、という感じです。

リスナーの準備

今回は、BackgroundBroadcastReceiverListener.ktという名前でリスナーを自作しました。

BackgroundBroadcastReceiverListener.kt
interface BackgroundBroadcastReceiverListener {
    fun onScreenOn()
    fun onScreenOff()
    fun onUserPresent()
}

Listenerを使う

まずはBackgroundBroadcastReceiver.ktにコンストラクタと初期化ブロックを追加し、intentを受け取ったらリスナーのメソッドを呼ぶようにします。

BackgroundBroadcastReceiver.kt

class BackgroundBroadcastReceiver constructor(_listener: BackgroundBroadcastReceiverListener): BroadcastReceiver() {

    private lateinit var listener: BackgroundBroadcastReceiverListener

    init{
        listener = _listener
    }

    override fun onReceive(context: Context, intent: Intent) {
        // This method is called when the BroadcastReceiver is receiving an Intent broadcast.
        //TODO("backgroundBroadcastReceiver.onReceive() is not implemented")
        var action: String? = intent.getAction()
        if(action.equals(Intent.ACTION_SCREEN_ON)){
            listener.onScreenOn()

        }else if(action.equals(Intent.ACTION_SCREEN_OFF)){
            listener.onScreenOff()

        }else if(action.equals(Intent.ACTION_USER_PRESENT)){
            listener.onUserPresent()
        }
    }
}

xxxxxx.ktではリスナーを継承して、リスナーのメソッドをoverrideします。

xxxxxx.kt
class BackgroundService: BackgroundBroadcastReceiverListener {

    //thisを追加
    var bbr: BackgroundBroadcastReceiver = BackgroundBroadcastReceiver(this)

    override fun onCreate() {
        super.onCreate()
        //レシーバーの登録
        registerReceiver(bbr, IntentFilter(Intent.ACTION_SCREEN_ON))
        registerReceiver(bbr, IntentFilter(Intent.ACTION_SCREEN_OFF))
        registerReceiver(bbr, IntentFilter(Intent.ACTION_USER_PRESENT))
    }

    //BackgroundBroadcastReceiverListener用のメソッド
    override fun onScreenOn() {
        //画面ON時の処理
    }

    override fun onScreenOff() {
        //画面OFF時の処理

    }

    override fun onUserPresent() {
        //スクリーンロック解除時の処理
    }
}

これでようやくxxxxxx.ktでスクリーンロック解除周りを処理できるようになりました!
BroadcastReceiverのその他のintentを使った処理も同じようにできるはず!?