Android Studio 基础 之 获取系统Calendar 日历日程(可获得当天以后可设定天数范围内的日历日程) (涉及指定日期时间判断是星期几的方法使用)的方法整理

 

目录

Android Studio 基础 之 获取系统Calendar 日历日程(可获得当天以后可设定天数范围内的日历日程) (涉及指定日期时间判断是星期几的方法使用)的方法整理

一、简单介绍

二、实现原理

三、注意实现

四、效果预览

五、实现步骤

六、关键代码

日历日程一些有用的基础知识点:


 

一、简单介绍

Android 开发中的一些基础操作,使用整理,便于后期使用。

本节介绍,Android 开发中,获取手机设备的系统Calendar 的 日历日程的方法,方法不唯一,欢迎指正。

 

二、实现原理

1、getContentResolver().query(Uri.parse(CALENDER_EVENT_URL), null, null, null, "dtstart"+" DESC");

获取日历日程事件 Cursor,然后循环获取每个日程事件

2、getContentResolver().query(Uri.parse(CALENDER_EVENT_URL), null, null, null, "dtstart"+" DESC");

"dtstart"+" DESC",实现日历日程事件按日程事件开始时间降序排序得到日程事件结果

3、Cursor.getString(eventCursor.getColumnIndex("title")) 得到日程事件标题

4、Cursor.getString(eventCursor.getColumnIndex("description")) 得到日程事件描述

5、Cursor.getString(eventCursor.getColumnIndex("eventLocation")) 得到日程事件位置

6、Cursor.getString(eventCursor.getColumnIndex("dtstart"))  得到日程事件开始时间

7、Cursor.getString(eventCursor.getColumnIndex("dtend")) 得到日程事件结束时间

8、Calendar.getInstance().setTime(format.parse("yyyy-MM-dd HH:mm:ss")) 判断指定日期时间是星期几

 

三、注意实现

1、添加Calendar 相关权限

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

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

 

2、getContentResolver().query() 最后一个参数进行数据排序,这里是 "dtstart"+" DESC" 日程事件开始时间降序排序, "dtstart"+" AXSC" 日程事件开始时间升序排序

 

四、效果预览

Android 日历开发 androidstudio日历代码_Android 日历开发

 

五、实现步骤

1、打开 Android Studio 新建一个工程,或者新建一个模块

Android 日历开发 androidstudio日历代码_Android_02

 

2、默认操作,一路创建一个模块

Android 日历开发 androidstudio日历代码_日历日程事件_03

Android 日历开发 androidstudio日历代码_Android Studio_04

Android 日历开发 androidstudio日历代码_Android_05

 

3、创建一个 calendarUtil,编写获取日程日志事件的方法,CalenderDataStruct 日历日程事件的结构体

Android 日历开发 androidstudio日历代码_Android Studio_06

Android 日历开发 androidstudio日历代码_Android 日历开发_07

 

4、MainActivity ,测试 calendarUtil封装的方法

Android 日历开发 androidstudio日历代码_日历日程事件_08

 

5、打包,在设备上测试,效果如上

Android 日历开发 androidstudio日历代码_Calendar_09

 

六、关键代码

1、CalenderDataStruct

package com.example.calendartest;

/**
 * 日历日程数据结构
 */
public class CalenderDataStruct {
    String eventTitle = "";
    String startTime = "";
    String endTime = "";
    String description = "";
    String location = "";
    String week = "";

    public CalenderDataStruct(String eventTitle, String startTime, String endTime, String description, String location,String week) {
        this.eventTitle = eventTitle;
        this.startTime = startTime;
        this.endTime = endTime;
        this.description = description;
        this.location = location;
        this.week = week;
    }

    public String getEventTitle() {
        return eventTitle;
    }

    public void setEventTitle(String eventTitle) {
        this.eventTitle = eventTitle;
    }

