今天我們來說說“Android怎么才可以讓系統(tǒng)日歷同步日程?”這個問題的階級方法和解決方法的代碼與思路。希望正在學習Android的小伙伴們有所收獲!
具體內容如下
1、權限
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
2、動態(tài)權限Activity中
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_CALENDAR,
Manifest.permission.READ_CALENDAR}, 1);
}
3、使用
String tipTime = "2021-04-25 12:00";
long start = TimeUtils.stringToLong(tipTime ,"yyyy-MM-dd HH:mm");
long end = start + 60 * 60 * 1000L;
LogUtil.d("start:" + start);
LogUtil.d("end:" + end);
String[] split = tipTime.split(" ");
String[] dateStr = split[0].split("-");
int month = Integer.parseInt(dateStr[1]);
int day = Integer.parseInt(dateStr[2]);
String until = "20221231T235959Z";//截止時間:2022年12月31日23點59分59秒
String mRule = "";
switch (mRepeatType) {
case 1://不重復
mRule = null;
break;
case 2://按年重復(每年的某月某日)
mRule = "FREQ=YEARLY;UNTIL=" + until + ";WKST=SU;BYMONTH=" + month + ";BYMONTHDAY=" + day;
break;
case 3://按月重復(每月的某天)
mRule = "FREQ=MONTHLY;UNTIL=" + until + ";WKST=SU;BYMONTHDAY=" + day;
break;
case 4://按周重復
String date = split[0];
String week = TimeUtils.getWeek(date);
switch (week) {
case "周日":
mRule = "FREQ=WEEKLY;UNTIL=" + until + ";WKST=SU;BYDAY=SU";
break;
case "周一":
mRule = "FREQ=WEEKLY;UNTIL=" + until + ";WKST=SU;BYDAY=MO";
break;
case "周二":
mRule = "FREQ=WEEKLY;UNTIL=" + until + ";WKST=SU;BYDAY=TU";
break;
case "周三":
mRule = "FREQ=WEEKLY;UNTIL=" + until + ";WKST=SU;BYDAY=WE";
break;
case "周四":
mRule = "FREQ=WEEKLY;UNTIL=" + until + ";WKST=SU;BYDAY=TH";
break;
case "周五":
mRule = "FREQ=WEEKLY;UNTIL=" + until + ";WKST=SU;BYDAY=FR";
break;
case "周六":
mRule = "FREQ=WEEKLY;UNTIL=" + until + ";WKST=SU;BYDAY=SA";
break;
}
break;
case 5://按天(每天)
mRule = "FREQ=DAILY;UNTIL=" + until;
break;
case 6://自定義周幾重復,可多選
mRule = "FREQ=WEEKLY;UNTIL=" + until + ";WKST=SU;BYDAY=";
String[] weeks = mSelectedWeekStr.split(",");
for (int i = 0; i < weeks.length; i++) {
if (weeks[i].equals("周日")) {
mRule += "SU,";
} else if (weeks[i].equals("周一")) {
mRule += "MO,";
} else if (weeks[i].equals("周二")) {
mRule += "TU,";
} else if (weeks[i].equals("周三")) {
mRule += "WE,";
} else if (weeks[i].equals("周四")) {
mRule += "TH,";
} else if (weeks[i].equals("周五")) {
mRule += "FR,";
} else if (weeks[i].equals("周六")) {
mRule += "SA,";
}
}
if (mRule.endsWith(",")) {
mRule.substring(0, mRule.length() - 1);
}
break;
}
LogUtil.d("mRule:" + mRule);
CalendarEvent calendarEvent = new CalendarEvent(
mContent, mContent,
"",
start,
end,
0, mRule
);
// 添加事件
int addResult = CalendarProviderManager.addCalendarEvent(AddScheduleActivity.this, calendarEvent);
if (addResult == 0) {
ToastUtil.showShortToast("插入成功");
} else if (addResult == -1) {
ToastUtil.showShortToast("插入失敗");
} else if (addResult == -2) {
ToastUtil.showShortToast("沒有權限");
}
3、時間轉換方法
public static long stringToLong(String strTime, String formatType) {
Date date = null; // String類型轉成date類型
try {
date = stringToDate(strTime, formatType);
} catch (Exception e) {
e.printStackTrace();
}
if (date == null) {
return 0;
} else {
long currentTime = dateToLong(date); // date類型轉成long類型
return currentTime;
}
}
public static Date stringToDate(String strTime, String formatType) {
SimpleDateFormat formatter = new SimpleDateFormat(formatType);
Date date = null;
try {
date = formatter.parse(strTime);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
// date要轉換的date類型的時間
public static long dateToLong(Date date) {
return date.getTime();
}
4、CalendarProviderManager 類
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.provider.CalendarContract;
import calendarprovider.Util;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
import static com.kyle.calendarprovider.Util.checkContextNull;
/**
* 系統(tǒng)日歷工具
*/
public class CalendarProviderManager {
private static StringBuilder builder = new StringBuilder();
/**
* TIP: 要向系統(tǒng)日歷插入事件,前提系統(tǒng)中必須存在至少1個日歷賬戶
** /
// ----------------------- 創(chuàng)建日歷賬戶時賬戶名使用 ---------------------------
private static String CALENDAR_NAME = "TestC";
private static String CALENDAR_ACCOUNT_NAME = "Test";
private static String CALENDAR_DISPLAY_NAME = "Test的賬戶";
// ------------------------------- 日歷賬戶 -----------------------------------
/**
* 獲取日歷賬戶ID(若沒有則會自動創(chuàng)建一個)
*
* @return success: 日歷賬戶ID failed : -1 permission deny : -2
*/
@SuppressWarnings("WeakerAccess")
public static long obtainCalendarAccountID(Context context) {
long calID = checkCalendarAccount(context);
if (calID >= 0) {
return calID;
} else {
return createCalendarAccount(context);
}
}
/**
* 檢查是否存在日歷賬戶
*
* @return 存在:日歷賬戶ID 不存在:-1
*/
private static long checkCalendarAccount(Context context) {
try (Cursor cursor = context.getContentResolver().query(CalendarContract.Calendars.CONTENT_URI,
null, null, null, null)) {
// 不存在日歷賬戶
if (null == cursor) {
return -1;
}
int count = cursor.getCount();
// 存在日歷賬戶,獲取第一個賬戶的ID
if (count > 0) {
cursor.moveToFirst();
return cursor.getInt(cursor.getColumnIndex(CalendarContract.Calendars._ID));
} else {
return -1;
}
}
}
/**
* 創(chuàng)建一個新的日歷賬戶
*
* @return success:ACCOUNT ID , create failed:-1 , permission deny:-2
*/
private static long createCalendarAccount(Context context) {
// 系統(tǒng)日歷表
Uri uri = CalendarContract.Calendars.CONTENT_URI;
// 要創(chuàng)建的賬戶
Uri accountUri;
// 開始組裝賬戶數據
ContentValues account = new ContentValues();
// 賬戶類型:本地
// 在添加賬戶時,如果賬戶類型不存在系統(tǒng)中,則可能該新增記錄會被標記為臟數據而被刪除
// 設置為ACCOUNT_TYPE_LOCAL可以保證在不存在賬戶類型時,該新增數據不會被刪除
account.put(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL);
// 日歷在表中的名稱
account.put(CalendarContract.Calendars.NAME, CALENDAR_NAME);
// 日歷賬戶的名稱
account.put(CalendarContract.Calendars.ACCOUNT_NAME, CALENDAR_ACCOUNT_NAME);
// 賬戶顯示的名稱
account.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, CALENDAR_DISPLAY_NAME);
// 日歷的顏色
account.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.parseColor("#515bd4"));
// 用戶對此日歷的獲取使用權限等級
account.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
// 設置此日歷可見
account.put(CalendarContract.Calendars.VISIBLE, 1);
// 日歷時區(qū)
account.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, TimeZone.getDefault().getID());
// 可以修改日歷時區(qū)
account.put(CalendarContract.Calendars.CAN_MODIFY_TIME_ZONE, 1);
// 同步此日歷到設備上
account.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
// 擁有者的賬戶
account.put(CalendarContract.Calendars.OWNER_ACCOUNT, CALENDAR_ACCOUNT_NAME);
// 可以響應事件
account.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 1);
// 單個事件設置的最大的提醒數
account.put(CalendarContract.Calendars.MAX_REMINDERS, 8);
// 設置允許提醒的方式
account.put(CalendarContract.Calendars.ALLOWED_REMINDERS, "0,1,2,3,4");
// 設置日歷支持的可用性類型
account.put(CalendarContract.Calendars.ALLOWED_AVAILABILITY, "0,1,2");
// 設置日歷允許的出席者類型
account.put(CalendarContract.Calendars.ALLOWED_ATTENDEE_TYPES, "0,1,2");
/**
* TIP: 修改或添加ACCOUNT_NAME只能由SYNC_ADAPTER調用
* 對uri設置CalendarContract.CALLER_IS_SYNCADAPTER為true,即標記當前操作為SYNC_ADAPTER操作
* 在設置CalendarContract.CALLER_IS_SYNCADAPTER為true時,必須帶上參數ACCOUNT_NAME和ACCOUNT_TYPE(任意)
**/
uri = uri.buildUpon()
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, CALENDAR_ACCOUNT_NAME)
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE,
CalendarContract.Calendars.CALENDAR_LOCATION)
.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 檢查日歷權限
if (PackageManager.PERMISSION_GRANTED == context.checkSelfPermission(
"android.permission.WRITE_CALENDAR")) {
accountUri = context.getContentResolver().insert(uri, account);
} else {
return -2;
}
} else {
accountUri = context.getContentResolver().insert(uri, account);
}
return accountUri == null ? -1 : ContentUris.parseId(accountUri);
}
/**
* 刪除創(chuàng)建的日歷賬戶
*
* @return -2: permission deny 0: No designated account 1: delete success
*/
public static int deleteCalendarAccountByName(Context context) {
checkContextNull(context);
int deleteCount;
Uri uri = CalendarContract.Calendars.CONTENT_URI;
String selection = "((" + CalendarContract.Calendars.ACCOUNT_NAME + " = ?) AND ("
+ CalendarContract.Calendars.ACCOUNT_TYPE + " = ?))";
String[] selectionArgs = new String[]{CALENDAR_ACCOUNT_NAME, CalendarContract.ACCOUNT_TYPE_LOCAL};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (PackageManager.PERMISSION_GRANTED == context.checkSelfPermission(
"android.permission.WRITE_CALENDAR")) {
deleteCount = context.getContentResolver().delete(uri, selection, selectionArgs);
} else {
return -2;
}
} else {
deleteCount = context.getContentResolver().delete(uri, selection, selectionArgs);
}
return deleteCount;
}
// ------------------------------- 添加日歷事件 -----------------------------------
/**
* 添加日歷事件
*
* @param calendarEvent 日歷事件(詳細參數說明請參看{@link CalendarEvent}構造方法)
* @return 0: success -1: failed -2: permission deny
*/
public static int addCalendarEvent(Context context, CalendarEvent calendarEvent) {
/**
* TIP: 插入一個新事件的規(guī)則:
* 1. 必須包含CALENDAR_ID和DTSTART字段
* 2. 必須包含EVENT_TIMEZONE字段,使用TimeZone.getDefault().getID()方法獲取默認時區(qū)
* 3. 對于非重復發(fā)生的事件,必須包含DTEND字段
* 4. 對重復發(fā)生的事件,必須包含一個附加了RRULE或RDATE字段的DURATION字段
*/
checkContextNull(context);
// 獲取日歷賬戶ID,也就是要將事件插入到的賬戶
long calID = obtainCalendarAccountID(context);
// 系統(tǒng)日歷事件表
Uri uri1 = CalendarContract.Events.CONTENT_URI;
// 創(chuàng)建的日歷事件
Uri eventUri;
// 系統(tǒng)日歷事件提醒表
Uri uri2 = CalendarContract.Reminders.CONTENT_URI;
// 創(chuàng)建的日歷事件提醒
Uri reminderUri;
// 開始組裝事件數據
ContentValues event = new ContentValues();
// 事件要插入到的日歷賬戶
event.put(CalendarContract.Events.CALENDAR_ID, calID);
setupEvent(calendarEvent, event);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 判斷權限
if (PackageManager.PERMISSION_GRANTED == context.checkSelfPermission(
"android.permission.WRITE_CALENDAR")) {
eventUri = context.getContentResolver().insert(uri1, event);
} else {
return -2;
}
} else {
eventUri = context.getContentResolver().insert(uri1, event);
}
if (null == eventUri) {
return -1;
}
if (-2 != calendarEvent.getAdvanceTime()) {
// 獲取事件ID
long eventID = ContentUris.parseId(eventUri);
// 開始組裝事件提醒數據
ContentValues reminders = new ContentValues();
// 此提醒所對應的事件ID
reminders.put(CalendarContract.Reminders.EVENT_ID, eventID);
// 設置提醒提前的時間(0:準時 -1:使用系統(tǒng)默認)
reminders.put(CalendarContract.Reminders.MINUTES, calendarEvent.getAdvanceTime());
// 設置事件提醒方式為通知警報
reminders.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
reminderUri = context.getContentResolver().insert(uri2, reminders);
if (null == reminderUri) {
return -1;
}
}
return 0;
}
// ------------------------------- 更新日歷事件 -----------------------------------
/**
* 更新指定ID的日歷事件
*
* @param newCalendarEvent 更新的日歷事件
* @return -2: permission deny else success
*/
public static int updateCalendarEvent(Context context, long eventID, CalendarEvent newCalendarEvent) {
checkContextNull(context);
int updatedCount1;
Uri uri1 = CalendarContract.Events.CONTENT_URI;
Uri uri2 = CalendarContract.Reminders.CONTENT_URI;
ContentValues event = new ContentValues();
setupEvent(newCalendarEvent, event);
// 更新匹配條件
String selection1 = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs1 = new String[]{String.valueOf(eventID)};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (PackageManager.PERMISSION_GRANTED == context.checkSelfPermission(
"android.permission.WRITE_CALENDAR")) {
updatedCount1 = context.getContentResolver().update(uri1, event, selection1, selectionArgs1);
} else {
return -2;
}
} else {
updatedCount1 = context.getContentResolver().update(uri1, event, selection1, selectionArgs1);
}
ContentValues reminders = new ContentValues();
reminders.put(CalendarContract.Reminders.MINUTES, newCalendarEvent.getAdvanceTime());
reminders.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
// 更新匹配條件
String selection2 = "(" + CalendarContract.Reminders.EVENT_ID + " = ?)";
String[] selectionArgs2 = new String[]{String.valueOf(eventID)};
int updatedCount2 = context.getContentResolver().update(uri2, reminders, selection2, selectionArgs2);
return (updatedCount1 + updatedCount2) / 2;
}
/**
* 更新指定ID事件的開始時間
*
* @return If successfully returns 1
*/
public static int updateCalendarEventbeginTime(Context context, long eventID, long newBeginTime) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.DTSTART, newBeginTime);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
/**
* 更新指定ID事件的結束時間
*
* @return If successfully returns 1
*/
public static int updateCalendarEventEndTime(Context context, long eventID, long newEndTime) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.DTEND, newEndTime);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
/**
* 更新指定ID事件的起始時間
*
* @return If successfully returns 1
*/
public static int updateCalendarEventTime(Context context, long eventID, long newBeginTime,
long newEndTime) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.DTSTART, newBeginTime);
event.put(CalendarContract.Events.DTEND, newEndTime);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
/**
* 更新指定ID事件的標題
*
* @return If successfully returns 1
*/
public static int updateCalendarEventTitle(Context context, long eventID, String newTitle) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.TITLE, newTitle);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
/**
* 更新指定ID事件的描述
*
* @return If successfully returns 1
*/
public static int updateCalendarEventDes(Context context, long eventID, String newEventDes) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.DESCRIPTION, newEventDes);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
/**
* 更新指定ID事件的地點
*
* @return If successfully returns 1
*/
public static int updateCalendarEventLocation(Context context, long eventID, String newEventLocation) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.EVENT_LOCATION, newEventLocation);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
/**
* 更新指定ID事件的標題和描述
*
* @return If successfully returns 1
*/
public static int updateCalendarEventTitAndDes(Context context, long eventID, String newEventTitle,
String newEventDes) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.TITLE, newEventTitle);
event.put(CalendarContract.Events.DESCRIPTION, newEventDes);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
/**
* 更新指定ID事件的常用信息(標題、描述、地點)
*
* @return If successfully returns 1
*/
public static int updateCalendarEventCommonInfo(Context context, long eventID, String newEventTitle,
String newEventDes, String newEventLocation) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.TITLE, newEventTitle);
event.put(CalendarContract.Events.DESCRIPTION, newEventDes);
event.put(CalendarContract.Events.EVENT_LOCATION, newEventLocation);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
/**
* 更新指定ID事件的提醒方式
*
* @return If successfully returns 1
*/
private static int updateCalendarEventReminder(Context context, long eventID, long newAdvanceTime) {
checkContextNull(context);
Uri uri = CalendarContract.Reminders.CONTENT_URI;
ContentValues reminders = new ContentValues();
reminders.put(CalendarContract.Reminders.MINUTES, newAdvanceTime);
// 更新匹配條件
String selection2 = "(" + CalendarContract.Reminders.EVENT_ID + " = ?)";
String[] selectionArgs2 = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, reminders, selection2, selectionArgs2);
}
/**
* 更新指定ID事件的提醒重復規(guī)則
*
* @return If successfully returns 1
*/
private static int updateCalendarEventRRule(Context context, long eventID, String newRRule) {
checkContextNull(context);
Uri uri = CalendarContract.Events.CONTENT_URI;
// 新的數據
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.RRULE, newRRule);
// 匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
return context.getContentResolver().update(uri, event, selection, selectionArgs);
}
// ------------------------------- 刪除日歷事件 -----------------------------------
/**
* 刪除日歷事件
*
* @param eventID 事件ID
* @return -2: permission deny else success
*/
public static int deleteCalendarEvent(Context context, long eventID) {
checkContextNull(context);
int deletedCount1;
Uri uri1 = CalendarContract.Events.CONTENT_URI;
Uri uri2 = CalendarContract.Reminders.CONTENT_URI;
// 刪除匹配條件
String selection = "(" + CalendarContract.Events._ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(eventID)};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (PackageManager.PERMISSION_GRANTED == context.checkSelfPermission(
"android.permission.WRITE_CALENDAR")) {
deletedCount1 = context.getContentResolver().delete(uri1, selection, selectionArgs);
} else {
return -2;
}
} else {
deletedCount1 = context.getContentResolver().delete(uri1, selection, selectionArgs);
}
// 刪除匹配條件
String selection2 = "(" + CalendarContract.Reminders.EVENT_ID + " = ?)";
String[] selectionArgs2 = new String[]{String.valueOf(eventID)};
int deletedCount2 = context.getContentResolver().delete(uri2, selection2, selectionArgs2);
return (deletedCount1 + deletedCount2) / 2;
}
// ------------------------------- 查詢日歷事件 -----------------------------------
/**
* 查詢指定日歷賬戶下的所有事件
*
* @return If failed return null else return List<CalendarEvent>
*/
public static List<CalendarEvent> queryAccountEvent(Context context, long calID) {
checkContextNull(context);
final String[] EVENT_PROJECTION = new String[]{
CalendarContract.Events.CALENDAR_ID, // 在表中的列索引0
CalendarContract.Events.TITLE, // 在表中的列索引1
CalendarContract.Events.DESCRIPTION, // 在表中的列索引2
CalendarContract.Events.EVENT_LOCATION, // 在表中的列索引3
CalendarContract.Events.DISPLAY_COLOR, // 在表中的列索引4
CalendarContract.Events.STATUS, // 在表中的列索引5
CalendarContract.Events.DTSTART, // 在表中的列索引6
CalendarContract.Events.DTEND, // 在表中的列索引7
CalendarContract.Events.DURATION, // 在表中的列索引8
CalendarContract.Events.EVENT_TIMEZONE, // 在表中的列索引9
CalendarContract.Events.EVENT_END_TIMEZONE, // 在表中的列索引10
CalendarContract.Events.ALL_DAY, // 在表中的列索引11
CalendarContract.Events.ACCESS_LEVEL, // 在表中的列索引12
CalendarContract.Events.AVAILABILITY, // 在表中的列索引13
CalendarContract.Events.HAS_ALARM, // 在表中的列索引14
CalendarContract.Events.RRULE, // 在表中的列索引15
CalendarContract.Events.RDATE, // 在表中的列索引16
CalendarContract.Events.HAS_ATTENDEE_DATA, // 在表中的列索引17
CalendarContract.Events.LAST_DATE, // 在表中的列索引18
CalendarContract.Events.ORGANIZER, // 在表中的列索引19
CalendarContract.Events.IS_ORGANIZER, // 在表中的列索引20
CalendarContract.Events._ID // 在表中的列索引21
};
// 事件匹配
Uri uri = CalendarContract.Events.CONTENT_URI;
Uri uri2 = CalendarContract.Reminders.CONTENT_URI;
String selection = "(" + CalendarContract.Events.CALENDAR_ID + " = ?)";
String[] selectionArgs = new String[]{String.valueOf(calID)};
Cursor cursor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (PackageManager.PERMISSION_GRANTED == context.checkSelfPermission(
"android.permission.READ_CALENDAR")) {
cursor = context.getContentResolver().query(uri, EVENT_PROJECTION, selection,
selectionArgs, null);
} else {
return null;
}
} else {
cursor = context.getContentResolver().query(uri, EVENT_PROJECTION, selection,
selectionArgs, null);
}
if (null == cursor) {
return null;
}
// 查詢結果
List<CalendarEvent> result = new ArrayList<>();
// 開始查詢數據
if (cursor.moveToFirst()) {
do {
CalendarEvent calendarEvent = new CalendarEvent();
result.add(calendarEvent);
calendarEvent.setId(cursor.getLong(cursor.getColumnIndex(
CalendarContract.Events._ID)));
calendarEvent.setCalID(cursor.getLong(cursor.getColumnIndex(
CalendarContract.Events.CALENDAR_ID)));
calendarEvent.setTitle(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.TITLE)));
calendarEvent.setDescription(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.DESCRIPTION)));
calendarEvent.setEventLocation(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.EVENT_LOCATION)));
calendarEvent.setDisplayColor(cursor.getInt(cursor.getColumnIndex(
CalendarContract.Events.DISPLAY_COLOR)));
calendarEvent.setStatus(cursor.getInt(cursor.getColumnIndex(
CalendarContract.Events.STATUS)));
calendarEvent.setStart(cursor.getLong(cursor.getColumnIndex(
CalendarContract.Events.DTSTART)));
calendarEvent.setEnd(cursor.getLong(cursor.getColumnIndex(
CalendarContract.Events.DTEND)));
calendarEvent.setDuration(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.DURATION)));
calendarEvent.setEventTimeZone(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.EVENT_TIMEZONE)));
calendarEvent.setEventEndTimeZone(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.EVENT_END_TIMEZONE)));
calendarEvent.setAllDay(cursor.getInt(cursor.getColumnIndex(
CalendarContract.Events.ALL_DAY)));
calendarEvent.setAccessLevel(cursor.getInt(cursor.getColumnIndex(
CalendarContract.Events.ACCESS_LEVEL)));
calendarEvent.setAvailability(cursor.getInt(cursor.getColumnIndex(
CalendarContract.Events.AVAILABILITY)));
calendarEvent.setHasAlarm(cursor.getInt(cursor.getColumnIndex(
CalendarContract.Events.HAS_ALARM)));
calendarEvent.setRRule(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.RRULE)));
calendarEvent.setRDate(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.RDATE)));
calendarEvent.setHasAttendeeData(cursor.getInt(cursor.getColumnIndex(
CalendarContract.Events.HAS_ATTENDEE_DATA)));
calendarEvent.setLastDate(cursor.getInt(cursor.getColumnIndex(
CalendarContract.Events.LAST_DATE)));
calendarEvent.setOrganizer(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.ORGANIZER)));
calendarEvent.setIsOrganizer(cursor.getString(cursor.getColumnIndex(
CalendarContract.Events.IS_ORGANIZER)));
// ----------------------- 開始查詢事件提醒 ------------------------------
String[] REMINDER_PROJECTION = new String[]{
CalendarContract.Reminders._ID, // 在表中的列索引0
CalendarContract.Reminders.EVENT_ID, // 在表中的列索引1
CalendarContract.Reminders.MINUTES, // 在表中的列索引2
CalendarContract.Reminders.METHOD, // 在表中的列索引3
};
String selection2 = "(" + CalendarContract.Reminders.EVENT_ID + " = ?)";
String[] selectionArgs2 = new String[]{String.valueOf(calendarEvent.getId())};
try (Cursor reminderCursor = context.getContentResolver().query(uri2, REMINDER_PROJECTION,
selection2, selectionArgs2, null)) {
if (null != reminderCursor) {
if (reminderCursor.moveToFirst()) {
List<CalendarEvent.EventReminders> reminders = new ArrayList<>();
do {
CalendarEvent.EventReminders reminders1 = new CalendarEvent.EventReminders();
reminders.add(reminders1);
reminders1.setReminderId(reminderCursor.getLong(
reminderCursor.getColumnIndex(CalendarContract.Reminders._ID)));
reminders1.setReminderEventID(reminderCursor.getLong(
reminderCursor.getColumnIndex(CalendarContract.Reminders.EVENT_ID)));
reminders1.setReminderMinute(reminderCursor.getInt(
reminderCursor.getColumnIndex(CalendarContract.Reminders.MINUTES)));
reminders1.setReminderMethod(reminderCursor.getInt(
reminderCursor.getColumnIndex(CalendarContract.Reminders.METHOD)));
} while (reminderCursor.moveToNext());
calendarEvent.setReminders(reminders);
}
}
}
} while (cursor.moveToNext());
cursor.close();
}
return result;
}
/**
* 判斷日歷賬戶中是否已經存在此事件
*
* @param begin 事件開始時間
* @param end 事件結束時間
* @param title 事件標題
*/
public static boolean isEventAlreadyExist(Context context, long begin, long end, String title) {
String[] projection = new String[]{
CalendarContract.Instances.BEGIN,
CalendarContract.Instances.END,
CalendarContract.Instances.TITLE
};
Cursor cursor = CalendarContract.Instances.query(
context.getContentResolver(), projection, begin, end, title);
return null != cursor && cursor.moveToFirst()
&& cursor.getString(
cursor.getColumnIndex(CalendarContract.Instances.TITLE)).equals(title);
}
// ------------------------------- 日歷事件相關 -----------------------------------
/**
* 組裝日歷事件
*/
private static void setupEvent(CalendarEvent calendarEvent, ContentValues event) {
// 事件開始時間
event.put(CalendarContract.Events.DTSTART, calendarEvent.getStart());
// 事件結束時間
event.put(CalendarContract.Events.DTEND, calendarEvent.getEnd());
// 事件標題
event.put(CalendarContract.Events.TITLE, calendarEvent.getTitle());
// 事件描述(對應手機系統(tǒng)日歷備注欄)
event.put(CalendarContract.Events.DESCRIPTION, calendarEvent.getDescription());
// 事件地點
event.put(CalendarContract.Events.EVENT_LOCATION, calendarEvent.getEventLocation());
// 事件時區(qū)
event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
// 定義事件的顯示,默認即可
event.put(CalendarContract.Events.ACCESS_LEVEL, CalendarContract.Events.ACCESS_DEFAULT);
// 事件的狀態(tài)
event.put(CalendarContract.Events.STATUS, 0);
// 設置事件提醒警報可用
event.put(CalendarContract.Events.HAS_ALARM, 1);
// 設置事件忙
event.put(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY);
if (null != calendarEvent.getRRule()) {
// 設置事件重復規(guī)則
event.put(CalendarContract.Events.RRULE,
getFullRRuleForRRule(calendarEvent.getRRule(),
calendarEvent.getStart(), calendarEvent.getEnd()));
}
}
/**
* 獲取完整的重復規(guī)則(包含終止時間)
*
* @param rRule 重復規(guī)則
* @param beginTime 開始時間
* @param endTime 結束時間
*/
private static String getFullRRuleForRRule(String rRule, long beginTime, long endTime) {
builder.delete(0, builder.length());
switch (rRule) {
case RRuleConstant.REPEAT_WEEKLY_BY_MO:
case RRuleConstant.REPEAT_WEEKLY_BY_TU:
case RRuleConstant.REPEAT_WEEKLY_BY_WE:
case RRuleConstant.REPEAT_WEEKLY_BY_TH:
case RRuleConstant.REPEAT_WEEKLY_BY_FR:
case RRuleConstant.REPEAT_WEEKLY_BY_SA:
case RRuleConstant.REPEAT_WEEKLY_BY_SU:
return builder.append(rRule).append(Util.getFinalRRuleMode(endTime)).toString();
case RRuleConstant.REPEAT_CYCLE_WEEKLY:
return builder.append(rRule).append(Util.getWeekForDate(beginTime)).append("; UNTIL = ")
.append(Util.getFinalRRuleMode(endTime)).toString();
case RRuleConstant.REPEAT_CYCLE_MONTHLY:
return builder.append(rRule).append(Util.getDayOfMonth(beginTime))
.append("; UNTIL = ").append(Util.getFinalRRuleMode(endTime)).toString();
default:
return rRule;
}
}
// ------------------------------- 通過Intent啟動系統(tǒng)日歷 -----------------------------------
/*
日歷的Intent對象:
動作 描述 附加功能
ACTION_VIEW 打開指定時間的日歷 無
ACTION_VIEW 查看由EVENT_ID指定的事件 開始時間,結束時間
ACTION_EDIT 編輯由EVENT_ID指定的事件 開始時間,結束時間
ACTION_INSERT 創(chuàng)建一個事件 所有
Intent對象的附加功能:
Events.TITLE 事件標題
CalendarContract.EXTRA_EVENT_BEGIN_TIME 開始時間
CalendarContract.EXTRA_EVENT_END_TIME 結束時間
CalendarContract.EXTRA_EVENT_ALL_DAY 是否全天
Events.EVENT_LOCATION 事件地點
Events.DESCRIPTION 事件描述
Intent.EXTRA_EMALL 受邀者電子郵件,用逗號分隔
Events.RRULE 事件重復規(guī)則
Events.ACCESS_LEVEL 事件私有還是公有
Events.AVAILABILITY 預定事件是在忙時計數還是閑時計數
*/
/**
* 通過Intent啟動系統(tǒng)日歷新建事件界面插入新的事件
* <p>
* TIP: 這將不再需要聲明讀寫日歷數據的權限
*
* @param beginTime 事件開始時間
* @param endTime 事件結束時間
* @param title 事件標題
* @param des 事件描述
* @param location 事件地點
* @param isAllDay 事件是否全天
*/
public static void startCalendarForIntentToInsert(Context context, long beginTime, long endTime,
String title, String des, String location,
boolean isAllDay) {
checkCalendarAccount(context);
// FIXME: 2019/3/6 VIVO手機無法打開界面,找不到對應的Activity com.bbk.calendar
Intent intent = new Intent(Intent.ACTION_INSERT)
.setData(CalendarContract.Events.CONTENT_URI)
.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime)
.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime)
.putExtra(CalendarContract.Events.ALL_DAY, isAllDay)
.putExtra(CalendarContract.Events.TITLE, title)
.putExtra(CalendarContract.Events.DESCRIPTION, des)
.putExtra(CalendarContract.Events.EVENT_LOCATION, location);
if (null != intent.resolveActivity(context.getPackageManager())) {
context.startActivity(intent);
}
}
/**
* 通過Intent啟動系統(tǒng)日歷來編輯指定ID的事件
* <p>
*
* @param eventID 要編輯的事件ID
*/
public static void startCalendarForIntentToEdit(Context context, long eventID) {
checkCalendarAccount(context);
Uri uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_EDIT).setData(uri);
if (null != intent.resolveActivity(context.getPackageManager())) {
context.startActivity(intent);
}
}
/**
* 通過Intent啟動系統(tǒng)日歷來查看指定ID的事件
*
* @param eventID 要查看的事件ID
*/
public static void startCalendarForIntentToView(Context context, long eventID) {
checkCalendarAccount(context);
Uri uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW).setData(uri);
if (null != intent.resolveActivity(context.getPackageManager())) {
context.startActivity(intent);
}
}
// ----------------------------- 日歷賬戶名相關設置 -----------------------------------
public static String getCalendarName() {
return CALENDAR_NAME;
}
public static void setCalendarName(String calendarName) {
CALENDAR_NAME = calendarName;
}
public static String getCalendarAccountName() {
return CALENDAR_ACCOUNT_NAME;
}
public static void setCalendarAccountName(String calendarAccountName) {
CALENDAR_ACCOUNT_NAME = calendarAccountName;
}
public static String getCalendarDisplayName() {
return CALENDAR_DISPLAY_NAME;
}
public static void setCalendarDisplayName(String calendarDisplayName) {
CALENDAR_DISPLAY_NAME = calendarDisplayName;
}
}
5、CalendarEvent類
public class CalendarEvent {
// ----------------------- 事件屬性 -----------------------
/**
* 事件在表中的ID
*/
private long id;
/**
* 事件所屬日歷賬戶的ID
*/
private long calID;
private String title;
private String description;
private String eventLocation;
private int displayColor;
private int status;
private long start;
private long end;
private String duration;
private String eventTimeZone;
private String eventEndTimeZone;
private int allDay;
private int accessLevel;
private int availability;
private int hasAlarm;
private String rRule;
private String rDate;
private int hasAttendeeData;
private int lastDate;
private String organizer;
private String isOrganizer;
// ----------------------------------------------------------------------------------------
/**
* 注:此屬性不屬于CalendarEvent
* 這里只是為了方便構造方法提供事件提醒時間
*/
private int advanceTime;
// ----------------------------------------------------------------------------------------
// ----------------------- 事件提醒屬性 -----------------------
private List<EventReminders> reminders;
CalendarEvent() {
}
/**
* 用于方便添加完整日歷事件提供一個構造方法
*
* @param title 事件標題
* @param description 事件描述
* @param eventLocation 事件地點
* @param start 事件開始時間
* @param end 事件結束時間 If is not a repeat event, this param is must need else null
* @param advanceTime 事件提醒時間{@link AdvanceTime}
* (If you don't need to remind the incoming parameters -2)
* @param rRule 事件重復規(guī)則 {@link RRuleConstant} {@code null} if dose not need
*/
public CalendarEvent(String title, String description, String eventLocation,
long start, long end, int advanceTime, String rRule) {
this.title = title;
this.description = description;
this.eventLocation = eventLocation;
this.start = start;
this.end = end;
this.advanceTime = advanceTime;
this.rRule = rRule;
}
public int getAdvanceTime() {
return advanceTime;
}
public void setAdvanceTime(int advanceTime) {
this.advanceTime = advanceTime;
}
public long getId() {
return id;
}
void setId(long id) {
this.id = id;
}
public long getCalID() {
return calID;
}
void setCalID(long calID) {
this.calID = calID;
}
public String getTitle() {
return title;
}
void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
void setDescription(String description) {
this.description = description;
}
public String getEventLocation() {
return eventLocation;
}
void setEventLocation(String eventLocation) {
this.eventLocation = eventLocation;
}
public int getDisplayColor() {
return displayColor;
}
void setDisplayColor(int displayColor) {
this.displayColor = displayColor;
}
public int getStatus() {
return status;
}
void setStatus(int status) {
this.status = status;
}
public long getStart() {
return start;
}
void setStart(long start) {
this.start = start;
}
public long getEnd() {
return end;
}
void setEnd(long end) {
this.end = end;
}
public String getDuration() {
return duration;
}
void setDuration(String duration) {
this.duration = duration;
}
public String getEventTimeZone() {
return eventTimeZone;
}
void setEventTimeZone(String eventTimeZone) {
this.eventTimeZone = eventTimeZone;
}
public String getEventEndTimeZone() {
return eventEndTimeZone;
}
void setEventEndTimeZone(String eventEndTimeZone) {
this.eventEndTimeZone = eventEndTimeZone;
}
public int getAllDay() {
return allDay;
}
void setAllDay(int allDay) {
this.allDay = allDay;
}
public int getAccessLevel() {
return accessLevel;
}
void setAccessLevel(int accessLevel) {
this.accessLevel = accessLevel;
}
public int getAvailability() {
return availability;
}
void setAvailability(int availability) {
this.availability = availability;
}
public int getHasAlarm() {
return hasAlarm;
}
void setHasAlarm(int hasAlarm) {
this.hasAlarm = hasAlarm;
}
public String getRRule() {
return rRule;
}
void setRRule(String rRule) {
this.rRule = rRule;
}
public String getRDate() {
return rDate;
}
void setRDate(String rDate) {
this.rDate = rDate;
}
public int getHasAttendeeData() {
return hasAttendeeData;
}
void setHasAttendeeData(int hasAttendeeData) {
this.hasAttendeeData = hasAttendeeData;
}
public int getLastDate() {
return lastDate;
}
void setLastDate(int lastDate) {
this.lastDate = lastDate;
}
public String getOrganizer() {
return organizer;
}
void setOrganizer(String organizer) {
this.organizer = organizer;
}
public String getIsOrganizer() {
return isOrganizer;
}
void setIsOrganizer(String isOrganizer) {
this.isOrganizer = isOrganizer;
}
public List<EventReminders> getReminders() {
return reminders;
}
void setReminders(List<EventReminders> reminders) {
this.reminders = reminders;
}
@NonNull
@Override
public String toString() {
return "CalendarEvent{" +
"
id=" + id +
"
calID=" + calID +
"
title='" + title + ''' +
"
description='" + description + ''' +
"
eventLocation='" + eventLocation + ''' +
"
displayColor=" + displayColor +
"
status=" + status +
"
start=" + start +
"
end=" + end +
"
duration='" + duration + ''' +
"
eventTimeZone='" + eventTimeZone + ''' +
"
eventEndTimeZone='" + eventEndTimeZone + ''' +
"
allDay=" + allDay +
"
accessLevel=" + accessLevel +
"
availability=" + availability +
"
hasAlarm=" + hasAlarm +
"
rRule='" + rRule + ''' +
"
rDate='" + rDate + ''' +
"
hasAttendeeData=" + hasAttendeeData +
"
lastDate=" + lastDate +
"
organizer='" + organizer + ''' +
"
isOrganizer='" + isOrganizer + ''' +
"
reminders=" + reminders +
'}';
}
@Override
public int hashCode() {
return (int) (id * 37 + calID);
}
/**
* 事件提醒
*/
static class EventReminders {
// ----------------------- 事件提醒屬性 -----------------------
private long reminderId;
private long reminderEventID;
private int reminderMinute;
private int reminderMethod;
public long getReminderId() {
return reminderId;
}
void setReminderId(long reminderId) {
this.reminderId = reminderId;
}
public long getReminderEventID() {
return reminderEventID;
}
void setReminderEventID(long reminderEventID) {
this.reminderEventID = reminderEventID;
}
public int getReminderMinute() {
return reminderMinute;
}
void setReminderMinute(int reminderMinute) {
this.reminderMinute = reminderMinute;
}
public int getReminderMethod() {
return reminderMethod;
}
void setReminderMethod(int reminderMethod) {
this.reminderMethod = reminderMethod;
}
}
}
6、Util類
public class Util {
/**
* 獲取日歷事件結束日期
*
* @param time time in ms
*/
private static String getEndDate(long time) {
Date date = new Date(time);
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
return format.format(date);
}
/**
* 獲取最終日歷事件重復規(guī)則
*
* @param time time in ms
* "T235959" {@linkplain com.kyle.calendarprovider.calendar.RRuleConstant #51}
*/
public static String getFinalRRuleMode(long time) {
return getEndDate(time) + "T235959Z";
}
/**
* 格式化星期
*/
private static String formatWeek(int week) {
switch (week) {
case 0:
return "SU";
case 1:
return "MO";
case 2:
return "TU";
case 3:
return "WE";
case 4:
return "TH";
case 5:
return "FR";
case 6:
return "SA";
default:
return null;
}
}
/**
* 獲取重復周
*
* @param time time in ms
*/
public static String getWeekForDate(long time) {
Date date = new Date(time);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;
if (week < 0) {
week = 0;
}
return formatWeek(week);
}
/**
* 獲取指定時間段在一個月中的哪一天
*
* @param time time in ms
*/
public static int getDayOfMonth(long time) {
Date date = new Date(time);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar.get(Calendar.DAY_OF_MONTH);
}
/**
* check null
*/
public static void checkContextNull(Context context) {
if (null == context) {
throw new IllegalArgumentException("context can not be null");
}
}
}
在安卓中我們通過代碼和文字描述講述了有關于“Android怎么才可以讓系統(tǒng)日歷同步日程?”這個問題的解決方法和實現思路,更多有關于Android的內容我們都能在W3Cschool學習到更多新的使用方法和知識點。