今天使用Notification 遇到了 些诡异的问题,记录下来,以备后用。
- 需求:定时获取消息,并在通知栏显示;点击通知栏弹出消息框
- 实现:
AlarmManager + BroadcastReceiver + NotificationManager
部分代码如下:
public static void setupGetMessageAlarm(Context context) { Log.d("msg", "setupGetMessageAlarm"); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, MsgAlarmReceiver.class); intent.setAction(INTENT_GET_MESSAGE_ALARM); PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0); Calendar calendar1 = Calendar.getInstance(); calendar1.set(Calendar.HOUR_OF_DAY, 12); calendar1.set(Calendar.MINUTE, 30); Calendar calendar2 = Calendar.getInstance(); calendar2.set(Calendar.HOUR_OF_DAY, 18); calendar2.set(Calendar.MINUTE, 30); am.setRepeating(AlarmManager.RTC_WAKEUP, calendar1.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi); am.setRepeating(AlarmManager.RTC_WAKEUP, calendar2.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi); }
public class MsgAlarmReceiver extends BroadcastReceiver { private Context mContext; private MsgInfo mMsgInfo; private NotificationManager mNM; private static final int NOTIFICATION_ID = R.layout.activity_message; @Override public void onReceive(final Context context, Intent intent) { mContext = context; mNM = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Intent intent = new Intent(mContext, MessageActivity.class); Bundle bundle = new Bundle(); bundle.putParcelable(MsgInfo.class.getName(), mMsgInfo); intent.putExtras(bundle); PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); Notification notification = new Notification(); notification.icon = R.drawable.ic_app; notification.tickerText = mContext.getString(R.string.notification_ticker_message); notification.setLatestEventInfo(mContext, mMsgInfo.getTitle(), noticeMessage, pendingIntent); notification.flags = Notification.FLAG_AUTO_CANCEL; mNM.notify(NOTIFICATION_ID, notification); } }
- 出现问题:
- 点击通知,不弹出MessageActivity
解决方法:重启手机;原因未知
- 传递给activity的bundle为null
解决方法:将PendingIntent的flag设为 PendingIntent.FLAG_UPDATE_CURRENT;
原因见 点击打开链接 待研究
- 通知栏消息点击后不消失
解决方法:notification添加flag
notification.flags = Notification.FLAG_AUTO_CANCEL;
- 运行程序立即弹出notification
原因:设置的时钟已过时
解决方法:设置时钟时增加判断,已过时则设置为第二天执行,
Calendar calendar1 = Calendar.getInstance();
calendar1.set(Calendar.HOUR_OF_DAY, 12);
calendar1.set(Calendar.MINUTE, 30);
Calendar calendar2 = Calendar.getInstance();
calendar2.set(Calendar.HOUR_OF_DAY, 18);
calendar2.set(Calendar.MINUTE, 30);
// 若时间已过,设置下一天执行。
long alertTime1 = calendar1.getTimeInMillis(),
alertTime2 = calendar2.getTimeInMillis();
if(System.currentTimeMillis() > alertTime1){
alertTime1 += AlarmManager.INTERVAL_DAY;
}
if(System.currentTimeMillis() > alertTime2){
alertTime2 += AlarmManager.INTERVAL_DAY;
}
am.setRepeating(AlarmManager.RTC_WAKEUP, alertTime1, AlarmManager.INTERVAL_DAY, pi);
am.setRepeating(AlarmManager.RTC_WAKEUP, alertTime2, AlarmManager.INTERVAL_DAY, pi);
- 设置的第一个定时器不生效
原因:setRepeating的解释如下,
/**
* Schedule a repeating alarm. <b>Note: for timing operations (ticks,
* timeouts, etc) it is easier and much more efficient to use
* {@link android.os.Handler}.</b> If there is already an alarm scheduled
* for the same IntentSender, it will first be canceled.......
* Schedule a repeating alarm. <b>Note: for timing operations (ticks,
* timeouts, etc) it is easier and much more efficient to use
* {@link android.os.Handler}.</b> If there is already an alarm scheduled
* for the same IntentSender, it will first be canceled.......
看来要想设置两个Intent相同,仅仅是时间不同的闹铃是不能简单的采用设置两次的方法了。
从网上搜索到一种实现方式,每次找下一个时间点设置闹铃,闹铃执行时再设置下一个闹铃。代码如下:
public static void setupNextGetMessageAlarm(Context context) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, MsgAlarmReceiver.class);
intent.setAction(INTENT_GET_MESSAGE_ALARM);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
// 闹铃时间
final int HOUR_1 = 12, MINITE_1 = 30, HOUR_2 = 18, MINITE_2 = 30;
if(cal.get(Calendar.HOUR_OF_DAY) <= HOUR_1 && cal.get(Calendar.MINUTE) < MINITE_1){
cal.set(Calendar.HOUR_OF_DAY, HOUR_1);
cal.set(Calendar.MINUTE, MINITE_1);
}else if(cal.get(Calendar.HOUR_OF_DAY) <= HOUR_2 && cal.get(Calendar.MINUTE) < MINITE_2){
cal.set(Calendar.HOUR_OF_DAY, HOUR_2);
cal.set(Calendar.MINUTE, MINITE_2);
}else{
cal.set(Calendar.HOUR_OF_DAY, HOUR_1);
cal.set(Calendar.MINUTE, MINITE_1);
}
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
// 若时间已过,设置下一天执行。
long alertTime1 = cal.getTimeInMillis();
if(System.currentTimeMillis() > alertTime1){
alertTime1 += AlarmManager.INTERVAL_DAY;
}
am.setRepeating(AlarmManager.RTC_WAKEUP, alertTime1, AlarmManager.INTERVAL_DAY, pi);
}
@Override
public void onReceive(final Context context, Intent intent) {
LogUtil.d(TAG, "MsgAlarmReceiver");
mContext = context;
// 设置下一个闹铃
MsgUtils.setupNextGetMessageAlarm(context);
......