您的位置:首页 > 移动开发 > Android开发

Android - Calendar Provider(未完待续)

2013-05-19 11:27 120 查看


Calendar Provider

Calendar Provider 是一个存放用户日历事件的库,它提供的API,可以让你执行查询,插入,更新和删除日历,事件,参加者,提醒等等操作。

Calendar Provider 提供的API可以在应用程序和同步适配器中使用,它的规则取决于程序调用什么样的类型。本篇文章主要侧重于在应用程序中使用Calendar Provider API,对于同步适配器如何使用,请参阅 同步适配器

通常情况下,读取或写入日历数据,必须在应用程序的清单文件中添加适当的权限,为了使执行常见操作更容易,Calendar
Provider提供了Intents,如Calendar Intents。这些 Intents 可以让用户进入到日历程序进行查看,插入,修改事件,用户跳转到日历应用后可以返回到原来的应用程序,因此 您的应用程序并不需要权限配置,也不需要提供一个用户界面来查看或创建事件。


基础

Content Provider 提供了数据和应用程序之间的访问,Android平台(包括Calendar Provider)通常是通过Content Provider来公开数据,是基于关系型数据模型,其中的每一行是一个记录,每一列是一个特定的类型和含义的数据的一张表。通过 Calendar
Provider API 应用程序和同步适配器可以持续的读取/查看用户的日历数据。

每个 Content Provider 会公开一个 public 的 URI 来唯一标识这个数据集,一个 Content Provider 控制多个数据集(数据表)必须的为每一个数据集定义一个单独的URI。提供的URI必须以 "content://"
字符串开头,这些标识由 Content provider 控制,所以 Calendar
Provider 的每一个类都定义了一个 <class>.CONTENT_URI 的常量,比如说 Events.CONTENT_URI .

下图示出的日历提供者的数据模型的图形表示了其主表和字段,并将其链接到对方。



一个用户可以有多个日历,不同的日历关联不同的账户(Google 日历,Exchange,等等)

CalendarContract 提供了关于日历和时间的相关数据模型(类),这些数据存放在多个表中。下面一一列举

表(类)描述
CalendarContract.Calendars
此表包含日历的具体信息。
在此表中的每一行包含一个日历的详细信息,如名称,颜色,同步信息,等等。
CalendarContract.Events
此表包含事件的具体信息。
在此表中的每一行的信息,一个单一的事件,例如,事件标题,地点,开始时间,结束时间,等等。
该事件可能发生一次性或多次重复,Attendees,reminders和extended properties存储在单独的表中。
他们都有一个EVENT_ID,在事件表中引用为_ID。
CalendarContract.Instances该表保存每一个事件的发生的开始和结束的时间。

在此表中的每一行代表一个单独的事件的发生。

对于一次性的事件,事件的实例是一个1:1的映射。对于周期性事件,多行自动生成对应该事件多次出现。
CalendarContract.Attendees此表保存事件与会者(游客)信息。

每一行代表一个单一的住客的事件。指定类型的客人,客人的出席响应的事件。
CalendarContract.Reminders这个表保存警报/通知数据。

每一行代表一个单一的事件警,一个事件可以有多个提醒。

提醒每个事件的最大数目指定的 MAX_REMINDERS,这是由拥有给定日历同步适配器。

提醒被指定在活动开始前的几分钟,有一个方法,决定如何将提醒用户。
Calendar Provider API 被设计得非常灵巧和强大,同时提供了一个良好的用户体验和保护日历和数据的完整性。为此使用API时有一些事情要记住:

插入,更新和查看日历事件

插入,修改和读取从日历中的事件,你需要相应的权限,然而,如果你没有建立一个完整的日历应用程序或同步适配器,要求这些权限是没有必要的。相反,您可以使用支持Android的日历应用程序 Intent,关闭该应用程序的读取和写入操作,当您使用Intent,您的应用程序把用户带入到日历应用程序,在预充的形式执行所需的操作。他们做完后,会返回到您的应用程序。设计你的应用程序通过日历执行常见操作,为用户提供了一个一致的,强大的用户界面,这是推荐的方法。欲了解更多信息,请参阅
Calendar Intents

