ユーザーが設定した正確な時間に特定のアクションを実行する必要があるアプリを開発しています。このため、私は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);
メソッドの問題ですか、それとも間違った方法で行っていますか?
私は自分の問題の解決策を見つけたので、自分のために働いた自分の答えをここに投稿します。
setAlarmClock()メソッドを使用すると問題が解決しました。 setAlarmClock()メソッドを使用してアラームを設定した場合、これにより、システムがアラームの1時間前に居眠りモードに入ることができなくなります。アラームを設定した後、デバイスを手動で居眠りモードに強制してこれをテストしました。完全なシナリオを説明しましょう。
adbシェルdumpsys deviceidle force-idle
それが示している
居眠りモードに入ることができません
したがって、現在の時刻とアラーム時刻の間に少しのタイムスタンプがある場合、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);
バッテリーの最適化を無視することで、居眠りモードからアプリをホワイトリストに登録できます。
権限を追加
<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分ごとに複数回アラームを発生させることはできません。
ドキュメントによると
RTC-指定された時間に保留中のインテントを起動しますが、デバイスをウェイクアップしません。
RTC_WAKEUP-デバイスをウェイクアップして、指定された時間に保留中のインテントを起動します。
使用する AlarmManager.RTC_WAKEUP
の代わりに AlarmManager.RTC
@MarGinの回答への追加。
ユーザーがすべてを1つのダイアログで行う方がはるかに簡単ですが、これはGoogle Playのポリシーに違反しています
if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
startActivity(
Intent(
Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
Uri.parse("package:$packageName")
)
)
}