我正在编写一个需要用户每天在设定时间输入的应用程序。在我的偏好片段中,我使用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()));
}
}
答案 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);
}
}
}