    public String getStartTime() {
        return startTime;
    }

    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }

    public String getEndTime() {
        return endTime;
    }

    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getWeek() {
        return week;
    }

    public void setWeek(String week) {
        this.week = week;
    }

    @Override
    public String toString() {
        return "CalenderDataStruct{" +
                "eventTitle='" + eventTitle + '\'' +
                ", startTime='" + startTime + '\'' +
                ", endTime='" + endTime + '\'' +
                ", description='" + description + '\'' +
                ", location='" + location + '\'' +
                ", week='" + week + '\'' +
                '}';
    }
}

 

2、calendarUtil

package com.example.calendartest;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.telephony.TelephonyManager;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

public class calendarUtil {

    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 TelephonyManager mTm;


    public static ArrayList<CalenderDataStruct> GetCalenderSchedule(Context context){

        String startTime = "";
        String endTime = "";
        String eventTitle = "";
        String description = "";
        String location = "";
        String week = "";

        ArrayList<CalenderDataStruct> arr=new ArrayList<CalenderDataStruct>();
        Cursor eventCursor = context.getContentResolver().query(Uri.parse(CALENDER_EVENT_URL), null,
                null, null,  "dtstart"+" DESC");
        while (eventCursor.moveToNext()){

            eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
            description = eventCursor.getString(eventCursor.getColumnIndex("description"));
            location = eventCursor.getString(eventCursor.getColumnIndex("eventLocation"));
            startTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtstart"))));
            endTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtend"))));
            week = ""+ (getWeek(startTime));
            CalenderDataStruct item=new CalenderDataStruct(eventTitle, startTime, endTime,description, location,week);

            arr.add(item);
        }
        return arr;
    }


    private static JSONArray getcalendar(Context context){
        String startTime = "";
        String endTime = "";
        String eventTitle = "";
        String description = "";
        String location = "";

        JSONArray arr=new JSONArray();
        Cursor eventCursor = context.getContentResolver().query(Uri.parse(CALENDER_EVENT_URL), null,
                null, null, null);
        while (eventCursor.moveToNext()){
            JSONObject json=new JSONObject();
            eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
            description = eventCursor.getString(eventCursor.getColumnIndex("description"));
            location = eventCursor.getString(eventCursor.getColumnIndex("eventLocation"));
            startTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtstart"))));
            endTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtend"))));
            try {
                json.put("eventTitle",eventTitle);
                json.put("description",description);
                json.put("location",location);
                json.put("startTime",startTime);
                json.put("endTime",endTime);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            arr.put(json);
        }
        return arr;
    }

    /**
     * 时间戳转换为字符串
     * @param time:时间戳
     * @return
     */
    private static String timeStamp2Date(long time) {
        String format = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date(time));
    }

    /**
     * 判断当前日期是星期几
     *
     * @param  pTime     设置的需要判断的时间  //格式如2012-09-08
     *

     * @return dayForWeek 判断结果
     * @Exception 发生异常
     */

//  String pTime = "2012-03-12";
    private static int getWeek(String pTime) {


        int Week = 0;


        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar c = Calendar.getInstance();
        try {

            c.setTime(format.parse(pTime));

        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            Week = 0;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 2) {
            Week = 1;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 3) {
            Week = 2;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 4) {
            Week = 3;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 5) {
            Week = 4;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 6) {
            Week = 5;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 7) {
            Week = 6;
        }



        return Week;
    }
}

 

3、MainActivity

package com.example.calendartest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private  static  final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayList<CalenderDataStruct> calenderDataStructs = calendarUtil.GetCalenderSchedule(this);
        Log.i(TAG, "onCreate: calenderDataStructs "+ calenderDataStructs.size());
        for (CalenderDataStruct item : calenderDataStructs){


            Log.i(TAG, "onCreate: CalenderDataStruct "+ item.toString());
        }
    }
}

 

4、AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.calendartest">
<uses-permission android:name="android.permission.READ_CALENDAR"/>
    <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

5、 calendarUtil.java(新的添加功能函数:获取当天之后自定天数的日历日程)

