You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:27:36