之前开发的应用要求的一个功能是同步手机系统日历日程,发现网上也没什么总结好的答案,查阅了些资资料没有发现Android有获取指定日期事件的方法,于是自己就研究了一番。
1、先在Android的配置文件中添加读取日历的权限
<!--读取与写入系统日历权限--> <uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" />2、不同版本的日历URL路径:
if (Integer.parseInt(Build.VERSION.SDK) >= 8) { calanderEventURL = "content://com.android.calendar/events"; } else { calanderEventURL = "content://calendar/events"; }3、我通过handler_message机制发送消息查询数据库,在查询数据库之前对于于Android6.0以后的系统,要先判断相应的权限是否打开,判断代码如下
int result = 0; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { result = mContext.checkSelfPermission("android.permission.READ_CALENDAR"); }如果result为0的话说明相应的权限已打开,若不为0,则未打开,即可不进行查询或通知用户打开相应权限等后续操作
4、查询数据库
private List<Event> events=new ArrayList<>;//存储查询结果
public void query(){
Uri uri = Uri.parse(url);
//查询所有事件
String selection = "((" + CalendarContract.Events.DTSTART + " <> ?)And(" + CalendarContract.Events.CALENDAR_ID + "<>?))";
// MyLog.e("string", selection);
Cursor cursor = cr.query(uri, null, selection, new String[]{"null", "3"}, null);
while (cursor.moveToNext()) {
String duration = cursor.getString(cursor.getColumnIndex(CalendarContract.Events.DURATION));
if (!TextUtils.isEmpty(duration)) {
//重复事件 结束时间为null 有重复的type和规则
setRepeatEvents(cursor, startTime);
} else if (TextUtils.isEmpty(duration)) {
//正常事件 一定存在开始结束时间
setNormalEvents(cursor, startTime, EndTime);
}
}
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
Message msg = new Message();
msg.what = MainActivity.QUERY_SYSTEM_EVENTS;
msg.obj = events;;
handler.sendMessage(msg);
}
}
//开始时间和结束时间是13位时间戳
private void setNormalEvents(Cursor cursor, String startTime, String EndTime) {
Event bean = new Event();
long dstart = Long.parseLong(cursor.getString(cursor.getColumnIndex(CalendarContract.Events.DTSTART)));
long dtend = Long.parseLong(cursor.getString(cursor.getColumnIndex(CalendarContract.Events.DTEND)));
long start = Long.parseLong(startTime);
long end = Long.parseLong(EndTime);
//事件包含在当天
String allday = cursor.getString(cursor.getColumnIndex(CalendarContract.Events.ALL_DAY));
if ("1".equals(allday)) {//全天事件
if (dstart > start && dstart < end && dtend > end) {
setBasedate(cursor, bean);
}
} else {//在当天的正常事件
if (dstart > start && dtend < end && dstart < dtend) {
setBasedate(cursor, bean);
} else if (dstart < start && dtend > start && dtend < end) {
setBasedate(cursor, bean);
} else if (dstart < start && dtend > end) {
setBasedate(cursor, bean);
} else if (dstart > start && dstart < end && dtend > end) {
setBasedate(cursor, bean);
}
}
}
/**
* 设置基本数据
*
* @param cursor
* @param bean
*/
private void setBasedate(Cursor cursor, Event bean) {
bean.set_id(cursor.getString(cursor.getColumnIndex(CalendarContract.Events._ID)));
bean.setTitle(cursor.getString(cursor.getColumnIndex(CalendarContract.Events.TITLE)));
bean.setStart_time(cursor.getString(cursor.getColumnIndex(CalendarContract.Events.DTSTART)));
bean.setEnd_time(cursor.getString(cursor.getColumnIndex(CalendarContract.Events.DTEND)));
//全天事件
bean.setAllday(cursor.getString(cursor.getColumnIndex(CalendarContract.Events.ALL_DAY)));
//重复事件
bean.setRepeatRule(cursor.getString(cursor.getColumnIndex(CalendarContract.Events.RRULE)));
events.add(bean);
// MyLog.e("params", bean.toString());
}
//重复事件重复规则没有找到好方法进行解析还在研究中
private void setRepeatEvents(Cursor cursor, String startTime) {
Event bean = new Event();
long start = Long.parseLong(startTime);
long dstart = Long.parseLong(cursor.getString(cursor.getColumnIndex(CalendarContract.Events.DTSTART)));
if (MyTimeUtil.isSameDayOfMillis(start, dstart)) {//重复事件的起始天显示
setBasedate(cursor, bean);
} else if (dstart < start) {//重复的全天事件
//TODO // String allday = cursor.getString(cursor.getColumnIndex(CalendarContract.Events.ALL_DAY));
// if ("1".equals(allday)) {
// setBasedate(cursor, bean);
// }
}
}
这段代码可以获取指点日期的系统日历事件,对于开始时间在指定日期 的重复事件也可以读出,当鉴于本人能力有限没有能解决了重复事件rrule规则,对于重复事件的处理还不完善,哪位大神有好方法,解决重复日程的问题,请指教
本文介绍如何在Android应用中同步手机系统日历日程,包括添加权限、适配不同版本的URL路径、查询数据库及处理查询结果的具体实现。
1268