package com.example.calendartest;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.telephony.TelephonyManager;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class calendarUtil {

    private static final String TAG ="Main_calendarUtil";

    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 TelephonyManager mTm;


    // 当天当前的时间变量
    private  static long currentTime;
    // 当天之后的几天后的时间变量
    private  static long afterDayTime = Long.MAX_VALUE;
    // 一天总共的毫秒数
    private  static long onedayMS = 1000*60*60*24;

    /**
     * 添加从当天开始获取之后几天的日历日程
     * @param context
     * @param afterDays
     * @return
     */
    public static ArrayList<CalenderDataStruct> GetCalenderScheduleFormNow(Context context,int afterDays){

        currentTime = System.currentTimeMillis();
        if (afterDays > 0){

            afterDayTime = afterDays * onedayMS +currentTime;
        }

        String startTime = "";
        String endTime = "";
        String eventTitle = "";
        String description = "";
        String location = "";
        String week = "";

        ArrayList<CalenderDataStruct> arr=new ArrayList<CalenderDataStruct>();
        Cursor eventCursor = context.getContentResolver().query(Uri.parse(CALENDER_EVENT_URL), null,
                null, null,  "dtstart"+" DESC");
        while (eventCursor.moveToNext()){
            long dtstart = Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtstart")));

            // 满足获取条件的日历日程数据
            if( currentTime < dtstart && dtstart < afterDayTime){

                eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
                description = eventCursor.getString(eventCursor.getColumnIndex("description"));
                location = eventCursor.getString(eventCursor.getColumnIndex("eventLocation"));
                startTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtstart"))));
                endTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtend"))));
                week = ""+ (getWeek(startTime));
                CalenderDataStruct item=new CalenderDataStruct(eventTitle, startTime, endTime,description, location,week);

                arr.add(item);
            }

        }
        return arr;
    }

    public static ArrayList<CalenderDataStruct> GetCalenderSchedule(Context context){

        String startTime = "";
        String endTime = "";
        String eventTitle = "";
        String description = "";
        String location = "";
        String week = "";

        ArrayList<CalenderDataStruct> arr=new ArrayList<CalenderDataStruct>();
        Cursor eventCursor = context.getContentResolver().query(Uri.parse(CALENDER_EVENT_URL), null,
                null, null,  "dtstart"+" DESC");
        while (eventCursor.moveToNext()){

            eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
            description = eventCursor.getString(eventCursor.getColumnIndex("description"));
            location = eventCursor.getString(eventCursor.getColumnIndex("eventLocation"));
            startTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtstart"))));
            endTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtend"))));
            week = ""+ (getWeek(startTime));
            CalenderDataStruct item=new CalenderDataStruct(eventTitle, startTime, endTime,description, location,week);

            arr.add(item);
        }
        return arr;
    }


    private static JSONArray getcalendar(Context context){
        String startTime = "";
        String endTime = "";
        String eventTitle = "";
        String description = "";
        String location = "";

        JSONArray arr=new JSONArray();
        Cursor eventCursor = context.getContentResolver().query(Uri.parse(CALENDER_EVENT_URL), null,
                null, null, null);
        while (eventCursor.moveToNext()){
            JSONObject json=new JSONObject();
            eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
            description = eventCursor.getString(eventCursor.getColumnIndex("description"));
            location = eventCursor.getString(eventCursor.getColumnIndex("eventLocation"));
            startTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtstart"))));
            endTime = timeStamp2Date(Long.parseLong(eventCursor.getString(eventCursor.getColumnIndex("dtend"))));
            try {
                json.put("eventTitle",eventTitle);
                json.put("description",description);
                json.put("location",location);
                json.put("startTime",startTime);
                json.put("endTime",endTime);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            arr.put(json);
        }
        return arr;
    }

    /**
     * 时间戳转换为字符串
     * @param time:时间戳
     * @return
     */
    private static String timeStamp2Date(long time) {
        String format = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date(time));
    }

    /**
     * 判断当前日期是星期几
     *
     * @param  pTime     设置的需要判断的时间  //格式如2012-09-08
     *

     * @return dayForWeek 判断结果
     * @Exception 发生异常
     */

//  String pTime = "2012-03-12";
    private static int getWeek(String pTime) {


        int Week = 0;


        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar c = Calendar.getInstance();
        try {

            c.setTime(format.parse(pTime));

        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            Week = 0;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 2) {
            Week = 1;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 3) {
            Week = 2;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 4) {
            Week = 3;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 5) {
            Week = 4;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 6) {
            Week = 5;
        }
        if (c.get(Calendar.DAY_OF_WEEK) == 7) {
            Week = 6;
        }



        return Week;
    }



    // 添加需要的动态申请的权限(危险权限才会弹出跳出)
    static String[] permissions = new String[] { "android.permission.READ_CALENDAR"

    };

    /**
     * 检测权限,然后动态申请未授权的权限
     * (给 Unity 使用)
     * @param permissions Unity 传给来的权限字符串
     */
    public static void checkPermissionsForUnity( Activity activity){

        

        // 申请权限
        checkPermissions(activity, permissions);
    }


    /**
     * 动态权限申请,可给Android 自己调用
     * @param activity
     * @param MANDATORY_PERMISSIONS
     */
    private static void checkPermissions(Activity activity, String[] MANDATORY_PERMISSIONS) {

        Log.i(TAG, "checkPermissions: 检测权限");
        // 判断授权列表
        List<String> unGrantedPermissions;
        unGrantedPermissions = new ArrayList();

        // 检测权限
        for (String permission : MANDATORY_PERMISSIONS) {
            Log.i(TAG, "checkPermissions: permission " +permission);
            if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                unGrantedPermissions.add(permission);
            }
        }

        // 权限请求是否授权
        if (unGrantedPermissions.size() != 0) {
            String[] array = new String[unGrantedPermissions.size()];
            ActivityCompat.requestPermissions(activity, unGrantedPermissions.toArray(array), 0);
            Log.i(TAG, "checkPermissions: 已经获得了所有权限");
        }

        Log.i(TAG, "checkPermissions: Is Over");
    }

}

 

