東北TECH道場の参加者向けに作成したハンズオンのその2です。
睡眠導入アプリの続き
その2では、画像を表示したり音声が再生できるようにしました。
このアプリに更に機能を追加していきましょう。
前準備
レイアウトファイルの修正
現状のレイアウトだと、画像とテキストが被ってしまっているため、レイアウトを少し変更します。
activity_main.xmlを開き、Designタブに切り替える
TextViewを上寄せにする
PropertiesからDelete Buttom Constraintをクリックし、Buttom Constraintを無効にします

Buttom Constraintが無効になり、TextViewが画面上部に現れます。

睡眠導入アプリに機能を追加する
例えば、眠るまでに何回羊を数えたか残したい。
アプリを使うシチュエーションを考えてみましょう。
このアプリを使う場所は?
⇒ ベッドや布団の上。
アプリを使う状況は?
⇒ 眠れないとき
眠れなくて、羊が一匹、羊が二匹....と数えているうちにいつの間にか寝ている...はず。
ということは...
このアプリで羊が一匹、羊が二匹と数えるということは画面をタップすること。
その後に寝るということは、画面をタップしなくなる。
画面をタップしなくなるということは、通常の設定ならスマートフォンは画面が消えてスリープ状態になる。
眠るまでに何回羊を数えたかを残すには、このスリープ状態に入る時までに何回数えたかを記録すれば良いのではないだろうか?
スリープ状態に入る時ってアプリで検出出来るの?
⇒ 出来ます。
スリープに入る時はActivityのonPause() が呼び出されます。
試してみましょう。
(端末のスリープに入るまでの時間を確認しておきましょう。若しくは端末のスリープボタンを押すことでもOKです)
スリープから回復してきた時に呼び出される処理を追加する
MainActivity.kt に次のコードを追加します。
override fun onPause() {
    super.onPause()
    Log.i("onPause", "眠るまでの回数=" + sheepCount)
}
追加する場所に気をつけましょう。
Activityの { } で囲まれた中で、且つ onCreate() の { } の外です。
class MainActivity : AppCompatActivity() {
    var sheepCount = 0
    var mp: MediaPlayer? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var greeting = "こんにちは"
        val trialTime = Date()
        val calendar = GregorianCalendar()
        calendar.time = trialTime
        val hour = calendar.get(Calendar.HOUR_OF_DAY)
        if (hour in 1..11) {
            greeting = "おはよう"
        } else if (hour > 15) {
            greeting = "こんばんは"
        }
        greeting += "ねむれませんか?"
        textview.text = greeting
        mp = MediaPlayer.create(applicationContext, R.raw.sheep_cry1)
        rootLayout.setOnClickListener {
            sheepCount++
            val sheepText = "ひつじが$sheepCount 匹"
            textview.text = sheepText
            when(sheepCount % 2) {
                0 -> {
                    imageView1.setImageResource(R.drawable.sheep_1)
                    mp?.start()
                }
                else -> imageView1.setImageResource(R.drawable.sheep_2)
            }
        }
    }
    // ↓ここに追加
    override fun onPause() {
        super.onPause()
        Log.i("onPause", "眠るまでの回数=$sheepCount")
    }
}
入力したら実行してみましょう。
自分でもう眠りそうだと思ったらスリープボタンを押す、若しくはいつの間にか寝て画面をタップしなくなったら端末がスリープ状態になり、この onPause() が呼ばれるはずです。
スリープから回復した時に呼び出される処理を追加する
MainActivity.kt に次のコードを追加します。
override fun onResume() {
    super.onResume()
    textview.text = "前回は$sheepCount 回羊を数えました。"
}
アプリを実行して何回か羊を数えた後にスリープボタンを押してスリープさせて、再びスリープボタンを押して回復した時の表示を確認してみましょう。
ちょっと実験
アプリを一旦終了させて、再び起動します。
次の2つの場合でそれぞれやってみましょう。
- ホームボタンを押した時
- バックボタンを押した時
ホームボタンを押した時は羊を数えた回数が残っていたが、バックボタンを押した時は0に戻っていたのではないでしょうか。
アプリが終了しても値を残す事ができるようにする方法
SharedPreferences というクラスを使うと出来ます。
値を保存する:
MainActivity.kt の onPause() に次のコードを追加します。
override fun onPause() {
    super.onPause()
    Log.i("onPause", "眠るまでの回数=$sheepCount")
    val sp: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) //追加
    sp.edit().putInt("SheepCount", sheepCount).apply()                              //追加
}
値を読み出す:
MainActivity.kt の onResume() に次のコードを追加します。
override fun onResume() {
    super.onResume()
    val sp: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) //追加
    val count = sp.getInt("SheepCount", -1)                                         //追加
    if (count >= 0) {                                                               //追加
        textview.text = "前回は$count 回羊を数えました。"                                 //追加
    }                                                                               //追加
}

