Android Calendar Provider(日历事件)

1 篇文章 0 订阅
1 篇文章 0 订阅

这篇文章的目的

写这篇文章的目的,主要是为了记录在日历事件中遇到的2个比较少见,在网上比较难查找资料的问题。

应用背景:
在应用中通过ContentProvider操作系统日历,向系统日历中添加、更新、删除日程事件。
所以应用中的日程事件,是与系统日历中的事件同步的。

问题1:
为应用不同的登录账号添加日历账号,用此日历账号在应用中添加日程事件,然后应用切换账号,日程事件消失。

问题2:
删除日历事件后,系统日历中已经删除,但在应用中通过ContentProvider还能查询到(小米、魅族、联想一些国产手机没有这个问题,三星有)。

Calendar Provider的详细操作,参见官方文章:
http://developer.android.com/guide/topics/providers/calendar-provider.html
对应的中文译文:
http://www.cnblogs.com/popapa/p/android_calendar-provider.html#sync-adapter


问题1

问题描述:

为应用不同的登录账号添加日历账号,用此日历账号在应用中添加日程事件,然后应用切换账号,日程事件消失。

问题原因:

这个问题,应该是(猜想)和Android系统日历的账号管理有关。

在项目中,添加日历账号的代码如下所示

private long addCalendarAccount(Context context) {
    boolean has_permission = Utils.hasPermission(context, "android.permission.WRITE_CALENDAR");
    if (!has_permission) {
        Utils.toast(context, R.string.calendar_disable_hint);
        return -1;
    }
    TimeZone timeZone = TimeZone.getDefault();
    ContentValues value = new ContentValues();
    value.put(Calendars.NAME, CALENDARS_NAME);

    value.put(Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME);
    value.put(Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL);
    value.put(Calendars.CALENDAR_DISPLAY_NAME, CALENDARS_DISPLAY_NAME);
    value.put(Calendars.VISIBLE, 1);
    value.put(Calendars.CALENDAR_COLOR, Color.BLUE);
    value.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER);
    value.put(Calendars.SYNC_EVENTS, 1);
    value.put(Calendars.CALENDAR_TIME_ZONE, timeZone.getID());
    value.put(Calendars.OWNER_ACCOUNT, CALENDARS_ACCOUNT_NAME);
    value.put(Calendars.CAN_ORGANIZER_RESPOND, 0);

    Uri calendarUri = Uri.parse(uri);
    calendarUri = calendarUri.buildUpon().appendQueryParameter(CALLER_IS_SYNCADAPTER, "true")
            .appendQueryParameter(Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME)
            .appendQueryParameter(Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL).build();

    Uri result = context.getContentResolver().insert(calendarUri, value);
    long id = result == null ? -1 : ContentUris.parseId(result);
    return id;
}

有一句设置账号类型的代码:

value.put(Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL);

其中Calendars.ACCOUNT_TYPE的说明如下图:
这里写图片描述

说明中有一句英文:
A type of ACCOUNT_TYPE_LOCAL will keep this event form being deleted if there are no matching accounts on the device.

大意是:
当ACCOUNT_TYPE为ACCOUNT_TYPE_LOCAL时,可以防止在设备中没有找到账号时日程事件被删除。

解决方案:

因此,问题1的解决方案就是设置ACCOUNT_TYPE为ACCOUNT_TYPE_LOCAL:

value.put(Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL);

问题2

问题描述:

删除日历事件后,系统日历中已经删除,但在应用中通过ContentProvider还能查询到(小米、魅族、联想一些国产手机没有这个问题,三星有)。

这个问题,在网上找了很长时间,都没有找到相应的资料,在最后快要放弃的时候,在Stackoverflow上找到了解决办法。
http://stackoverflow.com/questions/22554130/calendar-deleted-event-exists-in-cursor

其实问题修改起来很简单,因为日程事件删除之后,系统并没有真的删除,只是对把标示删除的字段改了而已,也就是只做了逻辑删除,而没有做物理删除。

小米、魅族、联想一些国产手机没有这个问题的原因,可能是国产手机的系统定制化高,查询的时候,已经对这个问题进行了处理,而三星没有处理。

其实这个问题,如果会阅读源码的话,花些时间,放些耐心应该是可以从源码中分析出来的,所有阅读源码还是很有必要的。

解决方案:

清楚问题原因之后,解决方案其实很简单,就是查询的时候,再过滤一下,增加查询条件(deleted != 1)就OK了。

比如应用中查询的代码

private void fillData(Context context, String selection,
        String[] selectionArgs, List<CalendarEvent> calendarEvents) {
    selection+=" and (deleted != 1)";
    Cursor cursor = context.getContentResolver().query(Uri.parse(eventUri),null, selection, selectionArgs, null);
    if (cursor.moveToFirst()) {
        do {
            CalendarEvent calendarEvent=new CalendarEvent();
            String title = cursor.getString(cursor.getColumnIndex(Events.TITLE));
            String description = cursor.getString(cursor.getColumnIndex(Events.DESCRIPTION));
            String repeat = cursor.getString(cursor.getColumnIndex(Events.RRULE));
            long eventId = cursor.getLong(cursor.getColumnIndex(Events._ID));
            long beginTime = cursor.getLong(cursor.getColumnIndex(Events.DTSTART));
            long endTime = cursor.getLong(cursor.getColumnIndex(Events.DTEND));
            int remind = getRemindMunites(context, eventId);
            calendarEvent.setEventId(eventId);
            calendarEvent.setDescription(description);
            calendarEvent.setTitle(title);
            calendarEvent.setBeginTime(beginTime);
            calendarEvent.setEndTime(endTime);
            calendarEvent.setRemind(remind);
            calendarEvent.setRepeat(repeat);
            calendarEvent.setCalendarId(cursor.getLong(cursor.getColumnIndex(Events.CALENDAR_ID)));
            calendarEvents.add(calendarEvent);
        } while (cursor.moveToNext());
    }
    cursor.close();
}

结束

文章就写到这里,附上添加、修改、删除日程时间完整Demo,点击下载

如果需要查询日程时间操作的详细资料,参见官方文章:
http://developer.android.com/guide/topics/providers/calendar-provider.html
对应的中文译文:
http://www.cnblogs.com/popapa/p/android_calendar-provider.html#sync-adapter

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值