=============

附录:如何在Android中按日期范围或月份获取日历事件(How to get Calendar event by date range or month in android)

if (Integer.parseInt(Build.VERSION.SDK) >= 8 || Integer.parseInt(Build.VERSION.SDK) <= 13 ) {

            uri = "content://com.android.calendar/events";
            CALENDAR_URI = Uri.parse(uri);

        } else if(Integer.parseInt(Build.VERSION.SDK) >= 14){

             CALENDAR_URI = CalendarContract.Events.CONTENT_URI;

        }
        else {

            uri = "content://calendar/events";
            CALENDAR_URI = Uri.parse(uri);

        }
Cursor cursors = context.getContentResolver().query(CALENDAR_URI, new String[]{ "_id", "title", "description", "dtstart", "dtend", "eventLocation" },
                null,null, null);



 cursors.moveToFirst();
                                    String[] CalNames = new String[cursors.getCount()];
                                    int[] CalIds = new int[cursors.getCount()];
                                    for (int i = 0; i < CalNames.length; i++) {
                                        CalIds[i] = cursors.getInt(0);
                                        CalNames[i] = "Event"+cursors.getInt(0)+": \nTitle: "+ cursors.getString(1)+"\nDescription: "+cursors.getString(2)+"\nStart Date: "+new Date(cursors.getLong(3))+"\nEnd Date : "+new Date(cursors.getLong(4))+"\nLocation : "+cursors.getString(5);   

                                        Date mDate = new Date(cursors.getLong(3));
                                        Date nDate = new Date(cursors.getLong(4));

                                        long mTime = mDate.getTime();
                                        long lTime = nDate.getTime();
                                        if(stTime <= mTime && enTime >= lTime){ 
 String eid = cursors.getString(0);

                                            int eID = Integer.parseInt(eid);

                                            String desc = cursors.getString(2);
                                            String title = cursors.getString(1);

=============

 

日历日程一些有用的基础知识点:


 

一.手机系统日历数据增删改查基础知识

想要对手机系统日历程序的数据进行增删改查其实不难,只要掌握一些基础知识加上简单的Android开发知识就可以完全掌握了。

 

1.对系统日历数据操作的原理

对手机系统日历数据的操作,其实就是对系统内的日历程序对应的数据库进行操作,并且系统日历开放了内容提供者,
如果你对内容提供者熟悉,使用内容提供者进行操作,就可以对系统日历数据库的数据进行操作。

 

2.系统日历数据知识

(1)Android手机系统的日历Google API详解:

https://developer.android.com/guide/topics/providers/calendar-provider?hl=zh-cn

上面这个网址有我们想要知道级大部分知识并且是中文版的,比如几个日历相关的Uri地址,还有日历增删改查的实现简单代码。

上面虽然是官网中的API介绍,但是一样有坑!比如使用它介绍的代码来插入日历数据就崩溃!

主要是一个日历事件id的说明,官网都没有说对,误导很多人。

我看了下,网上其他文章也很少有说对的。

下面还是简单介绍一下手机系统日历的知识:

(2)手机系统日历操作需要添加权限才能操作

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

并且这两个权限是隐私权限,在Android6.0后需要动态申请

(3)手机系统日历相关的表和url地址

手机日历程序相关的数据库表有五个,但是真正用到的就一两个。events是最重要的。

表名

说明

calendars

此表储存日历特定信息。 此表中的每一行都包含一个日历的详细信息,例如名称、颜色、同步信息等。

events

此表储存事件特定信息。 此表中的每一行都包含一个事件的信息 — 例如事件标题、地点、开始时间、结束时间等。 事件可一次性发生,也可多次重复发生。参加者、提醒和扩展属性存储在单独的表内。它们各自具有一个 EVENT_ID,用于引用 Events 表中的 _ID。

instances

此表储存每个事件实例的开始时间和结束时间。 此表中的每一行都表示一个事件实例。 对于一次性事件,实例与事件为 1:1 映射。对于重复事件,会自动生成多个行,分别对应多个事件实例。

attendees

此表储存事件参加者(来宾)信息。 每一行都表示事件的一位来宾。 它指定来宾的类型以及事件的来宾出席响应。

reminders

此表储存提醒/通知数据。 每一行都表示事件的一个提醒。一个事件可以有多个提醒。 每个事件的最大提醒数量在 MAX_REMINDERS 中指定,后者由拥有给定日历的同步适配器设置。 提醒以事件发生前的分钟数形式指定,其具有一个可决定用户提醒方式的方法。

关于各个表的使用官网API中都有简单介绍。
其中,如果我们只是对日历日程数据进行增删改查,只需要events者一个表,就足够了,但是如果需要对事件进行提醒就需要对reminders表进行数据插入。

events表的数据就是我们在系统日历中看到的数据,

remianders表的数据,设置了之后,在我们设定的时间会有通知栏的消息,提醒我们。

那个各个表格对于的url地址是什么呢?

private static String CALANDER_EVENT_URL = "";// 为了兼容不同版本的日历,2.2以后url发生改变
 private static String CALANDER_URL = "";
 private static String CALANDER_REMIDER_URL = "";
 private void initUrl() {
        if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
            CALANDER_URL = "content://com.android.calendar/calendars";
            CALANDER_EVENT_URL = "content://com.android.calendar/events";
            CALANDER_REMIDER_URL = "content://com.android.calendar/reminders";
        } else {
            CALANDER_URL = "content://calendar/calendars";
            CALANDER_EVENT_URL = "content://calendar/events";
            CALANDER_REMIDER_URL = "content://calendar/reminders";
        }

    }

可以看到表格的前缀都是一样的,重要替换后面的表格名字就可以了。
并且现在用的SDK基本不可能小于8,直接用最新的地址是不会有问题的。

手机系统日历程序的文件目录地址: ~/data/data/com.android.calendar/
~表示根目录
但是,我们是没有权限对里面的数据库文件直接拿出来或者替换!root权限是不够的。必须还有系统用户管理员权限。
我们只能根据它暴露的内容提供者的接口来对这几个数据库进行操作。

(4)下面对events表进行详细介绍

events(事件)表,是最重要的一个表,其他的表如果有需要可以看官网API。
表格对应的属性:

常量

说明

_ID

事件所属日历的 _ID。

CALENDAR_ID

事件的固定ID。

ORGANIZER

事件组织者(所有者)的电子邮件。

TITLE

事件的标题。

EVENT_LOCATION

事件的发生地点。

DESCRIPTION

事件的描述。

DTSTART

事件开始时间,以从公元纪年开始计算的协调世界时毫秒数表示。

DTEND

事件结束时间,以从公元纪年开始计算的协调世界时毫秒数表示。

EVENT_TIMEZONE

 

EVENT_END_TIMEZONE

事件结束时间的时区。

DURATION

RFC5545格式的事件持续时间。例如,值为 “PT1H” 表示事件应持续一小时,值为 “P2W” 表示持续 2 周。

ALL_DAY

值为 1 表示此事件占用一整天(按照本地时区的定义)。 值为 0 表示它是常规事件,可在一天内的任何时间开始和结束。

RRULE

事件的重复发生规则格式。例如,”FREQ=WEEKLY;COUNT=10;WKST=SU”。 您可以在此处找到更多示例。

RDATE

事件的重复发生日期。 RDATE 与 RRULE 通常联合用于定义一组聚合重复实例。 如需查看更详细的介绍,请参阅 RFC5545 规范。

上面是官网对events表的属性介绍,需要注意下面几点:

4—1.上面属性在表格中都是小写的,在类调用中才大写而已。

4—2.上面关于id的介绍,我做了一下更正,_id才是事件的id,官网中没有介绍_id,只介绍了calendar_id说这个属性是事件的id。

但是你打印出所有属性的值,就会发现_id才是递增的数值,calendar_id是固定值1,所以官网介绍有误。
后面需要对事件的删除,修改也是使用_id这个属性值,而官网中多次错用了calendar_id这个属性。

4—3.时间

事件开始的事件和结束的时间获取到都是毫秒数的字符串,把它装换为Long在转换为事件字符串就可以得到时间格式的字符串。
时区我感觉没有必要研究。

4—4.关于duration持续时间

如果不是一个重复事件(比如每天,每周,每月等等),那么duration返回的数值都是null
如果是重复事件,那么事件的结束时间就是null

通过几次打印,我发现duration返回的字符形式都是PxxxS,xxx有可能很大几天(需要自己换算成具体的时间),xxx也可能很小,比如半小时为1800

4—5.关于重复规则rrule

通过多次打印并没有发现rdate这个属性有什么作用!

rrule但是有些复杂,如果需要可以深入研究一下,下面是我设置时间打印出来的字符,供大家参考:

日历中的rrule
每周的提醒:
rrule : FREQ=WEEKLY;WKST=SU;BYDAY=MO

每月的提醒:
rrule : FREQ=MONTHLY;WKST=SU;BYMONTHDAY=4//?

每年的提醒:
rrule : FREQ=YEARLY;WKST=SU



每天的提醒
rrule :FREQ=DAILY;WKST=SU

每十天的提醒:
rrule : FREQ=DAILY;INTERVAL=10;WKST=SU

5天
rrule='FREQ=DAILY;INTERVAL=5;WKST=SU'

每8天提醒一次,截止到20180808
rrule='FREQ=DAILY;UNTIL=20180808T093000;INTERVAL=8;WKST=SU'

每8天提醒一次,提醒9次
rrule='FREQ=DAILY;COUNT=9;INTERVAL=8;WKST=SU'

我们需要自己根据得到的字符串,解析这个通知的重复规律。
如果需要也可以看看我实例代码中的处理,我是直接硬处理做的,利用String类对字符串进行分割,如果用json解析应该也是可以的。

4—6.events中重要的属性

个人觉得就下面几个:_id,title,dtstart,dtend,event_location,duration,rrule
其他的属性基本用处不大,有具体需要可以看API。

 

3.关于对手机系统日历数据的增删改查操作简单说明

官网API的代码,有的运行不起来,可以参考我实例中的代码。也可以先看官网的,测试一下。

(1)增加日历事件

String calID = "1";
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,比如添加提醒事件(往提醒表添加数据),或者其他事件

上面Events.CONTENT_URI对应的地址就是events表的url地址对应的Uri对象。
添加事件必须添加事件的calendar_id,title,dtstart,这三个数据,其他数据可以根据需要添加。
calendar_id的值设置为1,是可以添加日历事件的,如果随便一个数值就会报错。。。可以自己测试
calendar_id也并不一定要设为1,也可以设置为_id的第一个值,如果没有删数据就是1,如果删了第一个事件_id的值就是2,以此类推。
calendar_id一定要设置正确,只能是上面的两种情况,设置错误就是报错。

上面插入数据完成后,得到的eventID的值,其实就是表中_id的值,

(2)删除日历事件

long ID = 20; //这个id一定是要表中_id的值,不能是calendar_id的值。
...
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);

