alarmManager.setRepeating无论何时,都会立即显示通知

时间:2018-01-14 15:48:11

标签: android

我正在编写一个需要用户每天在设定时间输入的应用程序。在我的偏好片段中,我使用alarmManager.setRepeating来设置通知的显示时间。当通知打开时,用户可以进入应用程序所需输入的位置。

但是,一旦通知时间被设置,通知就会触发。我知道在文档中它说如果alarmManager.setRepeating中使用的时间已经过去,通知将立即触发。我已经尝试过设置将来的通知时间,我尝试将通知时间硬编码为未来几小时。它总是立即发射。

非常感谢任何帮助。

我的偏好片段

package test.test;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.util.Log;
import android.widget.Toast;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static android.content.Context.ALARM_SERVICE;

public class Preferences extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("Preferences", "onCreate: ");

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("Preferences", "onResume: ");
        getPreferenceScreen().getSharedPreferences()
                .registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("Preferences", "onPause: ");
        getPreferenceScreen().getSharedPreferences()
                .unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
    {
        Log.d("Preferences", "onSharedPreferenceChanged: ");

        AlarmManager alarmManager = (AlarmManager)getActivity().getSystemService(ALARM_SERVICE);

        if(key.equals("Mood_Notification_Time"))
        {
            if (sharedPreferences.getBoolean("Show_Mood_Notifications",true))
            {
                long time = sharedPreferences.getLong(key,64802000); // default value should be 20:00

                String temp = (new SimpleDateFormat("HH:mm:ss:SSS")).format(new Date(time));

                Log.d("Preferences", "onSharedPreferenceChanged: key value: " + sharedPreferences.getLong(key,64802000));
                Log.d("Preferences", temp);

                Toast.makeText(getActivity(),temp,Toast.LENGTH_LONG).show(); // show the time the notification is set for.

                Intent intent = new Intent(getActivity(), NotificationReceiver.class);
                PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(),123,intent,PendingIntent.FLAG_UPDATE_CURRENT);

                alarmManager.cancel(pendingIntent); // cancel old notifications

                int t1  = Integer.parseInt((new SimpleDateFormat("HH:mm:ss:SSS")).format(new Date(time)).replace(":",""));
                int t2  = Integer.parseInt((new SimpleDateFormat("HH:mm:ss:SSS")).format(new Date(System.currentTimeMillis())).replace(":",""));

                // Determine if the time specified is past already or not. If it is past add 24 hour.
                if (t1 < t2)
                {
                    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, TimeUnit.DAYS.toMillis(1) + time, alarmManager.INTERVAL_DAY, pendingIntent);
                }
                else
                {
                    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time, alarmManager.INTERVAL_DAY, pendingIntent);
                }
            }
        }

        // Deactivate alarm if its been disabled in preference
        if(key.equals("Show_Mood_Notifications"))
        {
            if (!sharedPreferences.getBoolean(key,true))
            {
                Log.d("Preferences", "onSharedPreferenceChanged: Deactivate Notifications");

                Intent intent = new Intent(getActivity(), NotificationReceiver.class);
                alarmManager.cancel(PendingIntent.getBroadcast(getActivity(),123,intent,PendingIntent.FLAG_UPDATE_CURRENT));
            }
        }
    }
}

我的广播接收器

package test.test;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.res.ResourcesCompat;

public class NotificationReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        Intent intent1 = new Intent(context,EditMoodActivity.class);
        intent1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(context,100,intent1,PendingIntent.FLAG_UPDATE_CURRENT);

        Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        Drawable vectorDrawable = ResourcesCompat.getDrawable(context.getResources(), R.drawable.applogo, null);
        Bitmap myLogo = ((BitmapDrawable) vectorDrawable).getBitmap();

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context).
                setSmallIcon(R.drawable.applogo).
                setLargeIcon(myLogo).
                setContentIntent(pendingIntent).
                setContentText("Set your mood for today.").
                setContentTitle("How was your day?").
                setSound(alarmSound).
                setPriority(Notification.PRIORITY_HIGH).
                setVisibility(Notification.VISIBILITY_PUBLIC).
                setVibrate(new long[]{100,50,100,50,100}).
                setCategory(Notification.CATEGORY_ALARM).
                setAutoCancel(true);
        notificationManager.notify(100,builder.build());
    }
}

TimePreference我在alarmManager.setRepeating中获取用于triggerAtMillis参数的时间

package test.test;

