11

我正在尝试使用 Android 的新日历 API 来读取今天的所有日历事件。我无法在数据库查询中找到正确的选择来返回所有事件。似乎所有重复的和全天的事件都被排除在选择之外。什么选择参数可以让我从日历 api 中获取今天的所有事件?

这是我目前的尝试:

    Cursor cur = null;
    String selection = "((" + CalendarContract.Events.DTSTART
            + " >= ?) AND (" + CalendarContract.Events.DTEND + " <= ?))";
    Time t = new Time();
    t.setToNow();
    String dtStart = Long.toString(t.toMillis(false));
    t.set(59, 59, 23, t.monthDay, t.month, t.year);
    String dtEnd = Long.toString(t.toMillis(false));
    String[] selectionArgs = new String[] { dtStart, dtEnd };
    cur = c.getContentResolver().query(CalendarContract.Events.CONTENT_URI,
            null, selection, selectionArgs, null);

我不确定如何扩大选择范围或添加到其中以获取重复事件和全天事件。任何帮助,将不胜感激。

4

5 回答 5

21

要获取今天的所有事件,包括重复事件,您需要使用 Instances 表,即

Uri.Builder eventsUriBuilder = CalendarContract.Instances.CONTENT_URI
            .buildUpon();
ContentUris.appendId(eventsUriBuilder, timeNow);
ContentUris.appendId(eventsUriBuilder, endOfToday);
Uri eventsUri = eventsUriBuilder.build();
Cursor cursor = null;       
cursor = mContext.getContentResolver().query(eventsUri, columns, null, null, CalendarContract.Instances.DTSTART + " ASC");

请注意,您必须将时间限制附加到事件 uri,您不能以任何其他方式排序。

为了也包括全天活动,只需将搜索范围扩大到前一天晚上 11:59 PM 和今晚 12:00 AM。

于 2012-10-26T01:13:37.867 回答
5

你的条件只给你严格在今天限制内的事件。您应该检查在今天之前开始并在(多日事件)之后结束的那些。

对于重复发生的事件,我手动检查它们。我没有找到其他方法。

我使用类似的东西:

String selection = "((" + CalendarContract.Events.DTSTART + " <= ?) AND (" + CalendarContract.Events.DTEND + " >= ?)) OR (" + CalendarContract.Events.RRULE + " is not null )";

String[] selectionArgs = new String[] { dtEnd, dtStart};

问候,

于 2012-09-09T16:34:11.617 回答
2

您应该能够将 CalendarContract.Events.ALL_DAY 添加到您的选择条件以过滤所有 ALL_DAY 事件。

于 2012-05-05T20:37:42.130 回答
2

我知道这有点晚了,但我有一个非常相似的问题并且很难找到我正在寻找的答案。全天事件的强制 UTC 时区使事情变得棘手。这是我的解决方案:

    // "allDayStart" is an all-day event today, encoded in the default time zone
    Time allDayStart = new Time();
    allDayStart.timezone=TimeZone.getDefault().toString();
    allDayStart.set(dayStart.monthDay, dayStart.month, dayStart.year);

    // 2 time selections for the query: 
        // 1) Between day-start and day-end (not all-day); or
        // 2) Equals today at 0:00:00 (all-day) in the default timezone
    String calSelection = 
        "((" + Calendars.ACCOUNT_NAME + " = ?) " +
            "AND (" + Calendars.OWNER_ACCOUNT + "= ?) " +
            "AND (" +
                "((" + Events.DTSTART + ">= ?) " +
                "AND (" + Events.DTSTART + "<= ?) " +
                "AND (" + Events.ALL_DAY + "= ?) " +
                ") " +
            "OR ((" + Events.DTSTART + "= ?) " +
                "AND (" + Events.ALL_DAY + "= ?)" +
                ")" +
            ")" +
        ")"; 

    String[] calSelectionArgs = new String[] {
        accountName, ownerName, 
        dayStartInMillis.toString(), dayEndInMillis.toString(), "0", // during today, not all day
        allDayStartInMillis.toString(), "1" // Started today at default start-time for all-day events (all-day), default time zone
    }; 

可以将查询细化为不需要 2 个部分,但这对我来说已经足够了。

如果有帮助,这里是 dayStart 和 dayEnd 的来源:

    Time dayStart = new Time();
    dayStart.setToNow();
    dayStart.hour=0;
    dayStart.minute=0;
    dayStart.second=0;

    Time dayEnd = new Time();
    dayEnd.set(dayStart);
    dayEnd.hour=dayStart.hour+23;
    dayEnd.minute=dayStart.minute+59;
    dayEnd.second=dayStart.second+59;

    Long dayStartInMillis = dayStart.toMillis(false);
    Long dayEndInMillis = dayEnd.toMillis(false) + 999;
    Long allDayStartInMillis = allDayStart.toMillis(false);
于 2013-09-18T04:58:17.863 回答
1

尝试使用 Instances.CONTENT_BY_DAY_URI。检查此答案以获取示例 - https://stackoverflow.com/a/36622111/1219241

于 2016-04-18T10:05:12.537 回答