大于0就表示删除数据成功。

(3)修改日历事件

long ID = 188; //这个id一定是要表中_id的值,不能是calendar_id的值

ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri updateUri = null;
// The new title for the event
values.put(Events.TITLE, "Kickboxing");
updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);

根据需求可以修改多个数据
同样rows大于零就表示修改成功。

(4)查询日历事件,这也是最重要的操作

前提是你要自己插入一条数据以上。

有些人想要研究日历表格,但是又不能复制里面的数据库出来,那怎么才能详细看到这个表格的所有属性呢。

你可以用下面几句代码遍历出整个表格中所有的属性值:

String CALANDER_EVENT_URL = "content://com.android.calendar/events";
        Uri uri = Uri.parse(CALANDER_EVENT_URL);
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        while (cursor.moveToNext()) {

            int columnCount = cursor.getColumnCount();
            Log.e(TAG, "columnCount :" + columnCount);//多少个属性
            for (int i = 0; i < columnCount; i++) {
                //获取到属性的名称
                String columnName = cursor.getColumnName(i);
                //获取到属性对应的值
                String message = cursor.getString(cursor.getColumnIndex(columnName));
                //打印属性和对应的值
                Log.e(TAG, columnName + " : " + message);

            }
        }

这时,你可以清楚看到_id和calendar_id的值的区别。

