转自Android向系统日历中添加日程事件

总结

在项目开发中,我们有预约提醒、定时提醒需求时,可以使用系统日历来辅助提醒;

通过向系统日历中写入事件、设置提醒方式(闹钟),实现到时间自动提醒的功能;

好处:由于提醒功能是交付给系统日历来做,不会出现应用被杀情况,会准时提醒;

坏处:系统日历在提醒时,不能直接再跳转回我们自己的app,只有在提醒文案中加入url,通过调用浏览器来中转;

一般来说实现向系统日历中读写事件:

  • 1.需要有读写日历权限
  • 2.如果没有日历账户需要先创建账户
  • 3.实现日历事件增删改查、提醒功能

申请权限

为了实现在项目中调用系统日历和插入日程事件,我们首先在AndroidManifest.xml文件中添加相关权限,如下:

<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />

添加日历相关的uri

系统calendar content provider相关的uri,以下为Android2.2版本以后的uri,之前的就不写了

private static String CALANDER_URL = "content://com.android.calendar/calendars";
private static String CALANDER_EVENT_URL = "content://com.android.calendar/events";
private static String CALANDER_REMIDER_URL = "content://com.android.calendar/reminders";

检查并添加日历账户

1.检查是否有现有存在的账户。存在则返回账户id,否则返回-1

private static int checkCalendarAccount(Context context) {
Cursor userCursor = context.getContentResolver().query(Uri.parse(CALANDER_URL), null, null, null, null);
try {
if (userCursor == null)//查询返回空值
return -1;
int count = userCursor.getCount();
if (count > 0) {//存在现有账户,取第一个账户的id返回
userCursor.moveToFirst();
return userCursor.getInt(userCursor.getColumnIndex(CalendarContract.Calendars._ID));
} else {
return -1;
}
} finally {
if (userCursor != null) {
userCursor.close();
}
}
}

2.添加账户。账户创建成功则返回账户id,否则返回-1

private static String CALENDARS_NAME = "test";
private static String CALENDARS_ACCOUNT_NAME = "test@gmail.com";
private static String CALENDARS_ACCOUNT_TYPE = "com.android.exchange";
private static String CALENDARS_DISPLAY_NAME = "测试账户"; private static long addCalendarAccount(Context context) {
TimeZone timeZone = TimeZone.getDefault();
ContentValues value = new ContentValues();
value.put(CalendarContract.Calendars.NAME, CALENDARS_NAME); value.put(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME);
value.put(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE);
value.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, CALENDARS_DISPLAY_NAME);
value.put(CalendarContract.Calendars.VISIBLE, 1);
value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE);
value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
value.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
value.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, timeZone.getID());
value.put(CalendarContract.Calendars.OWNER_ACCOUNT, CALENDARS_ACCOUNT_NAME);
value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0); Uri calendarUri = Uri.parse(CALANDER_URL);
calendarUri = calendarUri.buildUpon()
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME)
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE)
.build(); Uri result = context.getContentResolver().insert(calendarUri, value);
long id = result == null ? -1 : ContentUris.parseId(result);
return id;
}

3.获取账户。如果账户不存在则先创建账户,账户存在获取账户id;获取账户成功返回账户id,否则返回-1

//检查是否已经添加了日历账户,如果没有添加先添加一个日历账户再查询
private static int checkAndAddCalendarAccount(Context context){
int oldId = checkCalendarAccount(context);
if( oldId >= 0 ){
return oldId;
}else{
long addId = addCalendarAccount(context);
if (addId >= 0) {
return checkCalendarAccount(context);
} else {
return -1;
}
}
}

添加日历事件、日程

public static void addCalendarEvent(Context context,String title, String description, long beginTime){
// 获取日历账户的id
int calId = checkAndAddCalendarAccount(context);
if (calId < 0) {
// 获取账户id失败直接返回,添加日历事件失败
return;
} ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
// 插入账户的id
event.put("calendar_id", calId); Calendar mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(beginTime);//设置开始时间
long start = mCalendar.getTime().getTime();
mCalendar.setTimeInMillis(start + ONE_HOUR);//设置终止时间
long end = mCalendar.getTime().getTime(); event.put(CalendarContract.Events.DTSTART, start);
event.put(CalendarContract.Events.DTEND, end);
event.put(CalendarContract.Events.HAS_ALARM, 1);//设置有闹钟提醒
event.put(CalendarContract.Events.EVENT_TIMEZONE, "Asia/Shanghai"); //这个是时区,必须有,
//添加事件
Uri newEvent = context.getContentResolver().insert(Uri.parse(CALANDER_EVENT_URL), event);
if (newEvent == null) {
// 添加日历事件失败直接返回
return;
}
//事件提醒的设定
ContentValues values = new ContentValues();
values.put(CalendarContract.Reminders.EVENT_ID, ContentUris.parseId(newEvent));
// 提前10分钟有提醒
values.put(CalendarContract.Reminders.MINUTES, 10);
values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
Uri uri = context.getContentResolver().insert(Uri.parse(CALANDER_REMIDER_URL), values);
if(uri == null) {
// 添加闹钟提醒失败直接返回
return;
}
}

删除日历事件、日程

根据设置的title来查找并删除

public static void deleteCalendarEvent(Context context,String title){
Cursor eventCursor = context.getContentResolver().query(Uri.parse(CALANDER_EVENT_URL), null, null, null, null);
try {
if (eventCursor == null)//查询返回空值
return;
if (eventCursor.getCount() > 0) {
//遍历所有事件,找到title跟需要查询的title一样的项
for (eventCursor.moveToFirst(); !eventCursor.isAfterLast(); eventCursor.moveToNext()) {
String eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
if (!TextUtils.isEmpty(title) && title.equals(eventTitle)) {
int id = eventCursor.getInt(eventCursor.getColumnIndex(CalendarContract.Calendars._ID));//取得id
Uri deleteUri = ContentUris.withAppendedId(Uri.parse(CALANDER_EVENT_URL), id);
int rows = context.getContentResolver().delete(deleteUri, null, null);
if (rows == -1) {
//事件删除失败
return;
}
}
}
}
} finally {
if (eventCursor != null) {
eventCursor.close();
}
}
}

