【Android】アラーム機能 ~ 基本編 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2020/07/14/000000

の続き。
長くなったので、分冊。

目次

【1】アラーム種類
 補足1:省エネと精度
 補足2:反復アラーム
【2】アラームのキャンセルするには
【3】複数アラームを設定するには
【番外編1】スリープ解除
【番外編2】バイブレーション機能
【番外編3】日付・時間ダイアログ

【1】アラーム種類

# Method Name 1回or反復 精度 Notes
1 set() 1回 低精度
2 setExact() 1回 高精度
3 setRepeating() 反復 高精度
4 setInexactRepeating() 反復 低精度
5 setAndAllowWhileIdle() 1回 低精度 制限下でDozeモードでも実行
6 setExactAndAllowWhileIdle() 1回 高精度 制限下でDozeモードでも実行
7 setAlarmClock() 1回 高精度 Dozeモードでも実行

補足1:省エネと精度

* 低精度 = 制度を引き換えに、電池の消耗を抑えることができる

Doze モード

* cf. Doze (ドーズ) = 居眠りする
* 省エネ機能

※ setAndAllowWhileIdle() / setExactAndAllowWhileIdle() の制限

*  9 分に 2 回以上アラームを発生させることができない
* 実行時間が10秒以内

補足2:反復アラーム

* setRepeating() / setInexactRepeating() があるけど、
 Doze モードになると使えなくなる
 ⇒ 結局、色々、調べたけど、以下のサイトのように
  setAlarmClock() を使って、鳴らしたら、
  次のアラームを設定する方法がいい気がする

https://banatech.net/blog/view/30

参考文献

公式ページ
https://developer.android.com/training/scheduling/alarms?hl=ja
https://developer.android.com/training/monitoring-device-state/doze-standby?hl=ja
一般サイト
https://akira-watson.com/android/alarmmanager-timer.html
http://www.taosoftware.co.jp/blog/2009/02/alarmmanager.html
https://akira-watson.com/android/setwindow-repeat.html
http://y-anz-m.blogspot.com/2011/03/alarmmanager.html
https://techium.hatenablog.com/entry/2016/04/14/010721
https://qiita.com/hiroaki-dev/items/e3149e0be5bfa52d6a51

【2】アラームのキャンセルするには

* alarmManager.cancel() を使用する

サンプル

// キャンセル
cancelButton.setOnClickListener {
    // キャンセルしたインテントを指定する
    val intent = Intent(
        this,
        AlarmBroadcastReceiver::class.java)
    val pending =
        PendingIntent.getBroadcast(
            this,0,intent,0)

    var alarmManager : AlarmManager =
        getSystemService(ALARM_SERVICE) as AlarmManager
    alarmManager.cancel(pending)
}

【3】複数アラームを設定するには

サンプル

fun setAlarm(
    targetDateTime: Calendar,
    alarmMessage: String?,
    targetRequestCode: Int?,
    targetPendingIntentFlags: Int
) {
    // かぶらないように requestCode を指定する
    val requestCode = targetRequestCode ?: Random().nextInt(Int.MAX_VALUE)

    val intent = Intent(context, AlarmBroadcastReceiver::class.java)
    if (alarmMessage != null) {
        intent.putExtra(Alarm.MESSAGE_FILED, alarmMessage)
    }

    // かぶらない requestCode を設定する
    val pending = PendingIntent.getBroadcast(
        context, requestCode, intent, targetPendingIntentFlags
    )

    when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> {
            var info = AlarmManager.AlarmClockInfo(
                targetDateTime.timeInMillis, null
            )
            alarmManager.setAlarmClock(info, pending)
        }
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT -> {
            alarmManager.setExact(
                AlarmManager.RTC_WAKEUP,
                targetDateTime.timeInMillis,
                pending
            )
        }
        else -> {
            alarmManager.set(
                AlarmManager.RTC_WAKEUP,
                targetDateTime.timeInMillis,
                pending
            )
        }
    }
}

参考文献
https://qiita.com/kumas/items/f21a55117d2a6cafa7c1

【番外編1】スリープ解除

* アラームした時にアプリがスリープ状態や
 アクティブとは限らないので、そのときの対処。

サンプル

@Suppress("DEPRECATION")
private fun setToShowApplication() {
    when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 -> {
            setShowWhenLocked(true)
            setTurnScreenOn(true)
            val keyguardManager =
                getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
            keyguardManager.requestDismissKeyguard(this, null)
        }
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
            this.window.addFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
        }
        else -> {
            this.window.addFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
                        WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
        }
    }
}

参考文献
https://qiita.com/wasnot/items/760bd2eb22c214485900
https://techbooster.org/android/application/4429/

【番外編2】バイブレーション機能

* バイブレーション機能について、調べてみた

公式サイト
https://developer.android.com/reference/kotlin/android/os/Vibrator
https://developer.android.com/reference/android/os/VibrationEffect

サンプル

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xxxx.xxx.xxxxx">
    <!-- ★追加★ -->
    <uses-permission android:name="android.permission.VIBRATE" />
    <application
    ... 略 ...
    </application>
</manifest>

AndroidManifest.kt

import android.content.Intent
import android.os.VibrationEffect
import android.os.Vibrator
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    ... 略 ...

    @Suppress("DEPRECATION")
    fun vibrate(vibrationTime: Long = 300, amplitude: Int = 10) {
        val vibrator =
            getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
        if (Build.VERSION.SDK_INT >= 26) {
            val vibrationEffect =
                VibrationEffect.createOneShot(
                    vibrationTime, amplitude)
            vibrator.vibrate(vibrationEffect);
        } else {
            vibrator.vibrate(vibrationTime);
        }
    }
}

参考文献
https://qiita.com/k-ysd/items/cfc8fc59760f7694ea54
http://android.techblog.jp/archives/7976265.html

【番外編3】日付・時間ダイアログ

以下の関連記事を参照のこと。

ダイアログ表示 ~ 基本編 / 日付・時間ダイアログ ~
https://dk521123.hatenablog.com/entry/2020/07/26/000000

関連記事

アラーム機能 ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/07/14/000000
Androidアプリから端末のアラームを設定する
https://dk521123.hatenablog.com/entry/2018/05/06/234117
ダイアログ表示 ~ 基本編 / アラートダイアログ ~
https://dk521123.hatenablog.com/entry/2013/10/05/214058
ダイアログ表示 ~ 基本編 / 日付・時間ダイアログ ~
https://dk521123.hatenablog.com/entry/2020/07/26/000000
ダイアログ表示 ~ 基本編 / チェックボックスラジオボタン
https://dk521123.hatenablog.com/entry/2013/10/09/001500
音声を再生するには
https://dk521123.hatenablog.com/entry/2020/07/18/000000
Kotlin ~ 基本編 / Enum・列挙型関連 ~
https://dk521123.hatenablog.com/entry/2020/08/10/125112