Android平台Calendar的resultCode判定问题求助
onActivityResult判断日历事件是否创建成功的解决方案 嘿,我懂你遇到的这个坑——用ACTION_EDIT拉起系统日历编辑界面后,靠onActivityResult的resultCode根本没法准确判断用户到底有没有真的创建事件,毕竟很多厂商的日历应用返回结果太不统一了,不管是保存还是取消,大概率都给你返回RESULT_OK,完全没参考性。
给你几个实用的解决思路:
通过查询日历数据库做最终验证
这是最靠谱的方式,毕竟事件真的创建了才会出现在日历数据库里。不过前提是你得先获取READ_CALENDAR和WRITE_CALENDAR的动态权限(Android 6.0及以上需要),然后在onActivityResult里去查询验证。比如你可以在拉起日历的时候预设一个唯一的描述或者标记,之后用这个标记去匹配查询:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1 && resultCode == RESULT_OK) { ContentResolver cr = getContentResolver(); Uri eventUri = Events.CONTENT_URI; // 这里用你预先设置的唯一标识来筛选,比如自定义的描述 String selection = Events.DESCRIPTION + " = ?"; String[] selectionArgs = {"我的唯一事件标记"}; Cursor cursor = cr.query(eventUri, new String[]{Events._ID}, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { // 查到了,说明事件真的创建成功 Toast.makeText(this, "日历事件已创建", Toast.LENGTH_SHORT).show(); cursor.close(); } else { // 没查到,大概率用户取消了保存 Toast.makeText(this, "日历事件未创建", Toast.LENGTH_SHORT).show(); } } }拉起日历的时候记得把这个唯一标识传进去:
Intent intCalendar = new Intent(Intent.ACTION_EDIT); intCalendar.setType("vnd.android.cursor.item/event"); intCalendar.putExtra(Events.DESCRIPTION, "我的唯一事件标记"); startActivityForResult(intCalendar, 1);如果不需要用户编辑,改用
ACTION_INSERT直接创建
要是你不需要让用户手动修改事件内容,只是想快速创建,直接用ACTION_INSERT并带上所有事件参数(标题、时间、地点等),这种方式下部分厂商的日历会返回更准确的resultCode——保存返回RESULT_OK,取消返回RESULT_CANCELED。示例代码:Intent insertIntent = new Intent(Intent.ACTION_INSERT) .setData(Events.CONTENT_URI) .putExtra(Events.TITLE, "周末聚餐") .putExtra(Events.DTSTART, System.currentTimeMillis() + 86400000) .putExtra(Events.DTEND, System.currentTimeMillis() + 90000000) .putExtra(Events.EVENT_LOCATION, "XX餐厅"); startActivityForResult(insertIntent, 1);不过还是要提醒你,部分厂商的日历依然不遵循这个规范,所以最好还是结合数据库查询做双重验证。
适配新系统:替换废弃的
startActivityForResult
从Android 10(API 29)开始,startActivityForResult已经被废弃了,推荐用ActivityResultContracts.StartActivityForResult来替代,写法更简洁也更适配新系统:// 先注册启动器 ActivityResultLauncher<Intent> calendarLauncher = registerForActivityResult( new StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK) { // 在这里执行数据库查询验证逻辑 } } ); // 拉起日历的时候调用launch方法 Intent intCalendar = new Intent(Intent.ACTION_EDIT); intCalendar.setType("vnd.android.cursor.item/event"); intCalendar.putExtra(Events.DESCRIPTION, "我的唯一事件标记"); calendarLauncher.launch(intCalendar);
内容的提问来源于stack exchange,提问作者Breno