import android.content.Context;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TimePicker;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class TimePreference extends DialogPreference {
    private Calendar calendar;
    private TimePicker picker = null;

    public TimePreference(Context ctxt) {
        this(ctxt, null);
    }

    public TimePreference(Context ctxt, AttributeSet attrs) {
        this(ctxt, attrs, android.R.attr.dialogPreferenceStyle);
    }

    public TimePreference(Context ctxt, AttributeSet attrs, int defStyle) {
        super(ctxt, attrs, defStyle);

        setPositiveButtonText("Set");
        setNegativeButtonText("Cancel");
        calendar = new GregorianCalendar();
    }

    @Override
    protected View onCreateDialogView() {
        picker = new TimePicker(getContext());
        picker.setIs24HourView(true);
        return (picker);
    }

    @Override
    protected void onBindDialogView(View v) {
        super.onBindDialogView(v);
        picker.setCurrentHour(calendar.get(Calendar.HOUR_OF_DAY));
        picker.setCurrentMinute(calendar.get(Calendar.MINUTE));
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            calendar.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour());
            calendar.set(Calendar.MINUTE, picker.getCurrentMinute());

            setSummary(getSummary());
            if (callChangeListener(calendar.getTimeInMillis())) {
                persistLong(calendar.getTimeInMillis());
                notifyChanged();
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return (a.getString(index));
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {

        if (restoreValue) {
            if (defaultValue == null) {
                calendar.setTimeInMillis(getPersistedLong(System.currentTimeMillis()));
            } else {
                calendar.setTimeInMillis(Long.parseLong(getPersistedString((String) defaultValue)));
            }
        } else {
            if (defaultValue == null) {
                calendar.setTimeInMillis(System.currentTimeMillis());
            } else {
                calendar.setTimeInMillis(Long.parseLong((String) defaultValue));
            }
        }
        setSummary(getSummary());
    }

    @Override
    public CharSequence getSummary() {
        if (calendar == null) {
            return null;
        }
        return DateFormat.getTimeFormat(getContext()).format(new Date(calendar.getTimeInMillis()));
    }
}

1 个答案:

答案 0 :(得分:0)

我明白了。

alarmManager.setRepeating的triggerAtMillis参数不是简单的时间转换为毫秒。自UTC时间1970年1月1日午夜起,它是以毫秒为单位的时间。

发生的事情是我正在转换时间,例如:20:00到毫秒(64802000)。当我使用它作为triggerAtMillis的值时,它会将64802000添加到1970年1月1日午夜,即过去40年的午夜!

我现在要做的是计算当前时间和设定时间之间的差异,并使用System.currentTimeMillis()+结果。这将以毫秒为单位添加到当前时间戳的差异,这将导致将来的时间。因此,通知现在会在我设置时显示,而不是立即显示。

@Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
    {
        Log.d("Preferences", "onSharedPreferenceChanged: ");

        AlarmManager alarmManager = (AlarmManager)getActivity().getSystemService(ALARM_SERVICE);

        if(key.equals("Mood_Notification_Time"))
        {
            if (sharedPreferences.getBoolean("Show_Mood_Notifications",true))
            {
                long time = sharedPreferences.getLong(key,64802000); // default value should be 20:00

                String temp = (new SimpleDateFormat("HH:mm:ss:SSS")).format(new Date(time));

                Log.d("Preferences", "onSharedPreferenceChanged: key value: " + sharedPreferences.getLong(key,64802000));
                Log.d("Preferences", temp);

                Toast.makeText(getActivity(),temp,Toast.LENGTH_LONG).show();

                Intent intent = new Intent(getActivity(), NotificationReceiver.class);
                PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(),123,intent,PendingIntent.FLAG_UPDATE_CURRENT);

                alarmManager.cancel(pendingIntent); // cancel old notifications

                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

                String val1  = sdf.format(new Date(System.currentTimeMillis()));
                String val2  = sdf.format(new Date(time));

                Date d1 = null;
                Date d2 = null;

                try {
                    d1 = sdf.parse(val1);
                } catch (ParseException e) {
                    e.printStackTrace();
                }

                try {
                    d2 = sdf.parse(val2);
                } catch (ParseException e) {
                    e.printStackTrace();
                }

                long elapsed = d2.getTime() - d1.getTime();

                // Determine if the time specified is past already or not. If it is past add 24 hours so it displays the following day.
                if (elapsed < 0)
                {
                    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1) + elapsed, alarmManager.INTERVAL_DAY, pendingIntent);
                }
                else
                {
                    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + elapsed, alarmManager.INTERVAL_DAY, pendingIntent);
                }
            }
        }