如何在Xamarin中获取日历全部数据含手动添加事件与提醒
解决Xamarin Android获取全部日历事件的问题
看起来你遇到的问题主要来自两个方面:列引用错误和权限/查询范围的问题,下面一步步帮你修正:
1. 修正错误的列引用
你代码里用了ContactsContract.Contacts.InterfaceConsts.Id来获取事件ID,这明显混淆了联系人与日历事件的Contract,应该替换为CalendarContract.Events.InterfaceConsts.Id。另外,虽然从Events Uri查询CalendarContract.Calendars的字段是可行的,但统一使用CalendarContract.Events下的字段会更规范。
2. 确保拥有正确的日历权限
Android 6.0(API 23)及以上版本,读取日历需要动态申请运行时权限,仅在Manifest里声明是不够的:
- 首先在
AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.READ_CALENDAR" />
- 在代码中先检查权限,未授权则发起申请:
if (ContextCompat.CheckSelfPermission(Forms.Context, Manifest.Permission.ReadCalendar) != Permission.Granted) { ActivityCompat.RequestPermissions((Activity)Forms.Context, new string[] { Manifest.Permission.ReadCalendar }, 100); }
记得在OnRequestPermissionsResult方法中处理权限申请结果,只有权限通过后再执行日历查询逻辑。
3. 修正后的完整查询代码
下面是修正后的代码,确保能获取所有日历(包括手动添加事件所在的日历)的事件:
var calendarEventList = new List<Calendar>(); var eventsUri = CalendarContract.Events.ContentUri; // 定义需要查询的字段,避免不必要的列查询,提升性能 string[] projection = new[] { CalendarContract.Events.InterfaceConsts.Id, CalendarContract.Events.InterfaceConsts.CalendarDisplayName, CalendarContract.Events.InterfaceConsts.AccountName, CalendarContract.Events.InterfaceConsts.Title, CalendarContract.Events.InterfaceConsts.Description, CalendarContract.Events.InterfaceConsts.Dtstart, CalendarContract.Events.InterfaceConsts.Dtend }; if (ContextCompat.CheckSelfPermission(Forms.Context, Manifest.Permission.ReadCalendar) == Permission.Granted) { var cursor = Forms.Context.ContentResolver.Query(eventsUri, projection, null, null, null); if (cursor != null && cursor.MoveToFirst()) { do { calendarEventList.Add(new Calendar() { Id = cursor.GetString(cursor.GetColumnIndex(projection[0])), CalendarDisplayName = cursor.GetString(cursor.GetColumnIndex(projection[1])), AccountName = cursor.GetString(cursor.GetColumnIndex(projection[2])), Title = cursor.GetString(cursor.GetColumnIndex(projection[3])), Description = cursor.GetString(cursor.GetColumnIndex(projection[4])), Dtstart = cursor.GetString(cursor.GetColumnIndex(projection[5])), Dtend = cursor.GetString(cursor.GetColumnIndex(projection[6])) }); } while (cursor.MoveToNext()); cursor.Close(); // 记得关闭cursor,避免内存泄漏 } }
额外提示
- 如果还是只获取到节假日,检查手动事件是否存在于某个特定日历中:可以先查询所有日历列表,确认这些日历的ID,然后在查询事件时添加过滤条件(比如
CalendarContract.Events.InterfaceConsts.CalendarId = ?)来验证。 Dtstart和Dtend返回的是毫秒级时间戳,可转换为DateTime类型方便使用:DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(cursor.GetString(...))).DateTime
内容的提问来源于stack exchange,提问作者student
相关产品推荐
相关产品推荐

