Android 日历提供器(二)
Calendars表
CalendarContract.Calendars表包含了单个日历的详细信息。下表中Calendars表列对应用程序和同步适配器都是可写的。对于这个表支持的完整的字段列表,请看“CalendarContract.Calendars参考”
http://developer.android.com/reference/android/provider/CalendarContract.Calendars.html
常量 |
描述 |
NAME |
日历的名字 |
CALENDAR_DISPLAY_NAME |
显示给用户的名字 |
VISIBLE |
一个指明被选择的日历是否显示的布尔值。0指明跟这个日历相关联的不应该显示,1指明跟这个日历关联的事件应该显示。这个值会影响CalendarContract.Instances表中行的产生。 |
SYNC_EVENTS |
一个布尔值,指明日历是否应该被同步并在设备上保存其事件。0指明不同步这个日历并在设备上保存事件。1指明同步这个日历并在设备上保存其事件。 |
查询日历
这是一个显示怎样为特定的用户获取所有日历的例子。为了简单明了,在这个列子中,查询操作被写在了用户界面线程中(“主线程”)。实践中,应该用异步线程来替代主线程做这样的事情。
// 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
};
// 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;
接下来要构造查询。Selection变量指定了查询条件。在这个例子中,要查找所有的ACCOUNT_NAME是“sampleuser@google.com”并且ACCOUNT_TYPE是“com.google”的日历。查询会返回一个Cursor对象,你可以用它来遍历数据库查询的结果。
// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;
String selection = “((” + Calendars.ACCOUNT_NAME + " = ?) AND ("
+ Calendars.ACCOUNT_TYPE + " = ?))";
String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google"};
// 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;
// Get the field values
calID = cur.getLong(PROJECTION_ID_INDEX);
displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
// Do something with the values...
...
}
修改日历
你能够通过日历的_ID来执行更新处理,这个ID既可以是附加到Uri(用withAppendedId()方法)中的ID,也可以是第一个选择项目的ID。selection变量应用用“_id=?”开头,并且selectionArg数组的第一个参数应该是这个日历的_ID。也可以通过URI中的编码ID来做更新的处理。下例使用withAppendedId()方法来改变日历的显示名称:
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);
插入日历
Calendars被设计成以同步适配器为主的方式来管理的表,因此你只应该用同步适配器来插入新的日历。大多数情况,应用程序仅能改变日历的外观,如改变显示名字。如果应用程序需要创建一个本地日历,那么它能使用一个ACCOUNT_TYPE_LOCAL的ACCOUNT_TYPE列,通过执行同步适配器的日历插入处理来完成这件事情。ACCOUNT_TYPE_LOCAL是一个特殊的日历账号类型,它不跟设备账号关联。这种类型的日历不同步到服务器。关于同步适配器的讨论,请看“同步适配器”。
Events 表
CalendarContract.Events表包含了单个事件的详细信息。要添加、更新、或删除事件,应用程序必须在它的清单文件中包含WRITE_CALENDAR权限。
以下Events表列通过应用程序和同步适配器都是可写的。对于这个表的完整的字段列表,请看CalendarContract.Events参考。
常量 |
描述 |
CALENDAR_ID |
事件所属的日历的_ID |
ORGANIZER |
事件的组织者(所有者)的电子邮件 |
TITLE |
事件的标题 |
EVENT_LOCATION |
事件发生的地点 |
DESCRIPTION |
事件的描述 |
DTSTART |
事件的启动时间,使用从纪元开始的UTC毫秒计时 |
DTEND |
事件的结束时间,使用从纪元开始的UTC毫秒计时 |
EVENT_TIMEZONE |
事件所针对的时区 |
EVENT_END_TIMEZONE |
针对事件结束时间的时区 |
DURATION |
用RFC5545格式表示的事件持续时间,例如“PT1H”表示事件持续1小时的状态, “P2W”指明2周的持续时间。 |
ALL_DAY |
1指明这个事件会占用整天时间(由本地时区定义的时间);0指明它是一个普通的事件,可以在一天的任何时间开始和结束 |
RRULE |
格式化的事件复发规则(RFC5545)。如“FREQ=WEEKLY;COUNT=10;WKST=SU”。 |
RDATE |
事件的复发日期。通常RDATE要联合RRULE一起使用来定义一个重复发生的事件的合集。 |
AVAILABILITY |
If this event counts as busy time or is free time that can be scheduled over.???? |
GUESTS_CAN_MODIFY |
参与者是否能够修改事件 |
GUESTS_CAN_INVITE_OTHERS |
参与者是否能够邀请其他参与者 |
GUESTS_CAN_SEE_GUESTS |
参与者是否能够看到与会者列表 |
注:RFC5545地址:http://tools.ietf.org/html/rfc5545#section-3.8.2.5
给Events表添加数据
当你的应用程序要插入一个新的事件时,我们推荐你使用INSERT类型Intent对象(在“使用Intent对象来插入事件”一节中介绍)。但是,如果需要,你能够直接插入事件,本节介绍怎样做这件事情。
以下是针对插入一个新的事件的一些规则:
1. 必须包含CALENDAR_ID和DTSTART字段
2. 必须包含EVENT_TIMEZONE字段。使用getAvailableIDs()方法获得系统已安装的时区ID列表。注意如果通过INSTERT类型Intent对象来插入事件,那么这个规则不适用,因为在INSERT对象的场景中会提供一个默认的时区;
3. 对于非重复发生的事件,必须包含DTEND字段;
4. 对重复发生的事件,必须包含一个附加了RRULE或RDATE字段的DURATIION字段。注意,如果通过INSERT类型的Intent对象来插入一个事件,这个规则不适用。因为在这个Intent对象的应用场景中,你能够把RRULE、DTSTART和DTEND字段联合在一起使用,并且Calendar应用程序能够自动的把它转换成一个持续的时间。
以下是插入一个事件的例子,为了简单,这个例子在UI线程中被执行,实际上,插入和更新处理应该在一个后台的线程中异步的执行。有关更多的信息,请看AsyncQueryHandler类
long calID = 3;
long startMillis = 0;
long endMillis = 0;
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 9, 14, 7, 30);
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 9, 14, 8, 45);
endMillis = endTime.getTimeInMillis();
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Events.DTSTART, startMillis);
values.put(Events.DTEND, endMillis);
values.put(Events.TITLE, "Jazzercise");
values.put(Events.DESCRIPTION, "Group workout");
values.put(Events.CALENDAR_ID, calID);
values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
Uri uri = cr.insert(Events.CONTENT_URI, values);
// get the event ID that is the last element in the Uri
long eventID = Long.parseLong(uri.getLastPathSegment());
//
// ... do something with event ID
//
//
注意:看这个例子在事件被创建后是怎样获取这个事件的ID的,这是获取事件ID的最容易的方法,你会经常需要这个事件ID来执行其他的日历操作---如,给事件添加与会者或提醒。
更新事件
当你的应用程序想要允许用户编辑一个事件时,我们推荐你使用EDIT类型的Intent对象,但是如果需要,你能够直接编辑事件。你能够提供要编辑的事件的_ID来执行事件的更新处理,这个ID既可以是附加给Uri的ID(用withAppendedId()方法),也可以是第一个选择项。selection变量应该用“_id=?”来开头,并且selectionArg参数的第一个值应该是这个事件的_ID值。你也能使用没有ID的selection变量来做更新处理。下面的例子更新了用withAppendedId()方法指明的事件的标题。
private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 188;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri updateUri = null;
// The new title for the event
values.put(Events.TITLE, "Kickboxing");
myUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);
删除Events表的数据
你能够使用附加在URI上的_ID来删除一个事件,也能够使用标准的选择条件来删除事件。如果使用一个附加的ID,就不能做选择。有两个删除的版本:以应用程序的方式和以同步适配器的方式。应用程序删除时会把“deleted”列设置为1,这个标记告诉同步适配器,这行已经被删除并且这个删除应该传递给服务端。同步适配器会把事件连同它关联的数据一起从数据库中删除。以下是应用程序通过事件_ID来删除事件的例子:
private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 201;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri deleteUri = null;
deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().delete(deleteUri, null, null);
Log.i(DEBUG_TAG, "Rows deleted: " + rows);
Attendees表
CalendarContract.Attendees表的每一行代表一个事件的单一参与者。用给定的EVENT_ID调用query()方法能够这个事件对应的参与者列表。EVENT_ID必须跟一个特殊的事件匹配。
下表列出Attendees表的可写字段,当插入一个新的与会者时,必须包含ATTENDEE_NAME以外的其他所有字段。
常量 |
描述 |
EVENT_ID |
事件ID |
ATTENDEE_NAME |
与会者的名字 |
ATTENDEE_EMAIL |
与会者的电子邮件地址 |
ATTENDEE_RELATIONSHIP |
与会者与事件的关系,下列值之一 1. RELATIONSHIP_ATTENDEE 2. RELATIONSHIP_NONE 3. RELATIONSHIP_ORGANIZER 4. RELATIONSHIP_PERFORMER 5. RELATIONSHIP_SPEAKER |
ATTENDEE_TYPE |
与会者的类型。下列值之一 1. TYPE_REQUIRED 2. TYPE_OPTIONAL |
ATTENDEE_STATUS |
与会者的与会状态。下列值之一: 1. ATTENDEE_STATUS_ACCEPTED 2. ATTENDEE_STATUS_DECLINED 3. ATTENDEE_STATUS_INVITED 4. ATTENDEE_STATUS_NONE 5. ATTENDEE_STATUS_TENTATIVE |
添加与会者
以下是给一个事件添加一个与会者的例子。注意,EVENT_ID是必须的:
long eventID = 202;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Attendees.ATTENDEE_NAME, "Trevor");
values.put(Attendees.ATTENDEE_EMAIL, "trevor@example.com");
values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
values.put(Attendees.EVENT_ID, eventID);
Uri uri = cr.insert(Attendees.CONTENT_URI, values);
Reminders表
CalendarContract.Reminders表的每一行代表一个事件的一个提醒。用给定的EVENT_ID调用query()方法会返回这个事件的提醒列表。
下表列出了Reminders表的可写字段。当插入一个新的提醒时,必须包含所有这些字段。注意,同步适配器在CalendarContract.Calendars表中指定了支持的提醒的类型。详细内容请看ALLOWED_REMINDERS
http://developer.android.com/reference/android/provider/CalendarContract.CalendarColumns.html#ALLOWED_REMINDERS
常量 |
描述 |
EVENT_ID |
事件的ID |
MINUTES |
提供应该在几分钟之前触发事件。 |
METHOD |
在服务上设置的报警的方法,下列设置之一: 1. METHOD_ALERT 2. METHOD_DEFAULT 3. METHOD_EMAIL 4. METHOD_SMS |
添加提醒
下面的例子给一个事件添加一个提醒,这个体香在事件发生之前15分钟触发
long eventID = 221;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Reminders.MINUTES, 15);
values.put(Reminders.EVENT_ID, eventID);
values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
Uri uri = cr.insert(Reminders.CONTENT_URI, values);
Instances表
CalendarContract.Instances表保存一个事件的开始和结束时间。表中每一行代表一个单一发生的事件。Instances表不是可写的,并且只提供一个查询发生事件的方法。
下表列出了你能够查询的一些字段,注意:时区是由KEY_TIMEZONE_TYPE和KEY_TIMEZONE_INSTANCES字段定义的。
常量 |
描述 |
BEGIN |
这个事件实例的开始时间。UTC毫秒 |
END |
这个事件实例的结束时间。UTC毫秒 |
END_DAY |
这个事件实例的结束日,相对与日历的时区 |
END_MINUTE |
从日历的时区的0时开始计算的事件实例的结束分钟数 |
EVENT_ID |
这个事件实例的事件ID |
START_DAY |
相对日历时区的事件实例的开始日 |
START_MINUTE |
相对日历时区的从0时开始计算的实例事件的开始分钟数 |
查询Instances表
要查询Instances表,你需要在URI中给查询指定一个时间范围。在这个例子中,CalendarContract.Instances类通过CalendarContract.EventsColumns接口的实现获得对TITLE字段的访问。换句话说,TITLE字段是通过一个数据库视图来返回的,而不是通过查询CalendarContract.Instances表获得的。
private static final String DEBUG_TAG = "MyActivity";
public static final String[] INSTANCE_PROJECTION = new String[] {
Instances.EVENT_ID, // 0
Instances.BEGIN, // 1
Instances.TITLE // 2
};
// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_BEGIN_INDEX = 1;
private static final int PROJECTION_TITLE_INDEX = 2;
...
// Specify the date range you want to search for recurring
// event instances
Calendar beginTime = Calendar.getInstance();
beginTime.set(2011, 9, 23, 8, 0);
long startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2011, 10, 24, 8, 0);
long endMillis = endTime.getTimeInMillis();
Cursor cur = null;
ContentResolver cr = getContentResolver();
// The ID of the recurring event whose instances you are searching
// for in the Instances table
String selection = Instances.EVENT_ID + " = ?";
String[] selectionArgs = new String[] {"207"};
// Construct the query with the desired date range.
Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startMillis);
ContentUris.appendId(builder, endMillis);
// Submit the query
cur = cr.query(builder.build(),
INSTANCE_PROJECTION,
selection,
selectionArgs,
null);
while (cur.moveToNext()) {
String title = null;
long eventID = 0;
long beginVal = 0;
// Get the field values
eventID = cur.getLong(PROJECTION_ID_INDEX);
beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
title = cur.getString(PROJECTION_TITLE_INDEX);
// Do something with the values.
Log.i(DEBUG_TAG, "Event: " + title);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(beginVal);
DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));
}
}
Android 日历提供器(二)相关推荐
- Android 内容提供器---简介
内容提供器管理结构化的数据集的访问.它们封装数据.提供定义数据安全的机制.内容提供器是用运行在另一个进程中的代码连接另一个进程中的数据的标准接口. 当你想要访问内容提供器中的数据时,使用应用程序的Co ...
- android内容提供器读取图片,android实现拍照或从相册选取图片
从相册或拍照更换图片功能的实现:(取图无裁剪功能) 获取图片方式: (类似更换头像的效果) 1.手机拍照 选择图片: 2.相册选取图片: 本文只是简单实现该功能,页面展示有些简陋,运行效果图如下: 创 ...
- Android 内容提供器---内容提供器基础(内容的统一资源标识(URIs))
内容URI是在提供器中标识数据统一资源标识.内容的统一资源标识包括完整的提供器的符号名和所指向的一个表名.当你调用一个客户端方法来访问提供器中的一个表时,这个表的内容的统一资源标识就应该是参数之一. ...
- android 本地日历,Android日历提供商:如何删除自己的本地日历?
我正在学习如何使用Android日历.到目前为止,我能够显示有关现有日历的信息.我也可以创建自己的本地日历 - 测试代码如下: private void createCalendarTest() { ...
- Android内容提供器的应用,基于Android的智能终端应用防护系统短信过滤子模块的设计与实现...
摘要: 智能终端随着3G业务的推广而普及,在各种平台的竞争中,Android逐渐占据了主流,谷歌学习苹果的应用商店模式,推出了自己的应用商城.面对应用市场的繁荣,用户的终端安装了形形色色的应用,许多安 ...
- Android内容提供器——运行权限
程序运行是的权限分为两种,一种是普通权限,一种是危险权限.普通权限的话可以直接使用,只有危险权限需要询问用户的同意. 危险权限分组以及组内权限如下: 注:危险权限同一组内有一项权限被授权,则一组权限都 ...
- Android 日历开发教程[二]
一.创建 Android Project 在新建对话框中输入 App 属性,SDK版本全部选最新的,不作版本兼容.主题选择 Holo Dark. 下一步,使用默认设置 下一步,使用默认设置 下一步,使 ...
- Android核心服务解析篇(二)——Android源码结构分析
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 获得Android源码后,我们来分析源码结构.源码的全部工程分为如下三个部分. ①Core Project:核心工程部分,这是建 ...
- Android FFmpeg视频播放器三 音频封装格式解码播放
Android FFmpeg视频播放器一解封装 Android Android FFmpeg视频播放器二 视频封装格式解码播放 视频解封装之后就会得到音频流和视频流,解封状得到的数据是AVPackag ...
最新文章
- Machine learning of neural representations of suicide and emotion concepts identifies suicidal youth
- FLASH免激活js
- 关节点(atriculation point)算法
- 兼容单片机的CRC32查表计算程序的C语言实现
- 操作系统实验报告5:进程的创建和终止
- 【线程安全】—— 单例类双重检查加锁(double-checked locking)
- onvif协议之抓图
- thinkphp5 没有 $this->ajaxReturn
- 知其然知其所以然 itoa实现 整型转字符串
- USB数据采集卡,Labjack系列 U12、 U3-HV、T7 测量电流的方法
- 【微机原理】40道简答题
- 3.2-上位机与下位机的“私有协议”通信构架设计
- 高斯-约当消元法(转)
- 单点登录,统一登录平台的食堂打饭模型
- java xml transformer_java xml transformer.transform 无故增加换行
- JavaWeb项目 Web.xml文件详解(启动顺序)
- python图像处理(十)——图像仿射变换、图像透视变换和图像校正
- 怎么制作GIF 制作动态图的软件哪个好
- 核密度函数详解,核密度函数图如何看?
- PHP预设的配置模板,YzmCMS默认模板说明
热门文章
- 【SRS】ATC介绍
- Quartus II11.0破解注意
- QPainter 绘制阴影边界
- The file Tomcat8.exe was not found... Either the CATALINA_HOME environment variable is not defined c
- 转变:从SQL技术栈到图技术栈
- ESP8266扫描中文名称wifi问题
- Java class文件查看对应的JDK版本
- java ace admin_ace-admin-master
- 实用的latex符号
- python黑客帝国代码雨特效