web-dev-qa-db-ja.com

alarmmanagerのsetExactAndAllowWhileIdle()が正しく機能していません

ユーザーが設定した正確な時間に特定のアクションを実行する必要があるアプリを開発しています。このため、私はsetExactAndAllowWhileIdle()メソッドを使用しています このドキュメント は、Android Android 6.0以上のデバイス居眠りモードの概念があり、デバイスがしばらくアイドル状態になると、居眠りモードに入り、居眠りモードがアラームを制限します。デバイスが居眠りモードになっているときにアラームを発生させたい場合は、setExactAndAllowWhileIdle()メソッドを使用しますこのドキュメントには、テスト目的でデバイスを居眠りモードに手動で切り替える方法も含まれています。そのため、この方法を使用してテストしていますが、デバイスが居眠りモードになり、ターミナルコマンドで居眠りモードを停止すると、アラームが発生しませんmy過去のアラームは即座に発生します。

したがって、私の問題は、setExactAndAllowWhileIdle()このメソッドがDozeモードでは機能しないことですが、ドキュメントに記載されているように機能する必要があります。私はこの方法の制限を知っています。私は9分ごとに1つのアラームしか起動できず、このルールに従っています。だから、どこに問題があるのか​​理解できません。

マイコード:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC, d.getTime(), pendingIntent);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop)
    alarmManager.setExact(AlarmManager.RTC, d.getTime(), pendingIntent);
else
    alarmManager.set(AlarmManager.RTC, d.getTime(), pendingIntent);

メソッドの問題ですか、それとも間違った方法で行っていますか?

9
Jaydip Kalkani

私は自分の問題の解決策を見つけたので、自分のために働いた自分の答えをここに投稿します。

setAlarmClock()メソッドを使用すると問題が解決しました。 setAlarmClock()メソッドを使用してアラームを設定した場合、これにより、システムがアラームの1時間前に居眠りモードに入ることができなくなります。アラームを設定した後、デバイスを手動で居眠りモードに強制してこれをテストしました。完全なシナリオを説明しましょう。

  1. まず最初に、現在時刻から5分後にアラームを設定し、次のコマンドを使用して手動でデバイスをDozeモードにしようとしました。

adbシェルdumpsys deviceidle force-idle

それが示している

居眠りモードに入ることができません

  1. その後、現在の時刻から1時間1分後にアラームを設定し、デバイスをDozeモードにしようとしましたが、Dozeモードになりました。それから私は自分のデバイスで何もしていません、それはそれが居眠りモードであったとしても、時間通りにアラームを発します。

したがって、現在の時刻とアラーム時刻の間に少しのタイムスタンプがある場合、setAlarmClock()メソッドはデバイスがDozeモードに入るのを防ぐと結論付けます。それ以外の場合、デバイスが既にDozeモードになっていると、アラームが発生する前にDozeモードが解除されるため、アラームは正常に機能します。

更新されたコード:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(d.getTime(),pendingIntent),pendingIntent);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop)
    alarmManager.setExact(AlarmManager.RTC, d.getTime(), pendingIntent);
else
    alarmManager.set(AlarmManager.RTC, d.getTime(), pendingIntent);
11
Jaydip Kalkani

バッテリーの最適化を無視することで、居眠りモードからアプリをホワイトリストに登録できます。

権限を追加

<uses-permission 
Android:name="Android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

アプリのホワイトリストをリクエストする

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Intent intent = new Intent();
            String packageName = getPackageName();
            PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
            if (!pm.isIgnoringBatteryOptimizations(packageName)) {
                intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + packageName));
                startActivity(intent);
            }
        }

注:setAndAllowWhileIdle()もsetExactAndAllowWhileIdle()も、アプリごとに15分ごとに複数回アラームを発生させることはできません。

2
MarGin

ドキュメントによると

RTC-指定された時間に保留中のインテントを起動しますが、デバイスをウェイクアップしません。

RTC_WAKEUP-デバイスをウェイクアップして、指定された時間に保留中のインテントを起動します。

使用する AlarmManager.RTC_WAKEUP の代わりに AlarmManager.RTC

1
android_hub

@MarGinの回答への追加。
ユーザーがすべてを1つのダイアログで行う方がはるかに簡単ですが、これはGoogle Playのポリシーに違反しています

if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
    startActivity(
        Intent(
            Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
            Uri.parse("package:$packageName")
        )
    )
}
0
Vlad