Android Studio开发应用向Google Calendar添加提醒失败求助
解决Google Calendar添加提醒失败的问题
我来帮你排查下这个给Google Calendar添加提醒失败的问题,看了你的代码后,发现几个容易踩坑的地方,咱们一个个来修正:
1. 权限缺失(最常见原因)
Android 6.0(API 23)及以上版本,WRITE_CALENDAR和READ_CALENDAR属于危险权限,必须动态申请,只在Manifest里声明是不够的。
- 先在
AndroidManifest.xml里静态声明权限:
<uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" />
- 在代码里动态申请权限(比如在Activity的
onCreate里):
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CALENDAR, Manifest.permission.READ_CALENDAR}, 1001); }
记得处理权限申请的回调,只有用户授权后再执行添加日历事件的逻辑。
2. 硬编码日历ID的问题
你代码里直接用了calendar_id=1,但不同设备的默认日历ID不一定是1,比如Google账户的日历ID可能是其他值。正确的做法是先获取用户的默认日历ID:
private long getDefaultCalendarId(ContentResolver cr) { Uri calendarUri = CalendarContract.Calendars.CONTENT_URI; String[] projection = {CalendarContract.Calendars._ID}; String selection = CalendarContract.Calendars.IS_PRIMARY + " = 1"; Cursor cursor = cr.query(calendarUri, projection, selection, null, null); if (cursor != null && cursor.moveToFirst()) { long id = cursor.getLong(0); cursor.close(); return id; } return 1; // fallback到1,如果没找到的话 }
然后把values.put("calendar_id", 1);替换成values.put(CalendarContract.Events.CALENDAR_ID, getDefaultCalendarId(cr));
3. 使用官方推荐的Content URI常量
你硬编码了content://com.android.calendar/events,不如直接用CalendarContract提供的常量,兼容性更好,比如:
- 事件URI用
CalendarContract.Events.CONTENT_URI - 提醒URI用
CalendarContract.Reminders.CONTENT_URI
4. 时间戳单位错误的细节
你原来的Date构造函数传的是秒级时间戳(比如1472570400),但Date需要的是毫秒级时间戳,所以要乘以1000,不然事件会被设置到1970年,自然看不到!
修正后的完整代码
// 先确保权限已授权,再执行以下逻辑 Date d1 = new Date(1472570400000L); // 转成毫秒级时间戳 Calendar cal1 = Calendar.getInstance(); cal1.setTime(d1); Date d2 = new Date(1472574000000L); // 同样转成毫秒 Calendar cal2 = Calendar.getInstance(); cal2.setTime(d2); ContentResolver cr = getContentResolver(); long defaultCalendarId = getDefaultCalendarId(cr); // 插入事件 ContentValues eventValues = new ContentValues(); eventValues.put(CalendarContract.Events.CALENDAR_ID, defaultCalendarId); eventValues.put(CalendarContract.Events.TITLE, "Reminder Title"); eventValues.put(CalendarContract.Events.ALL_DAY, 0); eventValues.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID()); eventValues.put(CalendarContract.Events.DTSTART, cal1.getTimeInMillis()); eventValues.put(CalendarContract.Events.DTEND, cal2.getTimeInMillis()); eventValues.put(CalendarContract.Events.DESCRIPTION, "Reminder description"); eventValues.put(CalendarContract.Events.HAS_ALARM, 1); Uri eventUri = cr.insert(CalendarContract.Events.CONTENT_URI, eventValues); if (eventUri == null) { Log.e("Calendar", "Event insertion failed"); return; } long eventId = Long.parseLong(eventUri.getLastPathSegment()); // 插入提醒 ContentValues reminderValues = new ContentValues(); reminderValues.put(CalendarContract.Reminders.EVENT_ID, eventId); reminderValues.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT); reminderValues.put(CalendarContract.Reminders.MINUTES, 1); Uri reminderUri = cr.insert(CalendarContract.Reminders.CONTENT_URI, reminderValues); if (reminderUri == null) { Log.e("Calendar", "Reminder insertion failed"); }
最后再补充两个测试建议:
- 确保设备上登录了Google账户,并且默认日历是Google日历
- 尽量用真实设备测试,部分模拟器的Calendar Provider可能存在兼容性问题
内容的提问来源于stack exchange,提问作者Umaima Khurshid Ahmad
相关产品推荐
相关产品推荐

