Подтвердить что ты не робот

Список событий для определенного дня в Android 4+ (проблема ALL_DAY)

Я пытаюсь сделать все события в выбранный день в Android 4 +.

Насколько я понимаю, CalendarContract.Instances - это самый простой способ получения событий, поскольку он обрабатывает как повторяющиеся события, так и события одного времени.

Однако у меня есть некоторые проблемы с его способом обработки временных меток. Чтобы быть конкретным, он, по-видимому, обрабатывает события ALL_DAY по-разному.

Я начал со следующего кода (start - это день, в который я собираю события, миллисекундная "математика" должна избегать ненужных событий, начинающихся в 12 часов утра следующего дня, календарь использует часовой пояс по умолчанию).

public Cursor fetchCursor(Calendar start) {
    Calendar end = (Calendar) start.clone();
    end.add(Calendar.DATE, 1);

    long startTime = start.getTimeInMillis() + 1;
    long endTime = end.getTimeInMillis() - 1;

    ContentResolver resolver = mContext.getContentResolver();
    return CalendarContract.Instances.query(resolver, projection, startTime, endTime);
}

Этот код, похоже, хорошо работает со многими краевыми случаями, разными часовыми поясами, событиями, которые охватывают несколько дней... все, кроме событий за весь день.

Когда я рассмотрел возвращенное событие со значком ALL_DAY:

    Cursor c = fetchCursor(date);
    Log.e("SIZE", String.valueOf(c.getCount()));
    while (c.moveToNext()) {
        long begin = c.getLong(2); // CalendarContract.Instances.BEGIN
        long end = c.getLong(3);   // CalendarContract.Instances.END
        Date beginDate = new Date(begin);
        Date endDate = new Date(end);
        Log.e("EVENT", String.valueOf(begin) + " - " + String.valueOf(end));
        Log.e("EVENT", beginDate.toString() + " - " + endDate.toString());
    }

Я получил: EVENT(10075): Thu Sep 13 02:00:00 CEST 2012 - Sat Sep 15 02:00:00 CEST 2012.

Для меня это выглядит так: query ожидает, что начало и конец диапазона начнется в миллисекундах с момента времени в MY TIMEZONE (но API утверждает, что ему нужна временная метка UTC). Но события, отмеченные как ALL_DAY, используют миллис с эпохи в UTC (поэтому я получаю 2 дополнительных часа из-за +2 часового пояса).

Я также попытался вычислить и добавить смещение временной зоны. Тогда все дневные события работали нормально, но все остальное... нет.

private long getTimezoneOffset(TimeZone zone, long date) {
    long delta = zone.getOffset(date);
    return delta;
}

private long getTimeInUTC(Calendar date) {
    long time = date.getTimeInMillis();
    time += getTimezoneOffset(date.getTimeZone(), time);
    return time;
}

public Cursor fetchCursor(Calendar start) {
    Calendar end = (Calendar) start.clone();
    end.add(Calendar.DATE, 1);

    long startTime = getTimeInUTC(start) + 1;
    long endTime = getTimeInUTC(end) - 1;

    ContentResolver resolver = mContext.getContentResolver();
    return CalendarContract.Instances.query(resolver, projection, startTime, endTime);
}

Хотя существует довольно простой способ исправить эту проблему, перебирая курсор, изменяя события ALL_DAY и удаляя ненужные события, я хотел бы знать, есть ли лучший способ. Или, может быть, это ошибка Android? Но если это ошибка, то почему System Calendar работает нормально? Это непоследовательное поведение кажется странным для меня.

Спасибо.

4b9b3361

Ответ 1

calendar api также зависит от устройства, ваш код отлично работает в Android 4.4.4, но не во многих других устройствах, но следующий код отлично работает со всеми устройствами, в которых я тестировал.

вы можете попробовать это

public Cursor fetchCursor(Calendar start) {
        Calendar end = (Calendar) start.clone();
        end.add(Calendar.DATE, 1);


        ContentResolver resolver = this.getContentResolver();
        return CalendarContract.Instances.query(resolver,  new String[] { "calendar_id", "title", "description",
                "dtstart", "dtend", "eventLocation" }, start.getTimeInMillis(),
                end.getTimeInMillis());
    }