有没有办法在不使用 gdata-java-client 的情况下访问日历的条目?

Posted

技术标签:

【中文标题】有没有办法在不使用 gdata-java-client 的情况下访问日历的条目?【英文标题】:Is there a way to access the calendar's entries without using gdata-java-client? 【发布时间】:2010-10-25 05:16:52 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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 文章中提供的 open source test code 获得了这种方法。

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

【讨论】:

【参考方案2】:

这些答案很好,但它们都涉及对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,这需要被调用方法捕获或重新抛出。

【讨论】:

请注意,这不再适用于 API 14。有一个用于日历 (14+) here 的官方 API,其中涉及使用新的 `CalendarContract' 类【参考方案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 更改或公开时,这将让您非常轻松地更改它。

【讨论】:

谢谢!顺便说一句,您是否可以使用日历(通过从源代码构建 2 apk)和来自 DevTools 的“Google 登录服务”与最新的 SDK(1.5 R1)? 谷歌登录服务是谷歌专有的东西,除非你有一部真正的手机,否则它总是会崩溃。我没试过日历。【参考方案4】:

您可以使用日历内容提供程序 (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's post),因为它目前是私有 API。

【讨论】:

是的,但这是一个可能随时中断的私有 API。 您是绝对正确的,您的包装器显然是一个非常好的主意,即使当/如果它们更改某些内容时您仍然必须返回应用程序的代码。一旦 API 公开,包装器可能已经过时了。【参考方案5】:

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

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

【讨论】:

【参考方案6】:

关于可以更改的 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 发生变化。

【讨论】:

【参考方案7】:

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

公共字符串 getCalendarUriBase()

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

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

【讨论】:

以上是关于有没有办法在不使用 gdata-java-client 的情况下访问日历的条目?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在不使用循环的情况下获得价值?

有没有办法在不使用pairs()的情况下循环遍历数组?

有没有办法在不使用 viola-jones 算法的情况下用 opencv 检测人脸? [关闭]

有没有办法在不使用子查询的情况下根据不同的行计算平均值?

有没有办法在不应用存储库基类的情况下使用存储库?

有没有办法在不使用游标的情况下循环遍历 SQL 中的表变量?