这里演示一下查询主要数据的代码:

String CALANDER_EVENT_URL = "content://com.android.calendar/events";
        Uri uri = Uri.parse(CALANDER_EVENT_URL);
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        while (cursor.moveToNext()) {

            //事件的ID
            String id = cursor.getString(cursor.getColumnIndex(Events._ID)); //不同于Events.CALENDAR_ID
            //事件的标题
            String title = cursor.getString(cursor.getColumnIndex(Events.TITLE));
            //事件的起始时间
            String dtstart = cursor.getString(cursor.getColumnIndex(Events.DTSTART));
            //事件的结束时间 ,如果事件是每天/周,那么就没有结束时间
            String dtend = cursor.getString(cursor.getColumnIndex(Events.DTEND));
            //事件的描述
            String description = cursor.getString(cursor.getColumnIndex(Events.DESCRIPTION));
            //事件的重复规律
            String rrule = cursor.getString(cursor.getColumnIndex(Events.RRULE));
            //事件的复发日期。通常RDATE要联合RRULE一起使用来定义一个重复发生的事件的合集。
            String rdate = cursor.getString(cursor.getColumnIndex(Events.RDATE));
            //事件是否是全天的
            String allDay = cursor.getString(cursor.getColumnIndex(Events.ALL_DAY));
            //事件的地点
            String location = cursor.getString(cursor.getColumnIndex(Events.EVENT_LOCATION));
            //事件持续时间,例如“PT1H”表示事件持续1小时的状态, “P2W”指明2周的持续时间。P3600S表示3600秒
            String duration = cursor.getString(cursor.getColumnIndex(Events.DURATION));

            //other
            String last_date = cursor.getString(cursor.getColumnIndex(Events.LAST_DATE));
            String original_id = cursor.getString(cursor.getColumnIndex(Events.ORIGINAL_ID));
            String maxReminders = cursor.getString(cursor.getColumnIndex(Events.MAX_REMINDERS));
            String allowedReminders = cursor.getString(cursor.getColumnIndex(Events.ALLOWED_REMINDERS));

        。。。

        }

(5)其他的

一般来说,对日历的操作无非是添加或查询,其他操作是很少用到的。
比如,我Log了一下自己的日历事件,发现很多信用卡提示,火车票提示,淘宝自己设的活动提示的事件等等信息。