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

时间:2022-09-08 11:04:23

转自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&lpar;&rpar;&semi;函数中添加一个事件循环就可以了,即加入一句exec&lpar;&rpar;&semi;),信号槽不就是一个回调函数嘛

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

  4. 【定制Android系统】Android O 在ROM中添加自己的 so 库(1)——Android&period;mk 与 Android&period;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&rsqb; Gradle项目中添加JNI生成文件&lpar;&period;so文件&rpar;

    转: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&colon; 在给drawable中添加图片资源时,文件名必须全小写

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

随机推荐

  1. &period;NET跨平台之旅:基于&period;NET Core改写EnyimMemcached,实现Linux*问memcached缓存

    注:支持 .NET Core 的 memcached 客户端 EnyimMemcachedCore 的 NuGet 包下载地址:https://www.nuget.org/packages/Enyim ...

  2. Django实现注册

    前言 对于web开来说,用户登陆.注册.文件上传等是最基础的功能,针对不同的web框架,相关的文章非常多,但搜索之后发现大多都不具有完整性,对于想学习web开发的新手来说不具有很强的操作性:对于web ...

  3. Java对象生命周期

    [TOC] 1. 创建阶段(Created) 为对象分配存储空间 开始构造对象 从父类到子类对static成员进行初始化 父类成员变量按照顺序初始化,递归调用父类的构造方法 子类成员变量按照顺序初始化 ...

  4. Java正则表达式:Pattern类和Matcher类

    一.捕获组的概念 捕获组可以通过从左到右计算其开括号来编号,编号是从1 开始的.例如,在表达式 ((A)(B(C)))中,存在四个这样的组: 1     ((A)(B(C))) 2     (A) 3 ...

  5. Asp&period;NET路由管道处理过程 【重要】

    当ASP.NET处理请求时,路由管道主要由以下几个步骤组成: 1.UrlRoutingModule尝试使用RouteTable中注册的理由匹配当前请求: 2.如果RouteTable中有一个路由成功匹 ...

  6. 等价路由在路由器和CE交换机上默认的行为是不同的,路由器总是走第一个下一跳,CE交换机是逐包。

    结论: 1.在eNSP中实验,路由器和CE交换机对于等价路由的默认转发行为是不同的, 路由器:默认是基于流的转发形态,更准确的来讲,ping两个不同的下一跳,都是走等价路由的第一个路由,不走第二条路由 ...

  7. 【python接口自动化框架-unittest】【一】unittest单元测试框架概念

    一.unittst单元测试框架 概念参考:https://docs.python.org/2/library/unittest.html 使用方法:import unittest (引入unittes ...

  8. verilog中的多维数组

    reg  arrayb [7:0] [0:255] ;//二维数组.

  9. VMware虚拟机打开后不兼容

    在版本VMware Workstation10.0设置兼容性,在编辑——首选项——工作空间——设置EXS兼容.计算机工作区域打开虚拟机,右键管理.兼容性从新配置

  10. Python 类的多继承

    #类的多继承 ''' 与c++不同,python的类经过优化,多继承时不会产生方法二义性 ''' #python中所有的类都是默认继承于object类 class A(object): def tes ...