Lately I have been receiving informations from users about my alarm app not ringing when it should. Finally, one of the users have send me information from build in log, that was really strange:
74. 4:25:0 - StartAlarm received
75. 5:22:15 - AlarmOnScreen create
76. 5:22:15 - Time: 04:25
Problem is, informations to log are saved as follow:
//BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) {
Logger.initialize(context);
Logger.log("StartAlarm received");
Intent i = new Intent(context, AlarmOnScreen.class);
i.putExtras(intent.getExtras());
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
//AlarmOnScreen (activity)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm_on_screen);
Logger.log("AlarmOnScreen create");
//Time value of alarm is logged below
(...)
As you can see, start of the activity was delayed considerably. How is that possible? User raported that alarm was delayed until he started “using” the phone – I guess that means, until lockscreen was unlocked or screen turned on. I am still waiting for answer with more informations. On other time delay was only 5 minutes – every time, until user started “using phone”
Any ideas?
EDIT:
Let me add, that is something that have started happening lately, after application being out for months. I am still looking if I have maybe changed anything in manifest and in last update, but is it possible that it is somthing that happens only on new Android versions?
I think your problem is about using AlarmManager without proper use of WakeLocks, when device “sleeps” with screen turned-off, your receiver will not work properly.
I guess your receiver got onReceive() from AlarmManager, which is most probably was started with
_WAKEUPflag like this:This _WAKEUP flag means that device will “turn-on” even if it will be in a sleep mode.
However, as described by documentation here ( http://developer.android.com/reference/android/app/AlarmManager.html ) :
In your code that means that system goes back to sleep as soon as
onReceive()ends, and asstartActivity(i)doesn’t work synchronously – that leads directly to the problem, mentioned above – it will be launched, but much, much later, just when user will turn the screen on.To solve it, I would recommend doing something like this:
This solution will work for the first time and will let you understand the problem deeper. To test – just start to use your alarms when screen is off and, possibly, cable is plugged-off, but I’m not sure if the last is really needed to get device into sleep mode.
However, I would highly recommend to implement more elegant solution, suitable for your project, because current static-reference design is pretty poor, as it doesn’t work perfectly in racing conditions, for example.
Hope it helps and please let me know if any questions.
Good luck.
UPD:
I think I will also suggest to use not only PARTIAL_WAKE_LOCK, but FULL one. Like:
That will force the screen to be ON anyway, not depending on previous state and platform reaction on new activity creation.