Android 操作系统日历完成提醒功能 附带开关闹钟
如果想要一个稳定且不用担心生命周期的提醒方式,可以试试利用系统日历去完成任务的提醒或某个活动的预约。
项目仓库地址在文末
环境
-
Java 11
-
Android sdk 30
-
Gredle 7.1
minSdkVersion 23 targetSdkVersion 30
-
测试机型 mi 8(安卓 9) mi10 pro(安卓11) huawei m8(安卓7)
前置知识
日历操作表
其实完成这个功能本质是对安卓原生数据库的增删改查操作,下图就是30sdk中我们可以用到的系统常量
每一个静态类都对应这一个系统中的数据表。可以通过 下面命令去找到对应的路径
CalendarContract.{table_name}.CONTENT_URI
- events 是我们主要的任务内容和配置表
- Reminders 是日历提醒设置表
- extendedProperties 是拓展属性类
- Calendars 存放基础信息 如日历账户等信息
操作日历和设置闹钟提醒 其实就是对上述三张表的处理
ContentValues
这个类是用来存放我们自己定义的一些条件 ,在插入系统表之前 组装数据和一些必备的配置,使用的方式与Map一致。
PS: 因为底层维护了一个arrayMap 所以允许我们传入K,V形式的数据
ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
event.put("calendar_id", calId); //插入账户的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);
我们插入数据表的步骤为
- 使用 ContentValues 组装数据/加入需要的系统配置
- 使用 CalendarContract 拿到对应的系统路径
- 调用 context.getContentResolver() 这里有封装好的增上改查方法来完成对底层数据库的操作
功能流程
1、获取权限
在 AndroidManifest
中添加权限
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
如果安卓版本高 最好在activity中使用动态的权限校验,在初始化的时候调用此方法,就可以完成弹窗动态权限校验了
checkPermission(0, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR);
// 权限获取
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、创建日历账户
系统其实有为我们创建默认账户,但是既然日历有为我们准备创建用户的接口,那么我们还是创建一个属于自己app的用户,之后的各种操作也不会影响到系统的内容
我们自己定义了日历账户信息 在每次操作日历前 确保我们的app日历账户存在于系统日历,如果不存在就去创建一个 (不会重复创建 不用担心账号冗余)
private static String CALENDARS_NAME = "TaskList";
private static String CALENDARS_ACCOUNT_NAME = "MyTaskList";
private static String CALENDARS_ACCOUNT_TYPE = "MyTaskList";
/**
* 这里创建账户的展示名称,系统日历为我们提供了创建账户的入口,那我们就不使用系统自带的账户,创建一个自己app的账户
*/
private static String CALENDARS_DISPLAY_NAME = "靠谱的任务清单";
/**
* 检查是否存在现有账户,存在则返回账户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) { //查询返回空值
return -1;
}
int count = userCursor.getCount();
if (count > 0) { //存在现有账户,取第一个账户的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();
}
}
}
添加方法
其实添加方法就和我们平时操作数据库十分类似,就是组装数据,放入到数据表中
private static String CALENDARS_NAME = "TaskList";
private static String CALENDARS_ACCOUNT_NAME = "MyTaskList";
private static String CALENDARS_ACCOUNT_TYPE = "MyTaskList";
/**
* 这里创建账户的展示名称,系统日历为我们提供了创建账户的入口,那我们就不使用系统自带的账户,创建一个自己app的账户
*/
private static String CALENDARS_DISPLAY_NAME = "靠谱的任务清单";
/**
* 添加日历账户,账户创建成功则返回账户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);
// 可见度
value.put(CalendarContract.Calendars.VISIBLE, 1);
// 日历颜色
value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE);
// 权限
value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
value.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
// 时区
value.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, timeZone.getID());
value.put(CalendarContract.Calendars.OWNER_ACCOUNT, CALENDARS_ACCOUNT_NAME);
value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0);
Uri calendarUri = 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;
}
在拥有检查和创建方法后,我们去抽象一个条件判断方法,来用于一次调用完成创建日历账户 检查的完成流程
checkAndAddCalendarAccount
/**
* 检查是否已经添加了日历账户,如果没有添加先添加一个日历账户再查询
* 获取账户成功返回账户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、组装数据,添加日程
这个其实就比较简单了 ,就是为数据表添加行数和内容
-
检查日历账户 并且获取id
-
组装event 新增event
-
根据isAlarm判断是否需要添加闹钟提醒
-
在event数据中
event.put(CalendarContract.Events.HAS_ALARM, 1);
是用于老版本安卓的闹钟提醒 比较新的国内安卓版本都不在根据这个字段来判断了
-
新一些的安卓版本 使用ExtendedProperties 来添加额外属性,目前已知miui的高版本是需要设置
extendedProperties.put(CalendarContract.ExtendedProperties.VALUE, "{\"need_alarm\":true}");
并且账户内容要是我们自己创建的账户才可以完成闹钟提示
PS: 在封装工具类前 我是用系统默认用户 无法设置 不知道原因
-
-
设置 Reminders 日程提醒方式等
-
完成日程设置
调用完这个方法你就可以发现日历里 有对应的日程了
/**
* 这个是关键方法,调用插入日程提醒
*
* @param context
* @param eventId 事件id
* @param title 提醒事件标题
* @param description 事件描述
* @param reminderTime 任务开始时间,这里参数名不太合适,后面会加提醒时间,
* @param endTime 任务结束时间
* @param previousMinutes 提前多少分钟提醒,后续使用
* @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); //获取日历账户的id
if (calId < 0) { //获取账户id失败直接返回,添加日历事件失败
return -1L;
}
//添加日历事件
Calendar mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(reminderTime);//设置开始时间
long start = mCalendar.getTime().getTime();
mCalendar.setTimeInMillis(endTime);//设置终止时间
long end = mCalendar.getTime().getTime();
ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
event.put("calendar_id", calId); //插入账户的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);//设置有闹钟提醒,但是经测试,此方案无效
}
event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getDisplayName());//这个是时区,必须有
Uri newEvent = context.getContentResolver().insert(CalendarContract.Events.CONTENT_URI, event); //添加事件
if (newEvent == null) { //添加日历事件失败直接返回
return -1L;
}
//扩展属性 用于高版本安卓系统设置闹钟提醒
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;
}
}
//事件提醒的设定
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, "设置日程成功!!!", Toast.LENGTH_LONG).show();
return eventId;
}
4、 删除日程
这个就比较简单,因为我们是自定义日程id 所以我们直接通过传入的id 删除对应的日程即可,网上的工具类都是用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;
}
}
工具类代码
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";
/**
* 这里创建账户的展示名称,系统日历为我们提供了创建账户的入口,那我们就不使用系统自带的账户,创建一个自己app的账户
*/
private static String CALENDARS_DISPLAY_NAME = "靠谱的任务清单";
/**
* 检查是否已经添加了日历账户,如果没有添加先添加一个日历账户再查询
* 获取账户成功返回账户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;
}
}
}
/**
* 检查是否存在现有账户,存在则返回账户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) { //查询返回空值
return -1;
}
int count = userCursor.getCount();
if (count > 0) { //存在现有账户,取第一个账户的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();
}
}
}
/**
* 添加日历账户,账户创建成功则返回账户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);
// 可见度
value.put(CalendarContract.Calendars.VISIBLE, 1);
// 日历颜色
value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE);
// 权限
value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
value.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
// 时区
value.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, timeZone.getID());
value.put(CalendarContract.Calendars.OWNER_ACCOUNT, CALENDARS_ACCOUNT_NAME);
value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0);
Uri calendarUri = 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;
}
/**
* 这个是关键方法,调用插入日程提醒
*
* @param context
* @param eventId 事件id
* @param title 提醒事件标题
* @param description 事件描述
* @param reminderTime 任务开始时间,这里参数名不太合适,后面会加提醒时间,
* @param endTime 任务结束时间
* @param previousMinutes 提前多少分钟提醒,后续使用
* @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); //获取日历账户的id
if (calId < 0) { //获取账户id失败直接返回,添加日历事件失败
return -1L;
}
//添加日历事件
Calendar mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(reminderTime);//设置开始时间
long start = mCalendar.getTime().getTime();
mCalendar.setTimeInMillis(endTime);//设置终止时间
long end = mCalendar.getTime().getTime();
ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
event.put("calendar_id", calId); //插入账户的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);//设置有闹钟提醒,但是经测试,此方案无效
}
event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getDisplayName());//这个是时区,必须有
Uri newEvent = context.getContentResolver().insert(CalendarContract.Events.CONTENT_URI, event); //添加事件
if (newEvent == null) { //添加日历事件失败直接返回
return -1L;
}
//扩展属性 用于高版本安卓系统设置闹钟提醒
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;
}
}
//事件提醒的设定
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, "设置日程成功!!!", 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;
}
}
/**
* 查询日历日程相关的数据库表(查询其他表也适用),方法将查询表的所有列的所有行都展示出来了,就是这么人性化
*
* @param uri 用来区分查询的表的类型,查询不同的表,使用不同的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);//多少个属性
for (int i = 0; i < columnCount; i++) {
//获取到属性的名称
String columnName = cursor.getColumnName(i);
//获取到属性对应的值
String message = cursor.getString(cursor.getColumnIndex(columnName));
//打印属性和对应的值
Log.e("TAG", columnName + " : " + message);
}
}
}
}
Demo
页面布局
<?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);
}
/**
* 检查是否存在现有账户,存在则返回账户id,否则返回-1
*/
/**
* 添加日历账户,账户创建成功则返回账户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);
}
}
}
效果
文章来源:https://www.toymoban.com/news/detail-775827.html
仓库地址
Gitee地址 AndroidDemo文章来源地址https://www.toymoban.com/news/detail-775827.html
到了这里,关于Android 操作系统日历完成提醒功能 附带开关闹钟 适配高版本安卓的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!