具有DependencyService的Android设备日历不起作用

问题描述 投票:0回答:1

我制作了Xamarin.Forms应用,并希望将约会自动保存到设备日历中,而无需任何通知。

我找到了Microsoft解决方案:[Xamarin.Android日历] [1]

我不知道出了什么问题,我没有遇到任何异常,程序运行良好,但是我看不到任何保存到设备日历的约会。我也授予了读写权限

(在我也尝试过StartActivity版本之前,该方法起作用了,但是如果我从该应用程序发送了30个约会,如果设备日历显示了30次,用户将会发疯。

请给我任何建议,怎么了?

        public async Task<bool> AddAppointment(List<TestItem> xys)
        {
            var items = TestItem.GetAppointmentsToDeviceCalendar(xys);

            foreach (CalendarEvent item in items)
            {
                var uri = Android.App.Application.Context.ContentResolver.Insert(CalendarContract.Events.ContentUri, ToCalendarEvent(item));
            }
            return true;
        }

        private ContentValues ToCalendarEvent(CalendarEvent item)
        {
            ContentValues cv = new ContentValues();
            cv.Put(CalendarContract.Events.InterfaceConsts.CalendarTimeZone, TimeZone.Default.DisplayName);
            cv.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, "local");
            cv.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.DisplayName);
            cv.Put(CalendarContract.Events.InterfaceConsts.CalendarId, 1);
            cv.Put(CalendarContract.Events.InterfaceConsts.Title, item.Name);
            cv.Put(CalendarContract.Events.InterfaceConsts.Description, item.Description);
            cv.Put(CalendarContract.Events.InterfaceConsts.EventLocation, item.Location);
            cv.Put(CalendarContract.Events.InterfaceConsts.Dtstart, GetDateTimeMS(item.Start.Year, item.Start.Month, item.Start.Day, item.Start.Year, item.Start.Minute));
            cv.Put(CalendarContract.Events.InterfaceConsts.Dtend, GetDateTimeMS(item.End.Year, item.End.Month, item.End.Day, item.End.Hour, item.End.Minute));
            return cv;
        }

        long GetDateTimeMS(int yr, int month, int day, int hr, int min)
        {
            Calendar c = Calendar.GetInstance(Java.Util.TimeZone.Default);

            c.Set(Java.Util.CalendarField.DayOfMonth, day);
            c.Set(Java.Util.CalendarField.HourOfDay, hr);
            c.Set(Java.Util.CalendarField.Minute, min);
            c.Set(Java.Util.CalendarField.Month, month);
            c.Set(Java.Util.CalendarField.Year, yr);

            return c.TimeInMillis;
        }

  [1]: https://docs.microsoft.com/en-us/xamarin/android/user-interface/controls/calendar
c# android xamarin xamarin.android calendar
1个回答
0
投票

要作为同步适配器执行操作,应将CalendarContract.CALLER_IS_SYNCADAPTER设置为true,并且必须在Uri参数中设置CalendarContract.SyncColumns.ACCOUNT_NAMECalendarContract.SyncColumns.ACCOUNT_TYPE

尝试如下更改代码:

var uri = CalendarContract.Calendars.ContentUri;

uri = uri.BuildUpon()
    .AppendQueryParameter(CalendarContract.CallerIsSyncadapter, "true")
    .AppendQueryParameter(CalendarContract.Calendars.InterfaceConsts.AccountName, AccountName)      
    .AppendQueryParameter(CalendarContract.Calendars.InterfaceConsts.AccountType, CalendarContract.AccountTypeLocal)
    .Build();

Android.App.Application.Context.ContentResolver.Insert(uri, ToCalendarEvent(item));

参考:https://stackoverflow.com/a/33291608/11083277

更新:

我创建了一个基本的演示来测试该功能,并且效果很好。该事件已添加到设备的日历中,您可以参考代码。

public class MainActivity : AppCompatActivity
{
    private static string CALENDER_URL = "content://com.android.calendar/calendars";
    private static string CALENDER_EVENT_URL = "content://com.android.calendar/events";
    private static string CALENDER_REMINDER_URL = "content://com.android.calendar/reminders";

    private static string CALENDARS_NAME = "test";
    private static string CALENDARS_ACCOUNT_NAME = "[email protected]";
    private static string CALENDARS_ACCOUNT_TYPE = "com.android.test";
    private static string CALENDARS_DISPLAY_NAME = "hello-test";

    long account_id;
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.activity_main);

        //requestedPermission: you need request the permissions at runtime

        account_id = addCalendarAccount(this);

        Calendar c = Calendar.GetInstance(TimeZone.Default);
        c.Set(CalendarField.DayOfMonth, 15);
        c.Set(CalendarField.HourOfDay, 10);
        c.Set(CalendarField.Minute, 0);
        c.Set(CalendarField.Month, Calendar.July);
        c.Set(CalendarField.Year, 2020);

        addCalendarEvent("title", "description", c.TimeInMillis);
    }

    public long addCalendarAccount(Context context)
    {

        TimeZone timeZone = TimeZone.Default;
        ContentValues value = new ContentValues();
        value.Put(CalendarContract.Calendars.Name, CALENDARS_NAME);
        value.Put(CalendarContract.Calendars.InterfaceConsts.AccountName, CALENDARS_ACCOUNT_NAME);
        value.Put(CalendarContract.Calendars.InterfaceConsts.AccountType, CALENDARS_ACCOUNT_TYPE);
        value.Put(CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName, CALENDARS_DISPLAY_NAME);
        value.Put(CalendarContract.Calendars.InterfaceConsts.Visible, 1);
        value.Put(CalendarContract.Calendars.InterfaceConsts.CalendarColor, Color.Blue);
        value.Put(CalendarContract.Calendars.InterfaceConsts.SyncEvents, 1);
        value.Put(CalendarContract.Calendars.InterfaceConsts.CalendarTimeZone, timeZone.ID);
        value.Put(CalendarContract.Calendars.InterfaceConsts.OwnerAccount, CALENDARS_ACCOUNT_NAME);

        Uri calendarUri = Uri.Parse(CALENDER_URL);
        calendarUri = calendarUri.BuildUpon()
                .AppendQueryParameter(CalendarContract.CallerIsSyncadapter, "true")
                .AppendQueryParameter(CalendarContract.Calendars.InterfaceConsts.AccountName, CALENDARS_ACCOUNT_NAME)
                .AppendQueryParameter(CalendarContract.Calendars.InterfaceConsts.AccountType, CALENDARS_ACCOUNT_TYPE)
                .Build();

        Uri result = context.ContentResolver.Insert(calendarUri, value);
        long id = result == null ? -1 : ContentUris.ParseId(result);
        return id;
    }

    public void addCalendarEvent(string title, string description, long reminderTime)
    {
        Calendar mCalendar = Calendar.Instance;
        mCalendar.TimeInMillis = (reminderTime);//set the start time
        long start = mCalendar.Time.Time;
        mCalendar.TimeInMillis = (start + 10 * 60 * 1000);//set the end time
        long end = mCalendar.Time.Time;

        ContentValues eventValues = new ContentValues();

        eventValues.Put("title", title);
        eventValues.Put("description", description);
        eventValues.Put("calendar_id", account_id); //int the account id
        eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, start);
        eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, end);
        eventValues.Put(CalendarContract.Events.InterfaceConsts.HasAlarm, 1);
        eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, "Asia/Shanghai");
        Uri newEvent = this.ContentResolver.Insert(Uri.Parse(CALENDER_EVENT_URL), eventValues);
        if (newEvent == null)
        {
            return;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.