有没有办法在不使用 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 的情况下访问日历的条目?的主要内容,如果未能解决你的问题,请参考以下文章