I think your problem is using AlarmManager without using WakeLocks properly, when the device is sleeping with the screen off, your receiver will not work properly.
I think your receiver got onReceive () from AlarmManager, which most likely was launched with the _WAKEUP flag as follows:
mAlarmManager.set(AlarmManager.RTC_WAKEUP, .......);
This _WAKEUP flag means that the device will be "turned on" even if it is in sleep mode. However, as described in the documentation here ( http://developer.android.com/reference/android/app/AlarmManager.html ):
The alarm manager contains a processor monitoring lock while the onReceive () alarm receiver is running. This ensures that the phone will not sleep until you finish working with the broadcast. When the onReceive () function returns, the alarm manager releases this lock. This means that the phone will sleep in some cases as soon as your onReceive () method is complete. If your alarm receiver is called Context.startService (), it is possible that the phone will sleep before the requested service starts. To prevent this from happening, your BroadcastReceiver and service will need to implement a separate tracking blocking policy to make sure that the phone continues to work until the service becomes available.
In your code, this means that the system goes back to sleep as soon as onReceive() finishes, and as startActivity(i) does not work synchronously - this leads directly to the problem mentioned above - it will start, but a lot, much later when the user turns on the screen.
To solve this problem, I would recommend doing something like this:
//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.acquireLock(context); //Before, system could sleep right after this line(not exactly, however) and activity actually would be started much later } //AlarmOnScreen (activity) private static WakeLock sWakeLock; public static void acquireLock(Context context) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "providersLock"); //Limit 10 sec, if something wrong will happen - we'll not drain the battery to much. sWakeLock.acquire(10000); //As we are acquiring and releasing only once - we don't need a counter. sWakeLock.setReferenceCounted(false); } private static void releaseLock(Context context) { try { sWakeLock.release(); } catch (Exception e) { //In case it already auto-released e.printStackTrace(); } } @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 (...) @Override protected void onResume() { releaseLock(this); }
This solution will work for the first time and will allow you to better understand the problem. To check - just start using your alarms when the screen is off and maybe the cable is connected, but I'm not sure that the latter is really necessary to put the device into sleep mode.
However, I would strongly recommend implementing a more elegant solution suitable for your project, because the current static reference design is pretty bad, as it does not work perfectly in racing conditions, for example.
Hope this helps, and please let me know if you have any questions. Good luck.
UPD: I think I also suggest using not only PARTIAL_WAKE_LOCK, but also FULL. How:
pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "providersLock");
This will cause the screen to be turned on in any case, not depending on the previous state and platform reaction when creating a new activity.