记一次向系统日历写入数据的经历

       最近接到一个向系统日历里写入事件的需求,因为以前没作过这个,猜想多是系统数据库的增删改查操做。可是第一次听到这个需求仍是有点慌的,万一各个不一样厂商要分别处理怎么办,万一低版本系统不支持怎么办,因此我第一时间对这个功能进行了调研。出乎意外地顺利地是,只须要网上一搜索“android 写入日历事件”,便有了不少的结果,在此必须感谢大牛们的无私分享,也坚决了本身要多写博客的信心,因此今天把我处理日历需求的通过给你们分享一下。java

系统的日历数据库是哪一个,什么是日历帐号,如何申请本身的日历帐号?

       这里直接贴出代码中使用到的数据库uri以及日历帐户,其中前三个是系统数据库的uri,这里咱们一一来解释。第一个是日历数据库的总uri,必需要有这个uri才能打开系统的日历数据库。第二个是事件uri,若是想向日历中插入事件,在系统的contentResolver中传入这个key。第三个是给系统添加提醒,有了这个提醒之后,到点了就会在通知栏显示出日历通知(固然前提是app有通知栏权限)。最后的4个都是本app在系统日历中的帐户信息,用来给系统做区分的,随便填填就行了android

private static String CALENDER_URL = "content://com.android.calendar/calendars";
private static String CALENDER_EVENT_URL = "content://com.android.calendar/events";
private static String CALENDER_REMINDER_URL = "content://com.android.calendar/reminders";
private static String CALENDARS_NAME = "aaaa";
private static String CALENDARS_ACCOUNT_NAME = "aaaa@aaaa.com";
private static String CALENDARS_ACCOUNT_TYPE = "com.android.aaaa";
private static String CALENDARS_DISPLAY_NAME = "aaaa帐户";复制代码

检查是否有日历帐号,若是没有帐号就添加一个git


添加日历帐户也是数据库操做,具体代码以下:github


代码来操做系统日历须要什么权限?数据库

在安卓生态中,作不少操做都须要权限,更别提这是操做系统日历了。读写日历权限分别是bash

Manifest.permission.READ_CALENDAR复制代码
Manifest.permission.WRITE_CALENDAR复制代码

首先咱们要在manifest里面静态申请一下app

<uses-permission android:name="android.permission.READ_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>复制代码

其次,为了知足高API要求,还须要在实际使用的地方动态申请日历权限,代码以下,这里面的rxjava代码暂时不看,后面会讲到测试


应该怎么样去写入和删除日历?       spa

写入和删除日历其实就是系统数据库操做,这些代码很是简单,基本复制过去就可使用。我这里不直接贴代码是由于排版会错乱,后面我会贴上另一个写得比较好的帖子的连接,我也是从那里参考来的,感兴趣的话能够去那边复制。以下图,设置好了日历须要的参数,而后调用系统contentResolver的insert方法进行写入到库中以及提醒中,其中event.put(CalendarContract.Events.DTSTART, start);操作系统

就是设置提醒的时间,时间是以毫秒为单位


删除也是同样,调用数据库方法便可


坑点来了,这是满满的干货

按照上面的方式半个小时就调通了写入和删除日历功能,可是通常解决问题的时间比实际功能开发的时间老是要多很多,否则就不会出现那么多的bug了。哈哈,废话少说,直接干货送上

坑点一  个别手机在插入日历的时候会crash

安卓生态就是这么奇葩,各类各样的定制系统,各类各样的系统版本,因此咱们无法测试到全部手机的兼容性,正因如此,因此才会常常碰到很奇怪的问题。在插入的时候报错了,具体错误以下:


定位到这行错误的源码出,就是在写入日历时失败了,报了一个空指针。出现的几率很低,是在SIMULATOR 6.0.1的版本上出现的,这手机确实不多见,没人知道是什么状况,可是问题仍是要解决一下滴,否则crash率就降不下来了。因为是系统插入失败,因此这里很差干预,我是直接作了一个try..catch处理了,反正不报bug心情就舒畅了哈哈。


坑点二 部分手机明明没有日历权限,系统给你返回有权限

这问题真的是头痛了半天,这里必须吐槽一下。出问题的是oppo r9手机上,用户关闭了日历权限之后,系统给返回有权限,可是又写不进去日历。吐槽完了,问题仍是得本身来解决,谁让测试小姐姐那么可爱呢。通过我一整套流程的debug,发现只要没权限,系统给返回的cursor必定是为null的,这样就有了解决思路了,只须要在每次执行插入和删除前多加一个cursor是否为null的判断就行了,说干就干,代码以下:


这就是前面在申请权限是有那么多的CalendarReminderUtils.isNoCursor(App.getInstance())的缘由,这也是对碎片化满满的无奈啊。。。


坑点三 如何判断是否添加成功

上面说到了部分手机可能在没权限的时候返回有权限,那么在添加之后就不能保证目前百分百添加成功了。若是添加失败了,就应该给一个弹框或者提示。我这里只能是在添加后再判断一下系统数据库中是否有数据,若是没有数据的话就弹无权限的框,为了兼容那少部分手机也是没办法了,必须多作不少的操做。这里若是没权限,就调用showWaringDialog方法来显示弹框提示用户要给日历权限



坑点四 须要先删除以前的提醒再添加,不支持修改

       最初的话是每调用一次就添加一个提醒,因此后面日历里都塞满了相似的提醒,感受真的很low,而日历数据库又不支持修改,因此须要注意的是每次在新增时须要考虑是否须要删除以前的日历,否则日历里就会愈来愈多重复的事件。在删除后,再添加具体的新日历提醒,具体代码以下图:


坑点五 有些手机上删除不了日历事件

       这是在一台三星手机上复现的,其余国内品牌手机都没有这问题。就是调用了系统的删除日历代码,也没有报任何错误,可是去系统数据库查找的时候那条日历事件仍是存在,和没删除一个样。

       这个问题是在stackoverflow上面找到了答案,说是三星手机删除日历事件是属于软删除,即将deleted这个flag置为0的方式来删除,三星也喜欢玩非大众化,否则我们拥有强大心脏的安卓开发者早就已经习惯了。

这个解决方法是在查询时加一个条件,就是deleted != 1,由于被删除了在三星上就是0


总结:android向日历中写入事件整体来讲仍是比较简单的,没有想象中不一样平台不一样实现方式那么恐怖,网上的例子不少,拷贝过去稍微改改就能用了,有需求的能够在下面的连接中复制代码,我这里就再也不赘述了。因此基本实现不太值钱,可是实际项目中碰到的坑点就很可贵了,我这里已经把我碰到的坑点都列举了出来,但愿能对你们有所帮助。

demo地址:github.com/dongrong-fu…

相关文章
相关标签/搜索