Search code examples
androidalarmmanager

Android Alarmmanager Notifications Not Appearing After Long Idle Periods


I have been trying to fix this problem for weeks. The basic problem is that after a device has been left alone for a long period of time (8 hours) the scheduled notification will not activate. In testing I have been using two devices, An LG Optimus Elite and a Samsung Galaxy Note S4. On the Optimus Elite the Notification will happen when the device is woken up but on the Note the Notification disappears entirely and is never displayed. The whole system works while the device is awake or after a brief period of inactivity.

public class AlarmReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    try {
        WakeLocker.acquire(context);
        Bundle bundle = intent.getExtras();
        Intent i = new Intent(context, AlarmService.class);
        i.putExtra("name", bundle.getString("name"));
        i.putExtra("alarm", bundle.getString("alarm"));
        context.startService(i);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

**public class AlarmService extends Service {

LocalBroadcastManager broadcaster;
static final public String REFRESH_INTENT = "rf";

@Override
public IBinder onBind(Intent arg0)
{
    // TODO Auto-generated method stub
    return null;
}

public void handleIntent(Intent intent){
    broadcaster = LocalBroadcastManager.getInstance(this);
    Bundle bundle = intent.getExtras();
    String message = bundle.getString("alarm");
    if(message.equals("dosesTakenResetAlarm")){
        dailyReset(getApplicationContext());
    }
    else if(message.equals("scheduledReminder")){
        scheduledReminder(bundle.getInt("code", 0), bundle.getString("name"), getApplicationContext());
    }
    WakeLocker.release();
}

public void onStart(Intent intent, int startId){
    handleIntent(intent);
}

public int onStartCommand(Intent intent, int flags, int startId){
    handleIntent(intent);
    return START_NOT_STICKY;
}

@Override
public void onDestroy()
{
    // TODO Auto-generated method stub
    super.onDestroy();
    WakeLocker.release();
}

private void dailyReset(Context context){
    FileWriter fw = new FileWriter(context);
    AlarmCreator ac = new AlarmCreator();
    fw.fp.onloadString(fw.readFromFile());
    int medNum = 0;
    while(fw.fp.hasNext()){
        SaveData mv = fw.readEntry(medNum);
        fw.fp.onloadMedString(mv.data);
        String name = fw.fp.nextMedVariable();
        String doses = fw.fp.nextMedVariable();
        String frequency = fw.fp.nextMedVariable();
        String frequencyS = fw.fp.nextMedVariable();
        String reminders = fw.fp.nextMedVariable();
        String dosesT = fw.fp.nextMedVariable();
        frequencyS = ""+(Integer.parseInt(frequencyS)-1);
        if(Integer.parseInt(frequencyS) < 0){
            frequencyS = ""+(Integer.parseInt(frequency)-1);
        }
        fw.replaceEntry(fw.fp.buildMedSaveString(name, doses, frequency, frequencyS, reminders, "0"), mv.position1, mv.position2);
        if(frequencyS.equals("0")){
            fw.fp.onloadReminderString(reminders);
            int reminderNum = 0;
            while(fw.fp.hasNextReminder()){
                ReminderData temp = fw.fp.nextReminder();
                if(temp.half.equals("1")){
                    temp.hour = ""+(Integer.parseInt(temp.hour)+12);
                }
                ac.setAlarm(Integer.parseInt(temp.hour), Integer.parseInt(temp.minute), 0, ac.buildAlarmCode(medNum, reminderNum), name);
                reminderNum++;
            }
        }
        medNum++;
        fw.fp.nextMedication();
    }

    Intent intent = new Intent(REFRESH_INTENT);
    broadcaster.sendBroadcast(intent);
}

private void scheduledReminder(int code, String n, Context context){
    Intent intent = new Intent(context, Main.class);
    PendingIntent pIntent = PendingIntent.getActivity(context, 101, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(context)
                    .setSmallIcon(R.drawable.deleted)
                    .setContentTitle("Pillbud Reminder")
                    .setContentText("Take a dosage of "+n+".");
    mBuilder.setDefaults(Notification.DEFAULT_ALL);
    mBuilder.setContentIntent(pIntent);
    mBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
    NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    mNotifyMgr.notify(code, mBuilder.build());
}

}**

Also if anyone has any suggestions about how to induce this sleep state it would be very helpful for testing.


Solution

  • You'll need to grab a WakeLock. Have a look at either the WakefulBroadcastReceiver, or CommonsWare Guy's WakefulIntentService

    As for putting the device to sleep, if you have root, then adb shell into it, get root and enter:

      echo standby > /sys/power/state
    

    There is more information on power states here

    If you do not have root, there the call on the PowerManager, goToSleep, that should do it. You'll need to grant the calling app DEVICE_POWER permission