33

Android 4 以降で、選択した日に発生するすべてのイベントを取得しようとしています。

私の知る限り、CalendarContract.Instances は定期的なイベントと 1 回限りのイベントの両方を処理するため、イベントを取得する最も簡単な方法です。

ただし、タイムスタンプの処理方法に問題があります。具体的には、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のバグですか?しかし、それがバグである場合、システム カレンダーが正常に動作するのはなぜですか? この一貫性のない動作は、私には奇妙に思えます。

ありがとう。

4

1 に答える 1

1

CalendarAPIもデバイスに依存するものであり、コードは完全に機能しますAndroid - 4.4.4 KitKatが、他のデバイスでは機能しません。次のコードは、私がテストしたすべてのデバイスで完全に機能しています。

これを試して:

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());
}
于 2014-09-29T06:58:36.980 に答える