日历对象时间与Android手机时间不匹配

时间:2019-03-29 09:48:02

标签: android

我已经构建了一个小提醒应用程序演示,其中用户填写了一些详细信息并得到通知。当我设置通知时间时,将当前时间设置为5分钟后,例如当前时间是14:55,那么我将当前日期设置为15:00。现在,通知正好按时到来,当我什么也不做时,只需等待5分钟即可结束。

但是,当我手动转到我的Android手机并将时间设置为4分钟(14:59)之后,等待1分钟后,通知不会发出。为什么?

代码: 清单:

<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);
        }

3 个答案:

答案 0 :(得分:1)

设置警报时,应使用AlarmManager.RTC_WAKEUP。 AlarmManager.RTC_WAKEUP将根据时钟时间触发警报。

示例代码:

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

答案 1 :(得分:0)

通过使用TIME_SET接收器,您可以通知系统时间已更改。

无论何时创建警报,也只需将时间保存在本地数据库中。触发广播接收器时,调用服务,在该服务内部将获取所有现有警报时间以及新的系统时间。您应注意,更改系统时间后所有警报将被取消。因此,您应该重新创建所有警报。

答案 2 :(得分:0)

mAlarmManager.set()不会强制在确切的给定时间交付待定意图

  

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

     

注意:从API 19开始,传递给此方法的触发时间被认为是不精确的:警报不会在此时间之前发送,但可能会延迟并在一段时间后发送。操作系统将使用此策略,以便将警报在整个系统中“分批”在一起,从而最大程度地减少设备需要“唤醒”的次数,并最大程度地减少电池消耗。通常,只要将来的警报时间长,就不会延迟不久的警报时间。

mAlarmManager.setExact()可能符合您的尝试

如果您具有确切的时间和日期(年,月,日,小时和分钟)(您可以使用android studio调试器或logcat进行检查以显示值),则可以使用 mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, /*your exact time in millis*/, mPendingIntent