至此,我们就能向系统日历中 查找、添加账户,添加、删除、更新日程事件,添加提醒方式,来实现提醒用户的需求。

再次说明一点,当系统日历弹出提醒的时候并不能直接跳转回自己的app,需要在设置description字段的文本中添加一个html,用户点击html时调用浏览器,由页面中转回自己得app。

Android向系统日历中添加日程事件的更多相关文章

  1. Android 向系统日历中添加事件

    查了一天半,总算有点大概了.以下是自己的理解,有错误的地方望指正. android系统有日历功能,应用程序可以根据一些接口开发自己的功能,即使是日历app也是根据这些接口开发的,所以我们可以利用程序向 ...

  2. Android向系统日历添加日程提醒事件

    在项目开发过程中,有时会有预约提醒.定时提醒等需求,这时我们可以使用系统日历来辅助提醒.通过向系统日历中写入事件.设置提醒方式(闹钟),实现到达某个特定的时间自动提醒的功能.这样做的好处是由于提醒功能 ...

  3. 除了信号触发线程与接收者线程相同的情况能直接调用到slot,其它情况都依赖事件机制(解决上面代码收不到信号的问题其实很简单,在线程的run();函数中添加一个事件循环就可以了,即加入一句exec();),信号槽不就是一个回调函数嘛

    MainWindow::MainWindow(QWidget *parent) :   QMainWindow(parent)   {   pThreadCon = new CSerialThread ...

  4. 【定制Android系统】Android O 在ROM中添加自己的 so 库(1)——Android.mk 与 Android.bp 的区别【转】

    本文转载自: 版权声明:本文为博主原创文章,转载时请注明原作者及出处.    https://blog.csdn.net/u014248312/article/details/82020204需求:在 ...

  5. Android 获取系统相册中的所有图片

    Android 提供了API可获取到系统相册中的一些信息,主要还是通过ContentProvider 来获取想要的内容. 代码很简单,只要熟悉ContentProvider 就可以了. public ...

  6. 关于ios苹果系统的中的右键事件,查遍了全网都没有的小技巧。

    前阵子公司要求写一套手机端,兼容各种平台和系统,当然,pc端也没有放过. 我用了bootstrap框架和jq.在安卓中的右键事件只需要取消浏览器默认事件,然后长按就可以触发pc端的右键事件,非常好,一 ...

  7. Android Studio] Gradle项目中添加JNI生成文件(.so文件)

    转:http://blog.csdn.net/qiujuer/article/details/24209457 为了适应潮流使用Android Studio还是有半年多了! 对于从Eclipse迁移项 ...

  8. mfc 小程序---在系统菜单中添加菜单项

    1建立一个对话框工程:在dlg类里定义一个菜单指针m_pMenu,在对话框OnInitDialog函数里添加代码: m_pMenu=GetSystemMenu(FALSE);//获取系统菜单的指针 m ...

  9. Android Tips: 在给drawable中添加图片资源时,文件名必须全小写

    在给drawable中添加图片资源时,文件名必须全小写

随机推荐

  1. 世界上最好的Sed教程

    这是一份世界上最好的sed教程,sed是unix系统下流编辑里的超人.最初我写这份说明是为了我的 第二本电子书,然而随后我决定把这份说明变成一本免费电子书预览的同时再次做为文章发布到这里. Sed说明 ...

  2. Shell脚本的学习笔记二:字符串

    菜鸟教程提供的Shell在线编辑器 Shell 字符串 项目 功能 单引号 原样输出,变量无效.但可用成对单引号嵌套成对单引号输出变量 双引号 定义字符串中附带有变量的命令并且想将其解析后再输出的变量 ...

  3. php优秀框架codeigniter学习系列——CI_Output类的学习

    这篇文章主要介绍CI核心框架工具类CI_Output. 根据CI文档自己的定义,这个类主要就是生成返回的页面给浏览器.以下选取类中的重点方法进行说明. __construct() 在构造函数中,主要确 ...

  4. 外网访问SQLServer数据库holer实现

    外网访问内网SQLServer数据库 内网主机上安装了SQLServer数据库,只能在局域网内访问,怎样从公网也能访问本地SQLServer数据库? 本文将介绍使用holer实现的具体步骤. 1. 准 ...

  5. element-ui Select 清空model,页面没有清空选中项的问题

    业务场景: 在dialog 每次打开时, 选择应用程序要初始化为空. 最初的做法为: 监听dialog的show状态,当show为false时,设置selectApp为空这样写时,虽然selectAp ...

  6. 剑指Offer 6. 旋转数组的最小数字 (数组)

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋 ...

  7. Flink实战(1) - Apache Flink安装和示例程序的执行

    在Windows上安装 从官方网站下载需要的二进制包 比如我下载的是flink-1.2.0-bin-hadoop2-scala_2.10.tgz,解压后进入bin目录 可以执行bat文件,也可以使用c ...

  8. ggplot2 multiply graphs on one figure

    library(ggplot2)library(grid)grid.newpage()pushViewport(viewport(layout = grid.layout(1,2)))vplayout ...

  9. js post下载相当于 location.href

    /** *参数说明: url:下载地址,val:需要提交的参数值,具体类型和个数自行扩展 * 参数可以用obj = {url:""",val1:"111&quo ...

  10. (27)session(设置值、取值、修改、删除)

    session的由来 Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西, ...