Search code examples
javaandroidandroid-intentbroadcastreceiverandroid-broadcast

Why BroadcastReceiver is initializing on past time?


I am making an app which:

  1. Inputs from user a time range... (Initial time, Final time) suppose user gives (06:00 PM To 07:00 PM)
  2. When current time of the phone equals initial time then silent mode of the phone activates.

Everything working fine if the time range is of future (if my phone time is before 05:00PM in above case):

  1. Lets say My Phone current phone time is 08:00 PM and I have made time range from (06:00 PM To 07:00 PM). Then silent mode of the phone activates at my current time (08:00 PM). It should activate next day...

I have made a service for this...

Whenever user enters range of time it starts a service onStart and onStartCommand are overridden...

public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);

    ArrayList<HashMap<String, String>> arraylist_start = (ArrayList<HashMap<String, String>>) intent.getSerializableExtra("arraylist_start");

    if(arraylist_start != null){
        try {
            silentModeOnBroadCastReceiver.startAlarmAt(this, arraylist_start);
            silentModeOffBroadCastReceiver.startAlarmOff(this, arraylist_start);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

In arraylist_start i am taking list of time ranges from intent where user added time ranges... Same code is written in onStartCommand

In SilentModeOnBroadCastReceiver I have added startAlarmAt method which takes that ArrayList and calls pending intent

public void startAlarmAt(Context context, ArrayList<HashMap<String, String>> list) throws ParseException {
    Calendar calendar = Calendar.getInstance();
    for (int j = 0; j < list.size(); j++ ){
        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");


        String timeStart = list.get(j).get("timeStart");
        date1 = Calendar.getInstance();
        date2 = Calendar.getInstance();

        date1.setTime(dateFormat.parse(timeStart));
        Log.i("Date1Time", date1.toString());

        int hours = date1.get(Calendar.HOUR_OF_DAY);
        int minutes = date1.get(Calendar.MINUTE);

        calendar.set(Calendar.HOUR_OF_DAY, hours);
        calendar.set(Calendar.MINUTE, minutes);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, SilentModeOnBroadCastReceiver.class);
        PendingIntent pi = PendingIntent.getBroadcast(context, j, i, PendingIntent.FLAG_UPDATE_CURRENT);
        am.setRepeating(AlarmManager.RTC_WAKEUP, date1.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
    }
}

Now in SilentModeOnBroadCastReceiver

public void onReceive(Context context, Intent intent)
{
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
    wl.acquire();


    // Put here YOUR code.
    Toast.makeText(context, "Silent Activated !!!!!!!!!!", Toast.LENGTH_LONG).show();
    Silent silent = new Silent(context);

    silent.activateAudioMode(AudioManager.RINGER_MODE_SILENT);

    wl.release();
}

Please help fix my problem... Why BroadcastReceiver is initializing on past time?


Solution

  • The reason for this behavior is that Android does not call it to the exact time (except you set some special flags). Android is doing that to improve the battery usage. This results that Android tries to invoke that alarm listeners as soon as possible for the given set of properties. Since your time window is up Android is late to invoke it so it does it best and calls it almost directly.

    So just check if the window is in the past and if so add one day for the first call. I'm doing that in my app too, and it works fine.

    You can add one day with this simple call:

    if(calendar.before(GregorianCalendar.getInstance())) {
       calendar.add(Calendar.DAY_OF_MONTH, 1);
    }