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

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

【问题讨论】:

    标签: android android-calendar


    【解决方案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 较早成功,也可能存在更多异常。

          【讨论】:

            猜你喜欢
            • 2012-07-21
            • 2013-12-10
            • 2018-06-03
            • 2016-07-04
            • 2018-12-01
            • 2016-05-12
            • 2017-09-11
            • 2022-12-07
            • 2016-01-10
            相关资源
            最近更新 更多