警报管理器有时会在错误的时间触发
alarm manager sometimes firing at wrong times
我正在制作一个每天在不同时间有 5 个不同通知的应用。它工作完美,但在 Beta 测试后,一些用户抱怨某些警报在错误的时间再次触发我以前没有遇到过这个问题,我不知道如何跟踪问题所以我可以解决它。这就是我创建警报的方式:
Manager Class:(具有报警的所有功能)
public static Integer DEFAULT_SILENT_DURATION = 20 * 60 * 1000;
public static Integer DEFAULT_SILENT_START= 2 * 60 * 1000;
public Manager(Context applicationContext) {
this.context = applicationContext;
}
public static void acquireScreen(Context context) {
PowerManager pm = (PowerManager) context.getApplicationContext()
.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm
.newWakeLock(
(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP),
"TAG");
wakeLock.acquire();
Log.v("Check Manager acquireScreen","YES");
}
public static void releaseScreen(Context context) {
KeyguardManager keyguardManager = (KeyguardManager) context
.getApplicationContext().getSystemService(
Context.KEYGUARD_SERVICE);
KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
keyguardLock.disableKeyguard();
Log.v("Check Manager releaseScreen","YES");
}
public static void initPrayerAlarm(Service service,
Class<PrayerReceiver> receiver) {
Manager.prayerService = service; // we may need it ?
Manager.prayerIntet = new Intent(service, receiver);
Manager.prayerPendingIntent = PendingIntent
.getBroadcast(service, 1234432, Manager.prayerIntet,
PendingIntent.FLAG_UPDATE_CURRENT);
Manager.prayerAlarmManager = (AlarmManager) service
.getSystemService(Context.ALARM_SERVICE);
Manager.prayerAlarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 1000, Manager.prayerPendingIntent);
Log.v("Check Manager initPrayerAlarm",""+System.currentTimeMillis() + 1000);
}
public static void updatePrayerAlarm(long newTimeInterval) {
Manager.prayerAlarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + newTimeInterval,
Manager.prayerPendingIntent);
Log.v("Check Manager updatePrayerAlarm",""+System.currentTimeMillis() + newTimeInterval);
}
public void restartPrayerService(Activity activty) {
Intent intent = new Intent(activty, PrayerService.class);
context.startService(intent);
Log.v("Check Manager restartPrayerService","YES");
}
- 在我的 MainActivity 中调用管理器
restartPrayerService
函数
- 在PrayerService中我调用如下:
Manager.initPrayerState(this);
Manager.initPrayerAlarm(this, PrayerReceiver.class);
然后注册接收者。
祈祷者:
public class PrayerReceiver extends BroadcastReceiver {
static PrayerState prayerState;
private AudioManager am;
private Context context;
private SharedPreferences pref;
private Editor editor;
private int silentDuration;
private int silentStart ;
private int delayMilliSeconds = 1000 * 60; // one minute by default.
private Object obj;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
pref = PreferenceManager.getDefaultSharedPreferences(this.context);
Manager m = new Manager(context);
Preference p = m.getPreference();
this.silentDuration = p.getSilentDuration();
this.silentStart = p.getSilentStart();
editor = pref.edit();
try {
prayerState = Manager.getPrayerState();
am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
switch (prayerState.getCurrentState()) {
case PrayerState.WAITING_AZAN:
{
Log.v("Check PrayerReceiver PrayerState","WAITING_AZAN");
onWaitingAzan();
}
break;
case PrayerState.DOING_AZAN:
{
Log.v("Check PrayerReceiver PrayerState","DOING_AZAN");
onDoingAzan();
}
break;
case PrayerState.WAITING_PRAYER:
{
Log.v("Check PrayerReceiver PrayerState","WAITING_PRAYER");
onWaitingPrayer();
}
break;
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.v("Check PrayerReceiver PrayerState","ERROR");
}
}
public int getDelayMilliSeconds() {
return delayMilliSeconds;
}
public void setDelayMilliSeconds(int delayMilliSeconds) {
this.delayMilliSeconds = delayMilliSeconds;
}
private void onWaitingAzan() {
try {
boolean isRingerModeChangedToSilent = pref.getBoolean(
"isRingerModeChangedToSilent", false);
if (isRingerModeChangedToSilent == true) {
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
editor.putBoolean("isRingerModeChangedToSilent", false);
editor.commit();
}
// What is the remaining time until the next prayer ?
Date date = new Date();
int dd = date.getDate();
int mm = date.getMonth() + 1;
int yy = date.getYear() + 1900;
int h = date.getHours();
int m = date.getMinutes();
int s = date.getSeconds();
int nearestPrayerTime = Manager.computeNearestPrayerTime(context,
h, m, s, yy, mm, dd);
int deffTime = TimeHelper.different((h * 3600 + m * 60 + s),
nearestPrayerTime);
deffTime = deffTime * 1000; // to milliseconds
// ok , come back after X seconds to do the Azan
prayerState.setNextState(PrayerState.DOING_AZAN);
Manager.updatePrayerAlarm(deffTime);
} catch (Exception e) {
Log.v("Check PrayerReceiver onWaitingAzan","ERROR");
}
}
private void onDoingAzan() {
prayerState.setNextState(PrayerState.WAITING_PRAYER);
int delay = this.silentStart;
if(delay < 2000*60)
delay =2000*60; // two minutes - at lease
Log.v("Check PrayerReceiver onDoingAzan","delay "+delay);
Manager.playAzanNotification(context);
Manager.updatePrayerAlarm(delay);
}
private void onWaitingPrayer() {
Manager manager = new Manager(this.context);
Preference preference = manager.getPreference();
AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
if(am.getRingerMode() == AudioManager.RINGER_MODE_NORMAL && preference.isAutoSilentDisabled()==false ){
am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
editor.putBoolean("isRingerModeChangedToSilent", true);
editor.commit();
}
this.delayMilliSeconds = silentDuration;
prayerState.setNextState(PrayerState.WAITING_AZAN);
Manager.updatePrayerAlarm(delayMilliSeconds);
}
谁能帮帮我,到底我做错了什么?
Manager.prayerAlarmManager.set
未在 api 19 及以上的指定时间准确设置。这可能就是 "some" 用户抱怨的原因。
Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.
在 api 19 岁及以上,您需要 setExact
安排在特定时间
您将需要这样的东西:
if(android.os.Build.VERSION.SDK_INT >= 19) {
// setExact
}
else {
//set
}
我正在制作一个每天在不同时间有 5 个不同通知的应用。它工作完美,但在 Beta 测试后,一些用户抱怨某些警报在错误的时间再次触发我以前没有遇到过这个问题,我不知道如何跟踪问题所以我可以解决它。这就是我创建警报的方式:
Manager Class:(具有报警的所有功能)
public static Integer DEFAULT_SILENT_DURATION = 20 * 60 * 1000;
public static Integer DEFAULT_SILENT_START= 2 * 60 * 1000;
public Manager(Context applicationContext) {
this.context = applicationContext;
}
public static void acquireScreen(Context context) {
PowerManager pm = (PowerManager) context.getApplicationContext()
.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm
.newWakeLock(
(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP),
"TAG");
wakeLock.acquire();
Log.v("Check Manager acquireScreen","YES");
}
public static void releaseScreen(Context context) {
KeyguardManager keyguardManager = (KeyguardManager) context
.getApplicationContext().getSystemService(
Context.KEYGUARD_SERVICE);
KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
keyguardLock.disableKeyguard();
Log.v("Check Manager releaseScreen","YES");
}
public static void initPrayerAlarm(Service service,
Class<PrayerReceiver> receiver) {
Manager.prayerService = service; // we may need it ?
Manager.prayerIntet = new Intent(service, receiver);
Manager.prayerPendingIntent = PendingIntent
.getBroadcast(service, 1234432, Manager.prayerIntet,
PendingIntent.FLAG_UPDATE_CURRENT);
Manager.prayerAlarmManager = (AlarmManager) service
.getSystemService(Context.ALARM_SERVICE);
Manager.prayerAlarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 1000, Manager.prayerPendingIntent);
Log.v("Check Manager initPrayerAlarm",""+System.currentTimeMillis() + 1000);
}
public static void updatePrayerAlarm(long newTimeInterval) {
Manager.prayerAlarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + newTimeInterval,
Manager.prayerPendingIntent);
Log.v("Check Manager updatePrayerAlarm",""+System.currentTimeMillis() + newTimeInterval);
}
public void restartPrayerService(Activity activty) {
Intent intent = new Intent(activty, PrayerService.class);
context.startService(intent);
Log.v("Check Manager restartPrayerService","YES");
}
- 在我的 MainActivity 中调用管理器
restartPrayerService
函数 - 在PrayerService中我调用如下:
Manager.initPrayerState(this);
Manager.initPrayerAlarm(this, PrayerReceiver.class);
然后注册接收者。
祈祷者:
public class PrayerReceiver extends BroadcastReceiver {
static PrayerState prayerState;
private AudioManager am;
private Context context;
private SharedPreferences pref;
private Editor editor;
private int silentDuration;
private int silentStart ;
private int delayMilliSeconds = 1000 * 60; // one minute by default.
private Object obj;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
pref = PreferenceManager.getDefaultSharedPreferences(this.context);
Manager m = new Manager(context);
Preference p = m.getPreference();
this.silentDuration = p.getSilentDuration();
this.silentStart = p.getSilentStart();
editor = pref.edit();
try {
prayerState = Manager.getPrayerState();
am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
switch (prayerState.getCurrentState()) {
case PrayerState.WAITING_AZAN:
{
Log.v("Check PrayerReceiver PrayerState","WAITING_AZAN");
onWaitingAzan();
}
break;
case PrayerState.DOING_AZAN:
{
Log.v("Check PrayerReceiver PrayerState","DOING_AZAN");
onDoingAzan();
}
break;
case PrayerState.WAITING_PRAYER:
{
Log.v("Check PrayerReceiver PrayerState","WAITING_PRAYER");
onWaitingPrayer();
}
break;
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.v("Check PrayerReceiver PrayerState","ERROR");
}
}
public int getDelayMilliSeconds() {
return delayMilliSeconds;
}
public void setDelayMilliSeconds(int delayMilliSeconds) {
this.delayMilliSeconds = delayMilliSeconds;
}
private void onWaitingAzan() {
try {
boolean isRingerModeChangedToSilent = pref.getBoolean(
"isRingerModeChangedToSilent", false);
if (isRingerModeChangedToSilent == true) {
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
editor.putBoolean("isRingerModeChangedToSilent", false);
editor.commit();
}
// What is the remaining time until the next prayer ?
Date date = new Date();
int dd = date.getDate();
int mm = date.getMonth() + 1;
int yy = date.getYear() + 1900;
int h = date.getHours();
int m = date.getMinutes();
int s = date.getSeconds();
int nearestPrayerTime = Manager.computeNearestPrayerTime(context,
h, m, s, yy, mm, dd);
int deffTime = TimeHelper.different((h * 3600 + m * 60 + s),
nearestPrayerTime);
deffTime = deffTime * 1000; // to milliseconds
// ok , come back after X seconds to do the Azan
prayerState.setNextState(PrayerState.DOING_AZAN);
Manager.updatePrayerAlarm(deffTime);
} catch (Exception e) {
Log.v("Check PrayerReceiver onWaitingAzan","ERROR");
}
}
private void onDoingAzan() {
prayerState.setNextState(PrayerState.WAITING_PRAYER);
int delay = this.silentStart;
if(delay < 2000*60)
delay =2000*60; // two minutes - at lease
Log.v("Check PrayerReceiver onDoingAzan","delay "+delay);
Manager.playAzanNotification(context);
Manager.updatePrayerAlarm(delay);
}
private void onWaitingPrayer() {
Manager manager = new Manager(this.context);
Preference preference = manager.getPreference();
AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
if(am.getRingerMode() == AudioManager.RINGER_MODE_NORMAL && preference.isAutoSilentDisabled()==false ){
am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
editor.putBoolean("isRingerModeChangedToSilent", true);
editor.commit();
}
this.delayMilliSeconds = silentDuration;
prayerState.setNextState(PrayerState.WAITING_AZAN);
Manager.updatePrayerAlarm(delayMilliSeconds);
}
谁能帮帮我,到底我做错了什么?
Manager.prayerAlarmManager.set
未在 api 19 及以上的指定时间准确设置。这可能就是 "some" 用户抱怨的原因。
Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.
在 api 19 岁及以上,您需要 setExact
安排在特定时间
您将需要这样的东西:
if(android.os.Build.VERSION.SDK_INT >= 19) {
// setExact
}
else {
//set
}