Pooja Singh
Pooja Singh

Reputation: 121

Calendar object time mismatch with Android phone time

I've built one small reminder app demo, where user fill some details and get notified. When I set the notification time, after current time to 5 minutes later like if current time is 14:55, then I'm setting 15:00 with current date. Now, notification is coming perfectly on time, when I do nothing and simply wait for 5 minutes to over.

But, when I manually go to my Android phone, and set time to 4 minutes later (14:59) and after wait for 1 minutes, notification is not coming. Why?

Code: Manifest:

<application
...

 <receiver android:name=".Receiver.AlarmReceiver">
            <intent-filter>

                <action android:name="android.intent.action.TIME_SET" />
            </intent-filter>
        </receiver>

        <receiver android:name=".Receiver.BootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />

                <action android:name="android.intent.action.TIME_SET" />
            </intent-filter>
        </receiver>

    </application>

AlarmReceiver

    public void setAlarm(Context context, Calendar calendar, int ID) {
        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

        // Put Reminder ID in Intent Extra
        Intent intent = new Intent(context, AlarmReceiver.class);
        intent.putExtra(REMINDER_ID, Integer.toString(ID));
        mPendingIntent = PendingIntent.getBroadcast(context, ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        /*mPendingIntent = PendingIntent.getBroadcast(context, requestCode, new Intent(context, AlarmReceiver.class),
                PendingIntent.FLAG_NO_CREATE);
        isAlarmSet = (mPendingIntent != null);
        if (isAlarmSet) {
            showLog("isAlarmSet: " + isAlarmSet);
        } else {
            showLog("isAlarmSet: " + isAlarmSet);
        }*/

        // Calculate notification time
        Calendar c = Calendar.getInstance();
        long currentTime = c.getTimeInMillis();
        long diffTime = calendar.getTimeInMillis() - currentTime;

        // Start alarm using notification time
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME,
                SystemClock.elapsedRealtime() + diffTime,
                mPendingIntent);

        // Restart alarm if device is rebooted
        ComponentName receiver = new ComponentName(context, BootReceiver.class);
        PackageManager pm = context.getPackageManager();
        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }


    public void cancelAlarm(Context context, int ID) {
        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

        // Cancel Alarm using Reminder ID
        mPendingIntent = PendingIntent.getBroadcast(context, ID, new Intent(context, AlarmReceiver.class), 0);
        mAlarmManager.cancel(mPendingIntent);

        // Disable alarm
        ComponentName receiver = new ComponentName(context, BootReceiver.class);
        PackageManager pm = context.getPackageManager();
        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }

    private void showLog(String msg) {
        Log.d(TAG, msg);
    }
}

AddReminderActivity:

private void setReminderAlarm(int id) {
        String mDate = tvDueDate.getText().toString();
        if (mDate.equals("")) {
            mDate = CommonUtils.getDate();
        }
        String mTime = tvAlarmTime.getText().toString();

        String[] mDateSplit = mDate.split("-");
        String[] mTimeSplit = mTime.split(":");

        mDay = Integer.parseInt(mDateSplit[2]);
        mMonth = Integer.parseInt(mDateSplit[1]) - 1;
        mYear = Integer.parseInt(mDateSplit[0]);
        mHour = Integer.parseInt(mTimeSplit[0]);
        mMinute = Integer.parseInt(mTimeSplit[1]);


        // Check repeat type
        long mRepeatTime = 0;

        // Create a new notification
        int day = mDay - notificationDay;

            mCalendar.set(Calendar.DAY_OF_MONTH, mDay - notificationDay);
            mCalendar.set(Calendar.MONTH, mMonth);
            mCalendar.set(Calendar.YEAR, mYear);
            mCalendar.set(Calendar.HOUR_OF_DAY, mHour);
            mCalendar.set(Calendar.MINUTE, mMinute);
            mCalendar.set(Calendar.SECOND, 0);
            new AlarmReceiver().setAlarm(getApplicationContext(), mCalendar, id);
        }

Upvotes: 0

Views: 224

Answers (3)

Talha Arshad
Talha Arshad

Reputation: 143

You should use AlarmManager.RTC_WAKEUP while setting your alarm. AlarmManager.RTC_WAKEUP will trigger the alarm according to the time of the clock.

Example code:

mAlarmManager.set(AlarmManager.RTC_WAKEUP, currentTime + diffTime, mPendingIntent);

Upvotes: 1

Kilarn123
Kilarn123

Reputation: 733

mAlarmManager.set() does not force to deliver the pending intent at the exact given time

https://developer.android.com/reference/android/app/AlarmManager.html#set(int,%20long,%20android.app.PendingIntent)

Note: Beginning in API 19, the trigger time passed to this method is treated as inexact: the alarm will not be delivered before this time, but may be deferred and delivered some time later. The OS will use this policy in order to "batch" alarms together across the entire system, minimizing the number of times the device needs to "wake up" and minimizing battery use. In general, alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.

mAlarmManager.setExact() may fit what you are trying to do

if you have the exact time and date, (year, month, day, hour and minute) (you can check that with android studio debugger or with logcat to print the values) you can set the alarm with mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, /*your exact time in millis*/, mPendingIntent);

Upvotes: 0

Manoj Perumarath
Manoj Perumarath

Reputation: 10214

By using TIME_SET receiver you can get to notify about the system time has been changed.

Whenever you're creating an Alarm just save the time in a local db also. When the broadcast receiver is triggered invoke a service, inside that fetch all existing alarm time with the new system time. You should be aware that all the alarms will get cancelled once you change the system time. So you should recreate all your alarms.

Upvotes: 0

Related Questions