3

是否可以从手机离线获取日历条目?似乎唯一的方法是使用gdata-java-client

4

7 回答 7

9

Josef 和 Isaac 的日历访问解决方案仅适用于 Android 2.1 及更早版本。Google 已将 2.2 中的基本内容 URI 从“content://calendar”更改为“content://com.android.calendar”。此更改意味着最好的方法是尝试使用旧的基本 URI 获取游标,如果返回的游标为空,则尝试新的基本 URI。

请注意,我从Shane Conder 和 Lauren Darcey 在他们的Working With The Android Calendar文章中提供的开源测试代码中获得了这种方法。

private final static String BASE_CALENDAR_URI_PRE_2_2 = "content://calendar";
private final static String BASE_CALENDAR_URI_2_2 = "content://com.android.calendar";
/*
 * Determines if we need to use a pre 2.2 calendar Uri, or a 2.2 calendar Uri, and returns the base Uri
 */
private String getCalendarUriBase() {
    Uri calendars = Uri.parse(BASE_CALENDAR_URI_PRE_2_2 + "/calendars");
    try {
        Cursor managedCursor = managedQuery(calendars, null, null, null, null);
        if (managedCursor != null) {
            return BASE_CALENDAR_URI_PRE_2_2;
        }
        else {
            calendars = Uri.parse(BASE_CALENDAR_URI_2_2 + "/calendars");
            managedCursor = managedQuery(calendars, null, null, null, null);

            if (managedCursor != null) {
                return BASE_CALENDAR_URI_2_2;
            }
        }
    } catch (Exception e) { /* eat any exceptions */ }

    return null; // No working calendar URI found
}
于 2010-10-18T12:07:37.657 回答
8

这些答案很好,但它们都涉及硬编码Calendar URI(我在不同的 Android 设备上看到了三种不同的化身)。

一个更好的方法URI(它硬编码一个类的名称和一个字段)是这样的:

Class<?> calendarProviderClass = Class.forName("android.provider.Calendar");
Field uriField = calendarProviderClass.getField("CONTENT_URI");
Uri calendarUri = (Uri) uriField.get(null);

这并不完美(如果他们删除了android.provider.Calendar类或CONTENT_URI字段,它会中断),但它可以在比任何单个 URI 硬代码更多的平台上工作。

请注意,这些反射方法将抛出exceptions需要被调用方法捕获或重新抛出的内容。

于 2011-02-27T22:43:57.493 回答
3

您可以使用日历内容提供程序 ( com.android.providers.calendar.CalendarProvider)。例子:


ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(Uri.parse("content://calendar/events"), null, null, null, null);

while(cursor.moveToNext()) {
    String eventTitle = cursor.getString(cursor.getColumnIndex("title"));
    Date eventStart = new Date(cursor.getLong(cursor.getColumnIndex("dtstart")));
    // etc.
}

编辑:你可能想把它放在一个包装器中(参见Isaac 的帖子),因为它目前是一个私有 API。

于 2009-05-13T12:47:38.910 回答
3

目前,如果不使用私有 API,这是不可能的(请参阅 Josef 的帖子。)有一个日历提供程序,但它尚未公开。它可能随时更改并破坏您的应用程序。
不过,它可能不会改变(我认为他们不会从“日历”改变它),所以你也许可以使用它。但我的建议是使用这样的单独类:

public class CalendarProvider {
     public static final Uri CONTENT_URI = Uri.parse("content://calendar");
     public static final String TITLE = "title";
     public static final String ....

并直接使用那些而不是字符串。如果/当 API 更改或公开时,这将让您非常轻松地更改它。

于 2009-05-20T00:20:22.747 回答
2

您可以从这里使用 CalendarContract:https ://github.com/dschuermann/android-calendar-compatibility

它与 Android 4 上可用的 API 类相同,但适用于 Android >= 2.2。

于 2013-02-03T04:19:33.877 回答
1

Nick 的解决方案涉及 managedQuery,在 Context 类中没有定义。很多时候,当您在后台运行时,您会想要使用上下文对象。这是一个修改后的版本:

公共字符串 getCalendarUriBase() {

返回(android.os.Build.VERSION.SDK_INT>=8)?“内容://com.android.calendar”:“内容://日历”;}

此处不应执行对 null 的捕获,因为即使 managedQuery 较早成功,也可能存在更多异常。

于 2011-03-13T03:43:45.873 回答
1

关于可以更改的 API... 整个 ContentProvider 方法不会很快更改,因此仅通过更新字符串就可以克服很多问题。因此,创建您在整个项目中重用的常量。

public static final String URI_CONTENT_CALENDAR_EVENTS = "content://calendar/events";

ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(Uri.parse(URI_CONTENT_CALENDAR_EVENTS), null, null, null, null);
    //etc

如果你想要一个适当的私有 API,你必须创建一个 pojo 和一些这样的服务:

public class CalendarEvent {
    private long id;
    private long date;
    //etc...
}

public interface CalendarService {

    public Set<CalendarEvent> getAllCalendarEvents();

    public CalendarEvent findCalendarEventById(long id);

    public CalendarEvent findCalendarEventByDate(long date);

}

等等。这样,您只需更新 CalendarEvent 对象和此服务,以防 API 发生更改。

于 2010-07-10T17:24:29.720 回答