同步适配器

一个同步适配器让用户的设备上的日历数据与其他服务器或数据源同步。在CalendarContract.Calendars和CalendarContract.Events表,同步适配器使用保留的列。Provider 和应用程序不应该修改它们。事实上,他们是不可见的,除非他们是作为一个同步适配器访问。如需有关同步适配器的更多信息,请参阅 同步适配器

用户权限

读取日历数据必须在清单文件中添加读取权限,写入日历数据必须在清单文件中添加写入权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"...>
    <uses-sdk android:minSdkVersion="14" />
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
    ...
</manifest>


日历表

CalendarContract.Calendars 表包含个人日历的详细信息。下面的日历列写的应用程序和同步适配器。支持字段的完整列表,请参阅 CalendarContract.Calendars

常量描述
NAME日历名称
CALENDAR_DISPLAY_NAME显示给用户的日历的名称被
VISIBLE一个布尔值指示是否选择要显示的日历,与此日历关联的事件不应该显示0。

值为1表示应与此日历事件所示,这个值会影响行代在 CalendarContract.Instances 表。
SYNC_EVENTS一个布尔值,表示是否应该同步日历,并存储在设备上的事件。

值为0表示不同步日历或存储设备上的事件;

值为1表示该日历的同步事件和存储设备上的事件。

查询日历

下面是一个例子,显示了如何获得一个特定的用户所拥有的日历。为了简单起见,在本例中,查询的操作显示在用户界面线程(主线程)。在实践中,这应该是一个异步线程的,而不是在主线程。对于更多的讨论,请参阅 Loaders 。如果你不只是读取数据,还要修改它,请参阅 AsyncQueryHandler

// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
public static final String[] EVENT_PROJECTION = new String[] {
    Calendars._ID,                           // 0
    Calendars.ACCOUNT_NAME,                  // 1
    Calendars.CALENDAR_DISPLAY_NAME,         // 2
    Calendars.OWNER_ACCOUNT                  // 3
};
  
// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;


在接下来的例子中,你构建你的查询,指定查询条件。
在这个例子中,查询为有ACCOUNT_NAME = "sampleuser@google.com",ACCOUNT_TYPE = "com.google",OWNER_ACCOUNT = "sampleuser@google.com" 的日历。
如果你想看到所有日历查看,用户已不只是日历用户拥有者,请省略 OWNER_ACCOUNT 。
该查询返回一个Cursor对象,你可以用它来遍历由数据库查询返回的结果集。如需使用查询内容提供商的更多讨论,请参阅 Content Provider

// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;   
String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
                        + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                        + Calendars.OWNER_ACCOUNT + " = ?))";
String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
        "sampleuser@gmail.com"}; 
// Submit the query and get a Cursor object back. 
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);


下一节使用游标遍历结果集。

// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    long calID = 0;
    String displayName = null;
    String accountName = null;
    String ownerName = null;
      
    // Get the field values
    calID = cur.getLong(PROJECTION_ID_INDEX);
    displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
    accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
    ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
              
    // Do something with the values...

   ...
}


修改日历

private static final String DEBUG_TAG = "MyActivity";
...
long calID = 2;
ContentValues values = new ContentValues();
// The new display name for the calendar
values.put(Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar");
Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);


增加日历

日历被设计为主要管理同步适配器,所以你应该只使用一个同步适配器插入新的日历。在大多数情况下,应用程序可以仅使表面的变化,如改变的显示名称日历。如果一个应用程序需要创建一个本地的日历,它可以做到这一点进行日历同步适配器插入,使用的ACCOUNT_TYPE_LOCAL ACCOUNT_TYPE。 ACCOUNT_TYPE_LOCAL是一种特殊的帐户类型,不与设备帐户的日历。这种类型的日历都不会同步到服务器。同步适配器的讨论,请参阅 同步适配器
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: