Android 操作系統(tǒng)日歷完成提醒功能 附帶開(kāi)關(guān)鬧鐘
如果想要一個(gè)穩(wěn)定且不用擔(dān)心生命周期的提醒方式,可以試試?yán)孟到y(tǒng)日歷去完成任務(wù)的提醒或某個(gè)活動(dòng)的預(yù)約。
項(xiàng)目倉(cāng)庫(kù)地址在文末
環(huán)境
-
Java 11
-
Android sdk 30
-
Gredle 7.1
minSdkVersion 23 targetSdkVersion 30
-
測(cè)試機(jī)型 mi 8(安卓 9) mi10 pro(安卓11) huawei m8(安卓7)
前置知識(shí)
日歷操作表
? 其實(shí)完成這個(gè)功能本質(zhì)是對(duì)安卓原生數(shù)據(jù)庫(kù)的增刪改查操作,下圖就是30sdk中我們可以用到的系統(tǒng)常量
每一個(gè)靜態(tài)類(lèi)都對(duì)應(yīng)這一個(gè)系統(tǒng)中的數(shù)據(jù)表??梢酝ㄟ^(guò) 下面命令去找到對(duì)應(yīng)的路徑
CalendarContract.{table_name}.CONTENT_URI
- events 是我們主要的任務(wù)內(nèi)容和配置表
- Reminders 是日歷提醒設(shè)置表
- extendedProperties 是拓展屬性類(lèi)
- Calendars 存放基礎(chǔ)信息 如日歷賬戶(hù)等信息
操作日歷和設(shè)置鬧鐘提醒 其實(shí)就是對(duì)上述三張表的處理
ContentValues
? 這個(gè)類(lèi)是用來(lái)存放我們自己定義的一些條件 ,在插入系統(tǒng)表之前 組裝數(shù)據(jù)和一些必備的配置,使用的方式與Map一致。
PS: 因?yàn)榈讓泳S護(hù)了一個(gè)arrayMap 所以允許我們傳入K,V形式的數(shù)據(jù)
ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
event.put("calendar_id", calId); //插入賬戶(hù)的id
event.put("eventStatus", 1);
event.put(CalendarContract.Events._ID, eventId);
event.put(CalendarContract.Events.HAS_EXTENDED_PROPERTIES, true);
event.put(CalendarContract.Events.DTSTART, start);
event.put(CalendarContract.Events.DTEND, end);
我們插入數(shù)據(jù)表的步驟為
- 使用 ContentValues 組裝數(shù)據(jù)/加入需要的系統(tǒng)配置
- 使用 CalendarContract 拿到對(duì)應(yīng)的系統(tǒng)路徑
- 調(diào)用 context.getContentResolver() 這里有封裝好的增上改查方法來(lái)完成對(duì)底層數(shù)據(jù)庫(kù)的操作
功能流程
1、獲取權(quán)限
在 AndroidManifest
中添加權(quán)限
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
如果安卓版本高 最好在activity中使用動(dòng)態(tài)的權(quán)限校驗(yàn),在初始化的時(shí)候調(diào)用此方法,就可以完成彈窗動(dòng)態(tài)權(quán)限校驗(yàn)了
checkPermission(0, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR);
// 權(quán)限獲取
private void checkPermission(int callbackId, String... permissionsId) {
boolean permissions = true;
for (String p : permissionsId) {
permissions = permissions && ContextCompat.checkSelfPermission(this, p) == PERMISSION_GRANTED;
}
if (!permissions)
ActivityCompat.requestPermissions(this, permissionsId, callbackId);
}
2、創(chuàng)建日歷賬戶(hù)
系統(tǒng)其實(shí)有為我們創(chuàng)建默認(rèn)賬戶(hù),但是既然日歷有為我們準(zhǔn)備創(chuàng)建用戶(hù)的接口,那么我們還是創(chuàng)建一個(gè)屬于自己app的用戶(hù),之后的各種操作也不會(huì)影響到系統(tǒng)的內(nèi)容
我們自己定義了日歷賬戶(hù)信息 在每次操作日歷前 確保我們的app日歷賬戶(hù)存在于系統(tǒng)日歷,如果不存在就去創(chuàng)建一個(gè) (不會(huì)重復(fù)創(chuàng)建 不用擔(dān)心賬號(hào)冗余)
private static String CALENDARS_NAME = "TaskList";
private static String CALENDARS_ACCOUNT_NAME = "MyTaskList";
private static String CALENDARS_ACCOUNT_TYPE = "MyTaskList";
/**
* 這里創(chuàng)建賬戶(hù)的展示名稱(chēng),系統(tǒng)日歷為我們提供了創(chuàng)建賬戶(hù)的入口,那我們就不使用系統(tǒng)自帶的賬戶(hù),創(chuàng)建一個(gè)自己app的賬戶(hù)
*/
private static String CALENDARS_DISPLAY_NAME = "靠譜的任務(wù)清單";
/**
* 檢查是否存在現(xiàn)有賬戶(hù),存在則返回賬戶(hù)id,否則返回-1
*/
@SuppressLint("Range")
private static int checkCalendarAccount(Context context) {
Cursor userCursor = context.getContentResolver().query(CalendarContract.Calendars.CONTENT_URI, null, null, null, null);
try {
if (userCursor == null) { //查詢(xún)返回空值
return -1;
}
int count = userCursor.getCount();
if (count > 0) { //存在現(xiàn)有賬戶(hù),取第一個(gè)賬戶(hù)的id返回
for (int i = 0; i <= count - 1; i++) {
if (i == 0) {
userCursor.moveToFirst();
} else {
userCursor.moveToNext();
}
String type = userCursor.getString(userCursor.getColumnIndex(CalendarContract.Calendars.ACCOUNT_TYPE));
if (type.equals(CALENDARS_ACCOUNT_TYPE)) {
return userCursor.getInt(userCursor.getColumnIndex(CalendarContract.Calendars._ID));
}
}
}
return -1;
} finally {
if (userCursor != null) {
userCursor.close();
}
}
}
添加方法
其實(shí)添加方法就和我們平時(shí)操作數(shù)據(jù)庫(kù)十分類(lèi)似,就是組裝數(shù)據(jù),放入到數(shù)據(jù)表中
private static String CALENDARS_NAME = "TaskList";
private static String CALENDARS_ACCOUNT_NAME = "MyTaskList";
private static String CALENDARS_ACCOUNT_TYPE = "MyTaskList";
/**
* 這里創(chuàng)建賬戶(hù)的展示名稱(chēng),系統(tǒng)日歷為我們提供了創(chuàng)建賬戶(hù)的入口,那我們就不使用系統(tǒng)自帶的賬戶(hù),創(chuàng)建一個(gè)自己app的賬戶(hù)
*/
private static String CALENDARS_DISPLAY_NAME = "靠譜的任務(wù)清單";
/**
* 添加日歷賬戶(hù),賬戶(hù)創(chuàng)建成功則返回賬戶(hù)id,否則返回-1
*/
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);
// 可見(jiàn)度
value.put(CalendarContract.Calendars.VISIBLE, 1);
// 日歷顏色
value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE);
// 權(quán)限
value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
value.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
// 時(shí)區(qū)
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 = CalendarContract.Calendars.CONTENT_URI;
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;
}
在擁有檢查和創(chuàng)建方法后,我們?nèi)コ橄笠粋€(gè)條件判斷方法,來(lái)用于一次調(diào)用完成創(chuàng)建日歷賬戶(hù) 檢查的完成流程
checkAndAddCalendarAccount
/**
* 檢查是否已經(jīng)添加了日歷賬戶(hù),如果沒(méi)有添加先添加一個(gè)日歷賬戶(hù)再查詢(xún)
* 獲取賬戶(hù)成功返回賬戶(hù)id,否則返回-1
*/
@RequiresApi(api = Build.VERSION_CODES.N)
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;
}
}
}
3、組裝數(shù)據(jù),添加日程
這個(gè)其實(shí)就比較簡(jiǎn)單了 ,就是為數(shù)據(jù)表添加行數(shù)和內(nèi)容
-
檢查日歷賬戶(hù) 并且獲取id
-
組裝event 新增event
-
根據(jù)isAlarm判斷是否需要添加鬧鐘提醒
-
在event數(shù)據(jù)中
event.put(CalendarContract.Events.HAS_ALARM, 1);
是用于老版本安卓的鬧鐘提醒 比較新的國(guó)內(nèi)安卓版本都不在根據(jù)這個(gè)字段來(lái)判斷了
-
新一些的安卓版本 使用ExtendedProperties 來(lái)添加額外屬性,目前已知miui的高版本是需要設(shè)置
extendedProperties.put(CalendarContract.ExtendedProperties.VALUE, "{\"need_alarm\":true}");
并且賬戶(hù)內(nèi)容要是我們自己創(chuàng)建的賬戶(hù)才可以完成鬧鐘提示
PS: 在封裝工具類(lèi)前 我是用系統(tǒng)默認(rèn)用戶(hù) 無(wú)法設(shè)置 不知道原因
-
-
設(shè)置 Reminders 日程提醒方式等
-
完成日程設(shè)置
調(diào)用完這個(gè)方法你就可以發(fā)現(xiàn)日歷里 有對(duì)應(yīng)的日程了
/**
* 這個(gè)是關(guān)鍵方法,調(diào)用插入日程提醒
*
* @param context
* @param eventId 事件id
* @param title 提醒事件標(biāo)題
* @param description 事件描述
* @param reminderTime 任務(wù)開(kāi)始時(shí)間,這里參數(shù)名不太合適,后面會(huì)加提醒時(shí)間,
* @param endTime 任務(wù)結(jié)束時(shí)間
* @param previousMinutes 提前多少分鐘提醒,后續(xù)使用
* @param isAlarm 是否需要鬧鐘提醒
*/
@RequiresApi(api = Build.VERSION_CODES.N)
@SuppressLint("Range")
public static Long addCalendarEvent(Context context, long eventId, String title, String description, long reminderTime, long endTime, int previousMinutes, boolean isAlarm) {
if (context == null) {
return -1L;
}
int calId = checkAndAddCalendarAccount(context); //獲取日歷賬戶(hù)的id
if (calId < 0) { //獲取賬戶(hù)id失敗直接返回,添加日歷事件失敗
return -1L;
}
//添加日歷事件
Calendar mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(reminderTime);//設(shè)置開(kāi)始時(shí)間
long start = mCalendar.getTime().getTime();
mCalendar.setTimeInMillis(endTime);//設(shè)置終止時(shí)間
long end = mCalendar.getTime().getTime();
ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
event.put("calendar_id", calId); //插入賬戶(hù)的id
event.put("eventStatus", 1);
event.put(CalendarContract.Events._ID, eventId);
event.put(CalendarContract.Events.HAS_EXTENDED_PROPERTIES, true);
event.put(CalendarContract.Events.DTSTART, start);
event.put(CalendarContract.Events.DTEND, end);
if (isAlarm) {
event.put(CalendarContract.Events.HAS_ALARM, 1);//設(shè)置有鬧鐘提醒,但是經(jīng)測(cè)試,此方案無(wú)效
}
event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getDisplayName());//這個(gè)是時(shí)區(qū),必須有
Uri newEvent = context.getContentResolver().insert(CalendarContract.Events.CONTENT_URI, event); //添加事件
if (newEvent == null) { //添加日歷事件失敗直接返回
return -1L;
}
//擴(kuò)展屬性 用于高版本安卓系統(tǒng)設(shè)置鬧鐘提醒
if (isAlarm) {
Uri extendedPropUri = CalendarContract.ExtendedProperties.CONTENT_URI;
extendedPropUri = extendedPropUri.buildUpon()
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME)
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE).build();
ContentValues extendedProperties = new ContentValues();
extendedProperties.put(CalendarContract.ExtendedProperties.EVENT_ID, ContentUris.parseId(newEvent));
extendedProperties.put(CalendarContract.ExtendedProperties.VALUE, "{\"need_alarm\":true}");
extendedProperties.put(CalendarContract.ExtendedProperties.NAME, "agenda_info");
Uri uriExtended = context.getContentResolver().insert(extendedPropUri, extendedProperties);
if (uriExtended == null) { //添加事件提醒失敗直接返回
return -1L;
}
}
//事件提醒的設(shè)定
ContentValues values = new ContentValues();
values.put(CalendarContract.Reminders.EVENT_ID, ContentUris.parseId(newEvent));
values.put(CalendarContract.Reminders.MINUTES, 0);// 提前previousDate天有提醒
values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
Uri uri = context.getContentResolver().insert(CalendarContract.Reminders.CONTENT_URI, values);
if (uri == null) { //添加事件提醒失敗直接返回
return -1L;
}
Toast.makeText(context, "設(shè)置日程成功!!!", Toast.LENGTH_LONG).show();
return eventId;
}
4、 刪除日程
這個(gè)就比較簡(jiǎn)單,因?yàn)槲覀兪亲远x日程id 所以我們直接通過(guò)傳入的id 刪除對(duì)應(yīng)的日程即可,網(wǎng)上的工具類(lèi)都是用title 容易刪除同名日程
/**
* 刪除日歷事件
*/
public static void deleteCalendarEvent(Context context, Long delEventID) {
if (context == null) {
return;
}
Uri deleteUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, delEventID);
int rows = context.getContentResolver().delete(deleteUri, null, null);
if (rows == -1) { //事件刪除失敗
return;
}
}
工具類(lèi)代碼
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.provider.CalendarContract;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import java.util.Calendar;
import java.util.TimeZone;
public class CalendarReminderUtils {
private static String CALENDARS_NAME = "TaskList";
private static String CALENDARS_ACCOUNT_NAME = "MyTaskList";
private static String CALENDARS_ACCOUNT_TYPE = "MyTaskList";
/**
* 這里創(chuàng)建賬戶(hù)的展示名稱(chēng),系統(tǒng)日歷為我們提供了創(chuàng)建賬戶(hù)的入口,那我們就不使用系統(tǒng)自帶的賬戶(hù),創(chuàng)建一個(gè)自己app的賬戶(hù)
*/
private static String CALENDARS_DISPLAY_NAME = "靠譜的任務(wù)清單";
/**
* 檢查是否已經(jīng)添加了日歷賬戶(hù),如果沒(méi)有添加先添加一個(gè)日歷賬戶(hù)再查詢(xún)
* 獲取賬戶(hù)成功返回賬戶(hù)id,否則返回-1
*/
@RequiresApi(api = Build.VERSION_CODES.N)
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;
}
}
}
/**
* 檢查是否存在現(xiàn)有賬戶(hù),存在則返回賬戶(hù)id,否則返回-1
*/
@SuppressLint("Range")
private static int checkCalendarAccount(Context context) {
Cursor userCursor = context.getContentResolver().query(CalendarContract.Calendars.CONTENT_URI, null, null, null, null);
try {
if (userCursor == null) { //查詢(xún)返回空值
return -1;
}
int count = userCursor.getCount();
if (count > 0) { //存在現(xiàn)有賬戶(hù),取第一個(gè)賬戶(hù)的id返回
for (int i = 0; i <= count - 1; i++) {
if (i == 0) {
userCursor.moveToFirst();
} else {
userCursor.moveToNext();
}
String type = userCursor.getString(userCursor.getColumnIndex(CalendarContract.Calendars.ACCOUNT_TYPE));
if (type.equals(CALENDARS_ACCOUNT_TYPE)) {
return userCursor.getInt(userCursor.getColumnIndex(CalendarContract.Calendars._ID));
}
}
}
return -1;
} finally {
if (userCursor != null) {
userCursor.close();
}
}
}
/**
* 添加日歷賬戶(hù),賬戶(hù)創(chuàng)建成功則返回賬戶(hù)id,否則返回-1
*/
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);
// 可見(jiàn)度
value.put(CalendarContract.Calendars.VISIBLE, 1);
// 日歷顏色
value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE);
// 權(quán)限
value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
value.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
// 時(shí)區(qū)
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 = CalendarContract.Calendars.CONTENT_URI;
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;
}
/**
* 這個(gè)是關(guān)鍵方法,調(diào)用插入日程提醒
*
* @param context
* @param eventId 事件id
* @param title 提醒事件標(biāo)題
* @param description 事件描述
* @param reminderTime 任務(wù)開(kāi)始時(shí)間,這里參數(shù)名不太合適,后面會(huì)加提醒時(shí)間,
* @param endTime 任務(wù)結(jié)束時(shí)間
* @param previousMinutes 提前多少分鐘提醒,后續(xù)使用
* @param isAlarm 是否需要鬧鐘提醒
*/
@RequiresApi(api = Build.VERSION_CODES.N)
@SuppressLint("Range")
public static Long addCalendarEvent(Context context, long eventId, String title, String description, long reminderTime, long endTime, int previousMinutes, boolean isAlarm) {
if (context == null) {
return -1L;
}
int calId = checkAndAddCalendarAccount(context); //獲取日歷賬戶(hù)的id
if (calId < 0) { //獲取賬戶(hù)id失敗直接返回,添加日歷事件失敗
return -1L;
}
//添加日歷事件
Calendar mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(reminderTime);//設(shè)置開(kāi)始時(shí)間
long start = mCalendar.getTime().getTime();
mCalendar.setTimeInMillis(endTime);//設(shè)置終止時(shí)間
long end = mCalendar.getTime().getTime();
ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
event.put("calendar_id", calId); //插入賬戶(hù)的id
event.put("eventStatus", 1);
event.put(CalendarContract.Events._ID, eventId);
event.put(CalendarContract.Events.HAS_EXTENDED_PROPERTIES, true);
event.put(CalendarContract.Events.DTSTART, start);
event.put(CalendarContract.Events.DTEND, end);
if (isAlarm) {
event.put(CalendarContract.Events.HAS_ALARM, 1);//設(shè)置有鬧鐘提醒,但是經(jīng)測(cè)試,此方案無(wú)效
}
event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getDisplayName());//這個(gè)是時(shí)區(qū),必須有
Uri newEvent = context.getContentResolver().insert(CalendarContract.Events.CONTENT_URI, event); //添加事件
if (newEvent == null) { //添加日歷事件失敗直接返回
return -1L;
}
//擴(kuò)展屬性 用于高版本安卓系統(tǒng)設(shè)置鬧鐘提醒
if (isAlarm) {
Uri extendedPropUri = CalendarContract.ExtendedProperties.CONTENT_URI;
extendedPropUri = extendedPropUri.buildUpon()
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME)
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE).build();
ContentValues extendedProperties = new ContentValues();
extendedProperties.put(CalendarContract.ExtendedProperties.EVENT_ID, ContentUris.parseId(newEvent));
extendedProperties.put(CalendarContract.ExtendedProperties.VALUE, "{\"need_alarm\":true}");
extendedProperties.put(CalendarContract.ExtendedProperties.NAME, "agenda_info");
Uri uriExtended = context.getContentResolver().insert(extendedPropUri, extendedProperties);
if (uriExtended == null) { //添加事件提醒失敗直接返回
return -1L;
}
}
//事件提醒的設(shè)定
ContentValues values = new ContentValues();
values.put(CalendarContract.Reminders.EVENT_ID, ContentUris.parseId(newEvent));
values.put(CalendarContract.Reminders.MINUTES, 0);// 提前previousDate天有提醒
values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
Uri uri = context.getContentResolver().insert(CalendarContract.Reminders.CONTENT_URI, values);
if (uri == null) { //添加事件提醒失敗直接返回
return -1L;
}
Toast.makeText(context, "設(shè)置日程成功!!!", Toast.LENGTH_LONG).show();
return eventId;
}
/**
* 刪除日歷事件
*/
public static void deleteCalendarEvent(Context context, Long delEventID) {
if (context == null) {
return;
}
Uri deleteUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, delEventID);
int rows = context.getContentResolver().delete(deleteUri, null, null);
if (rows == -1) { //事件刪除失敗
return;
}
}
/**
* 查詢(xún)?nèi)諝v日程相關(guān)的數(shù)據(jù)庫(kù)表(查詢(xún)其他表也適用),方法將查詢(xún)表的所有列的所有行都展示出來(lái)了,就是這么人性化
*
* @param uri 用來(lái)區(qū)分查詢(xún)的表的類(lèi)型,查詢(xún)不同的表,使用不同的URI即可,其他的都一樣
*/
@SuppressLint("Range")
public void queryCalendarData(Uri uri, Activity context) {
Cursor cursor = context.getContentResolver().query(uri, null,
null, null, null);
while (cursor.moveToNext()) {
int columnCount = cursor.getColumnCount();
Log.e("TAG", "columnCount :" + columnCount);//多少個(gè)屬性
for (int i = 0; i < columnCount; i++) {
//獲取到屬性的名稱(chēng)
String columnName = cursor.getColumnName(i);
//獲取到屬性對(duì)應(yīng)的值
String message = cursor.getString(cursor.getColumnIndex(columnName));
//打印屬性和對(duì)應(yīng)的值
Log.e("TAG", columnName + " : " + message);
}
}
}
}
Demo
頁(yè)面布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/deleteEventButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="delete a Event" />
<Button
android:id="@+id/writeEventButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Input a Event" />
</LinearLayout>
Activity
public class CalenderDemoActivity extends AppCompatActivity implements View.OnClickListener {
private Button mDeleteEventButton;
private Button mWriteEventButton;
final int callbackId = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calender_demo);
checkPermission(callbackId, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR);
setupViews();
}
private void checkPermission(int callbackId, String... permissionsId) {
boolean permissions = true;
for (String p : permissionsId) {
permissions = permissions && ContextCompat.checkSelfPermission(this, p) == PERMISSION_GRANTED;
}
if (!permissions)
ActivityCompat.requestPermissions(this, permissionsId, callbackId);
}
private void setupViews() {
mDeleteEventButton = (Button) findViewById(R.id.deleteEventButton);
mWriteEventButton = (Button) findViewById(R.id.writeEventButton);
mDeleteEventButton.setOnClickListener(this);
mWriteEventButton.setOnClickListener(this);
}
/**
* 檢查是否存在現(xiàn)有賬戶(hù),存在則返回賬戶(hù)id,否則返回-1
*/
/**
* 添加日歷賬戶(hù),賬戶(hù)創(chuàng)建成功則返回賬戶(hù)id,否則返回-1
*/
@SuppressLint("Range")
@Override
public void onClick(View v) {
Long eventId = Long.parseLong(String.valueOf((int)Math.random()*999+1));
if (v == mWriteEventButton) {
Calendar mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(System.currentTimeMillis() + 1 * 60 * 1000);
long start = mCalendar.getTime().getTime();
mCalendar.setTimeInMillis(start + 1 * 60 * 1000);
long end = mCalendar.getTime().getTime();
CalendarReminderUtils.addCalendarEvent(this, eventId,"工作提醒", "該休息啦", start, end, 0,true);
Log.d("============eventid", "onClick: " + eventId);
} else if (v == mDeleteEventButton) {
// CalendarReminderUtils.queryCalendarData(CalendarContract.Calendars.CONTENT_URI, this);
CalendarReminderUtils.deleteCalendarEvent(this, eventId);
}
}
}
效果
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-775827.html
倉(cāng)庫(kù)地址
Gitee地址 AndroidDemo文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-775827.html
到了這里,關(guān)于Android 操作系統(tǒng)日歷完成提醒功能 附帶開(kāi)關(guān)鬧鐘 適配高版本安卓的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!