当前位置:首页 > 行业动态 > 正文

安卓开发 日历api

安卓日历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) |

安卓开发 日历api  第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();

注意事项

  1. 权限适配:Android 10+ 对后台访问日历有限制,需处理Storage permission变更
  2. 时区处理:始终使用EVENT_TIMEZONE字段指定时区,避免跨时区问题
  3. 数据同步:系统日历应用可能自动清理过期事件,重要数据建议备份到云端
  4. 厂商差异:部分定制系统(如EMUI)可能有特殊权限要求

相关问题与解答

Q1:如何处理日历权限被用户拒绝的情况?
A1:在onRequestPermissionsResult回调中检查权限状态,若被拒绝应:

  • 显示权限说明对话框
  • 提供应用设置入口引导用户手动开启
  • 禁用依赖该权限的功能按钮

Q2:如何保证跨设备/应用的数据一致性?
A2:建议通过以下方式:

  1. 使用sync adapter实现数据同步
  2. 监听日历数据变化(ContentObserver
  3. 重要事件数据存储到远程服务器
  4. 使用Account机制关联用户
0