上一篇
安卓开发 日历api
- 行业动态
- 2025-04-21
- 3
安卓日历API核心操作指南
权限管理
操作日历需要申请敏感权限,需在AndroidManifest.xml
声明并动态申请:
<uses-permission android:name="android.permission.READ_CALENDAR"/> <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
动态申请示例:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CALENDAR}, REQUEST_CODE); }
核心API接口
操作类型 | 方法/组件 | 说明 |
---|---|---|
数据读写 | ContentResolver |
通过URI操作日历数据库 |
系统交互 | CalendarContract |
提供标准日历数据接口 |
事件创建 | ContentValues |
构建日历事件参数 |
时间处理 | Calendar /Date |
时间计算与格式化 |
常用URI与字段
标准日历URI:
// 获取所有事件 Uri eventsUri = CalendarContract.Events.CONTENT_URI; // 获取特定日历下的事件 Uri calendarEventsUri = CalendarContract.Events.CONTENT_URI.buildUpon() .appendQueryParameter(CalendarContract.Calendars._ID, "calendar_id") .build();
常用字段映射表:
| 字段名 | 含义 | 数据类型 |
|——–|——|———-|
| DTSTART
| 事件开始时间 | long (毫秒级时间戳) |
| DTEND
| 事件结束时间 | long | | 事件标题 | String |
| DESCRIPTION
| 事件描述 | String |
| EVENT_LOCATION
| 事件地点 | String |
| ALL_DAY
| 是否全天事件 | int (0/1) |
核心操作示例
查询日历事件
// 构造查询条件 String[] projection = new String[]{ CalendarContract.Events._ID, CalendarContract.Events.TITLE, CalendarContract.Events.DTSTART, CalendarContract.Events.DTEND }; // 执行查询 Cursor cursor = getContentResolver().query( CalendarContract.Events.CONTENT_URI, projection, null, null, CalendarContract.Events.DTSTART + " DESC" // 按开始时间倒序 );
添加新事件
ContentValues values = new ContentValues(); values.put(CalendarContract.Events.TITLE, "会议主题"); values.put(CalendarContract.Events.DESCRIPTION, "项目进度讨论"); values.put(CalendarContract.Events.DTSTART, System.currentTimeMillis()); // 当前时间 values.put(CalendarContract.Events.DTEND, System.currentTimeMillis() + 3600000); // 1小时后 values.put(CalendarContract.Events.CALENDAR_ID, getDefaultCalendarId()); // 获取默认日历ID values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID()); // 插入数据 Uri eventUri = getContentResolver().insert(CalendarContract.Events.CONTENT_URI, values); long eventId = Long.parseLong(eventUri.getLastPathSegment());
删除事件
Uri deleteUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventId); int rows = getContentResolver().delete(deleteUri, null, null);
关键辅助方法
获取默认日历ID:
private long getDefaultCalendarId() { Cursor cursor = getContentResolver().query( CalendarContract.Calendars.CONTENT_URI, new String[]{CalendarContract.Calendars._ID}, CalendarContract.Calendars.VISIBLE + "=1 AND " + CalendarContract.Calendars.IS_PRIMARY + "=1", null, null ); if (cursor != null && cursor.moveToFirst()) { long id = cursor.getLong(0); cursor.close(); return id; } return -1; // 未找到默认日历 }
时间转换工具:
// 将Calendar对象转为毫秒时间戳 final Calendar cal = Calendar.getInstance(); cal.set(2023, Calendar.DECEMBER, 25, 14, 30); // 2023-12-25 14:30 long startMillis = cal.getTimeInMillis();
注意事项
- 权限适配:Android 10+ 对后台访问日历有限制,需处理
Storage permission
变更 - 时区处理:始终使用
EVENT_TIMEZONE
字段指定时区,避免跨时区问题 - 数据同步:系统日历应用可能自动清理过期事件,重要数据建议备份到云端
- 厂商差异:部分定制系统(如EMUI)可能有特殊权限要求
相关问题与解答
Q1:如何处理日历权限被用户拒绝的情况?
A1:在onRequestPermissionsResult
回调中检查权限状态,若被拒绝应:
- 显示权限说明对话框
- 提供应用设置入口引导用户手动开启
- 禁用依赖该权限的功能按钮
Q2:如何保证跨设备/应用的数据一致性?
A2:建议通过以下方式:
- 使用
sync adapter
实现数据同步 - 监听日历数据变化(
ContentObserver
) - 重要事件数据存储到远程服务器
- 使用
Account
机制关联用户