Android app 的提醒功能

这篇文章涉及到利用AlarmManager来实现提醒功能以及在锁屏状态下弹出提醒界面的功能。

作为web的补充,移动app也需要有自己的特色功能,两者相辅相成,满足用户不同需求。

我的Android Worktile在大版本3.0.0更新之后,要增加特有功能了——提醒。这也是用户们的呼声。


第一部分 提醒功能

设置提醒时间,时间到时弹出提醒界面

1.首先在配置文件manifest中注册一个receiver来接收AlarmManager发送的广播。

<receiver android:name="com.worktile.core.utils.RemindReceiver" > </receiver>
2.设置提醒时间

Intent intent = new Intent(context, RemindReceiver.class);
intent.putExtra("data", bundle);//携带提醒界面的信息。
PendingIntent sender = PendingIntent.getBroadcast(context, bundle.getString("xid").hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager manager = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);                                manager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);

关键点:PendingIntent.getBroadcast方法的第二个参数可以保证设置多个提醒,通过id来区分是新提醒,还是更新提醒,第四个参数可以保证可以更新提醒的时间;AlarmManager的set方法的第二个参数是提醒的时间,当第二个参数的时间到后,RemindReceiver的onReceive方法会被调用。因此在该方法中弹出提醒界面。

3.弹出提醒界面

@Override
	public void onReceive(Context context, Intent intent) {
		Intent intent_remind = new Intent(context, RemindActivity.class);
		intent_remind.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		intent_remind.putExtra("data", intent.getBundleExtra("data"));//<span style="font-family: Arial, Helvetica, sans-serif;">提醒界面的信息的相关信息被传递到这里</span>
		context.startActivity(intent_remind);	
	}


事情如果如此简单,生活该多美好。

问题1.这种方法在app意外崩溃之后(无法避免简直),或者关机重启后(电量伤不起),所设置的提醒会无效。

问题2.(我们的需求是给日程设置提醒)已经设置过提醒的日程应该显示提醒时间,没有设置过提醒的日程显示“未设置”。而AlarmManager的api方法没有获取所有提醒事件的方法,无从知道哪个日程被设置为提醒了。

问题3.日程有按日/周/月/年重复。AlarmManager可以设置重复提醒。有方法可以调用 日周好说,可月年。。。

manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, sender);</span>

manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY*7, sender)


由问题1和问题2,想到必须要把设置过的提醒存储起来。Android的轻量数据库方便简洁,而ormlite让存储更简单。

在给日程设置提醒时,在数据库中增加一条记录,记录该日程的相关信息。

在显示日程详情时,去数据库查看是否有记录,有?获取提醒时间:不显示提醒时间(问题2完败)

取消日程的提醒时,取消提醒的同时从数据库删除该条记录。删除该日程时,同理。

public static void unRemind(Context context, Bundle bundle) {// 取消注册Intent intent = new Intent(context, RemindReceiver.class);PendingIntent sender = PendingIntent.getBroadcast(context, bundle.getString("xid").hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);AlarmManager manager = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);manager.cancel(sender);// 数据库删除try {RemindDataUtil util = new RemindDataUtil(RemindDataUtil.getHelper(context).getRemindDataDao(), bundle.getString("xid"));util.delete();} catch (SQLException e) {e.printStackTrace();}}



在Application类的onCreate方法中遍历数据库的记录,设置提醒。这样,只要用户在使用app,降低了落下提醒的概率。缓解问题1。

另外,app 中有推送,而推送的receiver监听了USER_PRESENT,而application的onCreate方法会在四大组件创建之前调用。

onCreate()

Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.

也就是说,当用户关机再开机时,会调用推送的receiver的onReceive方法,而在此之前会调用application的onCreate方法,这样看来,应该不会错过提醒了。

关于问题3 ,如何按月按年设置重复提醒。我的解决办法是这样的:

在记录提醒的数据库中会记录初次提醒时间和是否重复的flag。

在application的onCreate方法中设置提醒时比较系统当前时间和提醒的提醒时间。如果系统时间大于提醒时间而且是重复提醒,则设置提醒时间为下一周期(月或年),更新数据库的提醒时间为下一周期。

application的onCreate调用的设置提醒方法

private void initRemind() {
		try {
			List<Remind> reminds = RemindDataUtil.getHelper(mContext).getRemindDataDao().queryForAll();
			for (Remind remind : reminds) {
				Bundle data = new Bundle();
				data.putInt("type", RemindActivity.TYPE_EVENT);
				data.putString("xid", remind.id);
				data.putString("projectId", remind.pid);
				data.putString("name", remind.name);
				data.putInt("repeat", remind.repeat);
				Calendar calendar = Calendar.getInstance();
				calendar.setTimeInMillis(remind.time);
				ProjectUtil.remind(mContext, calendar, data);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

ProjectUtil.remind:

public static void remind(Context context, Calendar calendar, Bundle bundle) {
		int repeat = bundle.getInt("repeat");
		// 进行闹铃注册
		Intent intent = new Intent(context, RemindReceiver.class);
		intent.putExtra("data", bundle);
		PendingIntent sender = PendingIntent.getBroadcast(context, bundle.getString("xid").hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
		AlarmManager manager = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);
		switch (repeat) {
		case 1:// 天
			manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, sender);
			break;
		case 2:// 周
			manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, sender);
			break;
		case 3:// 月
			if (calendar.getTimeInMillis() < System.currentTimeMillis())
				calendar.add(Calendar.MONTH, 1);
			manager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
			break;
		case 4:// 年
			if (calendar.getTimeInMillis() < System.currentTimeMillis())
				calendar.add(Calendar.YEAR, 1);
			manager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
			break;
		case 0:
			manager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
			break;
		}
		// 存进数据库
		try {
			RemindDataUtil util = new RemindDataUtil(RemindDataUtil.getHelper(context).getRemindDataDao());
			Remind remind = new Remind();
			remind.id = bundle.getString("xid");
			remind.pid = bundle.getString("projectId");
			remind.name = bundle.getString("name");
			remind.time = calendar.getTimeInMillis();
			remind.repeat = repeat;
			util.add(remind);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}



第二部分 弹出提醒界面 

提醒界面的注册:

<activity android:name="com.worktile.ui.uipublic.RemindActivity" android:label="@string/app_name"android:theme="@style/activity_dialog_remind_unlock" ></activity>


<style name="activity_dialog_remind_unlock" parent="@android:style/Theme.Translucent.NoTitleBar"></style>

   <style name="activity_dialog_remind_unlock" parent="@android:style/Theme.Translucent.NoTitleBar"></style>


锁屏时 显示壁纸背景+提示框(类似QQ的锁屏通知)

un锁屏时,显示当前显示界面+提示框

@Override
	protected void onCreate(Bundle savedInstanceState) {
		KeyguardManager mKeyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
		if (mKeyguardManager.inKeyguardRestrictedInputMode()) {
			// 锁屏状态
			setTheme(R.style.activity_dialog_remind);
		}
		super.onCreate(savedInstanceState);
		mp = new MediaPlayer();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
		setContentView(R.layout.activity_remind);
}



利益相关:worktile

搜索IT技术哪家强,Google比百度好的不是一星半点,定位问题快很多。红杏 访问墙外网站更方便。


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值