如何在 Android 中添加日历事件?

Posted

技术标签:

【中文标题】如何在 Android 中添加日历事件?【英文标题】:How to add calendar events in Android? 【发布时间】:2011-04-12 22:13:39 【问题描述】:

我刚刚开始熟悉 android,今天在一次项目会议上,有人说 Android 没有原生日历应用,所以用户只需使用他们喜欢的任何日历应用即可。

这是真的吗?如果是,我如何以编程方式将事件添加到用户的日历中?他们有共同的 API 吗?

不管怎样,我们的目标可能是 Android 2.x。

【问题讨论】:

您可能应该接受 oriharel 的回答,因为他提供了完成您任务的代码。 @SumitSharma 您的链接似乎不再有效 - 自动安装对话框似乎很可疑。 【参考方案1】:

Android 主要提供两种处理日历事件的方法。一个正在使用Calendar Provider,另一个正在将其交给system Calendar app.

日历提供程序为我们提供所有功能,包括插入、查询、更新和删除现有日历事件。但是,这些步骤很繁琐,并且必须需要用户的运行时权限(android.permission.READ_CALENDAR 和android.permission.WRITE_CALENDAR)才能读取和写入敏感的日历信息。这种方法很容易出错。

Google 官方建议开发者使用第二种方式,即使用 Intent 将所有日历操作交给系统日历应用。日历应用程序在我们的应用程序请求后立即打开

甚至插入新日历

    val startMillis: Long = Calendar.getInstance().run 
    set(2012, 0, 19, 7, 30)
    timeInMillis

val endMillis: Long = Calendar.getInstance().run 
    set(2012, 0, 19, 8, 30)
    timeInMillis

val intent = Intent(Intent.ACTION_INSERT)
        .setData(CalendarContract.Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis)
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis)
        .putExtra(CalendarContract.Events.TITLE, "Yoga")
        .putExtra(CalendarContract.Events.DESCRIPTION, "Group class")
        .putExtra(CalendarContract.Events.EVENT_LOCATION, "The gym")
        .putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com")
startActivity(intent)

以下活动已打开

【讨论】:

【参考方案2】:

这是向日历添加事件的 Kotlin 版本:

            val intent = Intent(Intent.ACTION_EDIT)
            intent.type = "vnd.android.cursor.item/event"
            intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startTime)
            intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime)
            intent.putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, false)
            intent.putExtra(CalendarContract.Events.TITLE, mTitle)
            startActivity(intent)

【讨论】:

【参考方案3】:

在你的代码中试试这个:

Calendar cal = Calendar.getInstance();              
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setType("vnd.android.cursor.item/event");
intent.putExtra("beginTime", cal.getTimeInMillis());
intent.putExtra("allDay", true);
intent.putExtra("rrule", "FREQ=YEARLY");
intent.putExtra("endTime", cal.getTimeInMillis()+60*60*1000);
intent.putExtra("title", "A Test Event from android app");
startActivity(intent);

【讨论】:

我非常喜欢这个解决方案。主要是因为它促使用户选择他/她自己的日历(如果他有多个日历)。 如何让它兼容android 2.2? 您应该使用 .setData(CalendarContract.Events.CONTENT_URI) 而不是 setType,因为使用 setType(string) 会在某些设备上崩溃! 完整教程在这里:code.tutsplus.com/tutorials/… 最好使用常量来避免拼写错误;) 您的代码告诉您的应用程序将数据发送到另一个(日历)应用程序,然后该应用程序使用该数据添加新的日历事件。您的应用不会写入或读取日历数据,因此您不需要清单中的任何权限。【参考方案4】:

在您的代码中使用此 API.. 它将帮助您插入事件,可以启用带有提醒的事件和带有会议的事件...此 api 适用于平台 2.1 及以上 那些使用少于 2.1 而不是 content://com.android.calendar/events 的人使用 content://calendar/events

 public static long pushAppointmentsToCalender(Activity curActivity, String title, String addInfo, String place, int status, long startDate, boolean needReminder, boolean needMailService) 
    /***************** Event: note(without alert) *******************/

    String eventUriString = "content://com.android.calendar/events";
    ContentValues eventValues = new ContentValues();

    eventValues.put("calendar_id", 1); // id, We need to choose from
                                        // our mobile for primary
                                        // its 1
    eventValues.put("title", title);
    eventValues.put("description", addInfo);
    eventValues.put("eventLocation", place);

    long endDate = startDate + 1000 * 60 * 60; // For next 1hr

    eventValues.put("dtstart", startDate);
    eventValues.put("dtend", endDate);

    // values.put("allDay", 1); //If it is bithday alarm or such
    // kind (which should remind me for whole day) 0 for false, 1
    // for true
    eventValues.put("eventStatus", status); // This information is
    // sufficient for most
    // entries tentative (0),
    // confirmed (1) or canceled
    // (2):
    eventValues.put("eventTimezone", "UTC/GMT +2:00");
   /*Comment below visibility and transparency  column to avoid java.lang.IllegalArgumentException column visibility is invalid error */

    /*eventValues.put("visibility", 3); // visibility to default (0),
                                        // confidential (1), private
                                        // (2), or public (3):
    eventValues.put("transparency", 0); // You can control whether
                                        // an event consumes time
                                        // opaque (0) or transparent
                                        // (1).
      */
    eventValues.put("hasAlarm", 1); // 0 for false, 1 for true

    Uri eventUri = curActivity.getApplicationContext().getContentResolver().insert(Uri.parse(eventUriString), eventValues);
    long eventID = Long.parseLong(eventUri.getLastPathSegment());

    if (needReminder) 
        /***************** Event: Reminder(with alert) Adding reminder to event *******************/

        String reminderUriString = "content://com.android.calendar/reminders";

        ContentValues reminderValues = new ContentValues();

        reminderValues.put("event_id", eventID);
        reminderValues.put("minutes", 5); // Default value of the
                                            // system. Minutes is a
                                            // integer
        reminderValues.put("method", 1); // Alert Methods: Default(0),
                                            // Alert(1), Email(2),
                                            // SMS(3)

        Uri reminderUri = curActivity.getApplicationContext().getContentResolver().insert(Uri.parse(reminderUriString), reminderValues);
    

    /***************** Event: Meeting(without alert) Adding Attendies to the meeting *******************/

    if (needMailService) 
        String attendeuesesUriString = "content://com.android.calendar/attendees";

        /********
         * To add multiple attendees need to insert ContentValues multiple
         * times
         ***********/
        ContentValues attendeesValues = new ContentValues();

        attendeesValues.put("event_id", eventID);
        attendeesValues.put("attendeeName", "xxxxx"); // Attendees name
        attendeesValues.put("attendeeEmail", "yyyy@gmail.com");// Attendee
                                                                            // E
                                                                            // mail
                                                                            // id
        attendeesValues.put("attendeeRelationship", 0); // Relationship_Attendee(1),
                                                        // Relationship_None(0),
                                                        // Organizer(2),
                                                        // Performer(3),
                                                        // Speaker(4)
        attendeesValues.put("attendeeType", 0); // None(0), Optional(1),
                                                // Required(2), Resource(3)
        attendeesValues.put("attendeeStatus", 0); // NOne(0), Accepted(1),
                                                    // Decline(2),
                                                    // Invited(3),
                                                    // Tentative(4)

        Uri attendeuesesUri = curActivity.getApplicationContext().getContentResolver().insert(Uri.parse(attendeuesesUriString), attendeesValues);
    

    return eventID;


【讨论】:

我添加了event.put("eventTimezone", "UTC/GMT +2:00")并删除了event.put("visibility", 3)event.put("transparency", 0),效果很好 可能出现时区错误。我添加了这个及其作品 eventValues.put("eventTimezone", TimeZone.getDefault().getID()); 我在Uri reminderUri = curActivity.getApplicationContext().getContentResolver().insert(Uri.parse(reminderUriString), reminderValues); 行收到android.database.sqlite.SQLiteException 但是当我设置 values.put("rrule", "FREQ=DAILY");并设置 endDate,它不起作用。为直到结束日期的所有日期设置事件。 @AmitabhaBiswas values.put(CalendarContract.Reminders.CALENDAR_ID, 1); values.put(CalendarContract.Reminders.TITLE, "Routine Everyday1"); values.put(CalendarContract.Reminders.DTSTART, millisecondsTimesEveryday); values.put(CalendarContract.Reminders.HAS_ALARM, true); values.put("rrule", "FREQ=DAILY"); //UNTIL=1924885800000 values.put(CalendarContract.Reminders.DTEND, EndtimeInMilliseconds); @AmitabhaBiswas【参考方案5】:

你必须添加标志:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

否则你会导致错误:

来自 Activity 上下文外部的startActivity() 需要FLAG_ACTIVITY_NEW_TASK

【讨论】:

【参考方案6】:

以防万一有人在 c# 中需要 Xamarin:

        Intent intent = new Intent(Intent.ActionInsert);
        intent.SetData(Android.Provider.CalendarContract.Events.ContentUri);
        intent.PutExtra(Android.Provider.CalendarContract.ExtraEventBeginTime, Utils.Tools.CurrentTimeMillis(game.Date));
        intent.PutExtra(Android.Provider.CalendarContract.EventsColumns.AllDay, false);
        intent.PutExtra(Android.Provider.CalendarContract.EventsColumns.EventLocation, "Location");
        intent.PutExtra(Android.Provider.CalendarContract.EventsColumns.Description, "Description");
        intent.PutExtra(Android.Provider.CalendarContract.ExtraEventEndTime, Utils.Tools.CurrentTimeMillis(game.Date.AddHours(2)));
        intent.PutExtra(Android.Provider.CalendarContract.EventsColumns.Title, "Title");
        StartActivity(intent);

辅助函数:

    private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static long CurrentTimeMillis(DateTime date)
    
        return (long)(date.ToUniversalTime() - Jan1st1970).TotalMilliseconds;
    

【讨论】:

【参考方案7】:

如果您有一个给定的日期字符串,其中包含日期和时间。

例如String givenDateString = pojoModel.getDate()/* Format dd-MMM-yyyy hh:mm:ss */

使用以下代码将带有日期和时间的事件添加到日历中

Calendar cal = Calendar.getInstance();
cal.setTime(new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss").parse(givenDateString));
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setType("vnd.android.cursor.item/event");
intent.putExtra("beginTime", cal.getTimeInMillis());
intent.putExtra("allDay", false);
intent.putExtra("rrule", "FREQ=YEARLY");
intent.putExtra("endTime",cal.getTimeInMillis() + 60 * 60 * 1000);
intent.putExtra("title", " Test Title");
startActivity(intent);

【讨论】:

【参考方案8】:

试试这个,

   Calendar beginTime = Calendar.getInstance();
    beginTime.set(yearInt, monthInt - 1, dayInt, 7, 30);



    ContentValues l_event = new ContentValues();
    l_event.put("calendar_id", CalIds[0]);
    l_event.put("title", "event");
    l_event.put("description",  "This is test event");
    l_event.put("eventLocation", "School");
    l_event.put("dtstart", beginTime.getTimeInMillis());
    l_event.put("dtend", beginTime.getTimeInMillis());
    l_event.put("allDay", 0);
    l_event.put("rrule", "FREQ=YEARLY");
    // status: 0~ tentative; 1~ confirmed; 2~ canceled
    // l_event.put("eventStatus", 1);

    l_event.put("eventTimezone", "India");
    Uri l_eventUri;
    if (Build.VERSION.SDK_INT >= 8) 
        l_eventUri = Uri.parse("content://com.android.calendar/events");
     else 
        l_eventUri = Uri.parse("content://calendar/events");
    
    Uri l_uri = MainActivity.this.getContentResolver()
            .insert(l_eventUri, l_event);

【讨论】:

【参考方案9】:

我使用了下面的代码,它解决了我在 ICS 的默认设备日历中添加事件以及在低于 ICS 的版本上添加事件的问题

    if (Build.VERSION.SDK_INT >= 14) 
        Intent intent = new Intent(Intent.ACTION_INSERT)
        .setData(Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
        .putExtra(Events.TITLE, "Yoga")
        .putExtra(Events.DESCRIPTION, "Group class")
        .putExtra(Events.EVENT_LOCATION, "The gym")
        .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com");
         startActivity(intent);


    else 
        Calendar cal = Calendar.getInstance();              
        Intent intent = new Intent(Intent.ACTION_EDIT);
        intent.setType("vnd.android.cursor.item/event");
        intent.putExtra("beginTime", cal.getTimeInMillis());
        intent.putExtra("allDay", true);
        intent.putExtra("rrule", "FREQ=YEARLY");
        intent.putExtra("endTime", cal.getTimeInMillis()+60*60*1000);
        intent.putExtra("title", "A Test Event from android app");
        startActivity(intent);
        

希望对你有所帮助.....

【讨论】:

关于Build.VERSION.SDK_INT > 14,如何添加60分钟的默认提醒以及如何获取提醒的ID?谢谢 嗨,我想知道是否可以修改显示可编辑日历字段的屏幕(例如更改某些视图的外观)? @user1950599 绝对不是。 Intent 从另一个应用程序启动一个 Activity,与它的唯一交互是您通过 Intent 发送的数据。【参考方案10】:

Google 日历是“本机”日历应用。据我所知,所有手机都安装了它的版本,默认的SDK提供了一个版本。

您可以查看此tutorial 以了解如何使用它。

【讨论】:

【参考方案11】:

如何以编程方式将事件添加到用户的日历?

哪个日历?

是否有他们共享的通用 API?

不,只是有一个用于 Windows 日历应用的“它们都共享的通用 API”。有一些通用的数据格式(例如 iCalendar)和 Internet 协议(例如 CalDAV),但没有通用的 API。有些日历应用甚至不提供 API。

如果您希望集成特定的日历应用程序,请联系他们的开发人员并确定他们是否提供 API。因此,例如,Mayra 引用的 Android 开源项目中的日历应用程序没有提供文档化和支持的 API。 Google 甚至在 Mayra 引用的教程中列出了 explicitly told developers to not use the techniques。

另一个选项是您可以将事件添加到相关的 Internet 日历中。例如,将事件从 Android 开源项目添加到日历应用程序的最佳方法是通过适当的 GData API 将事件添加到用户的 Google 日历。


更新

Android 4.0(API 级别 14)添加了 CalendarContract ContentProvider

【讨论】:

我们不想针对特定的日历 - 我们只想能够将事件添加到用户正在使用的任何日历中,这只是为了方便用户。我们的应用程序为组织专业会议的网站提供了一个界面。因此,如果有人注册,最好将其添加到他们的日历中。 @Peter Nelson:“我们不想针对特定的日历 - 我们只想能够将事件添加到用户正在使用的任何日历中,以方便用户。” ——你不能在 Android 上做到这一点,就像你在 Windows 上做不到一样。在这两个平台上,您都不知道“用户正在使用什么日历”,并且在这两个平台上都没有用于处理此类日历应用程序的通用 API。 我不知道你为什么一直将它与 Windows 进行比较 - 我认识的每个人都使用手机来组织他们的日程安排和约会 - 我不知道有人在他们的 PC 上这样做 - 也许这是一个世代相传的事情。但我知道Android无法做到这一点。谢谢。 @Peter Nelson:我一直将它与 Windows 进行比较,因为人们做出相同的假设。许多开发人员认为他们可以在 Windows 上“将事件添加到用户正在使用的任何日历中”,因为他们认为每个人都使用 Outlook,因此只有一个“任何日历”。 @Yar:“主要的 Android 手机日历,任何 Android 手机都有。” -- 没有该应用程序的所有 Android 设备除外。例如,许多 HTC 设备没有那个应用程序,而是有自己的日历应用程序,比如我左边六英寸的 HTC DROID Incredible。欢迎设备制造商用他们自己的实现替换日历应用程序——或几乎任何其他应用程序。【参考方案12】:

自 Android 4.0 版起,official APIs and intents are available 可与可用的calendar providers 交互。

【讨论】:

真正有用的评论,不能强调这一点:) 也许您可以提供一些代码来配合仅链接的答案?

以上是关于如何在 Android 中添加日历事件?的主要内容,如果未能解决你的问题,请参考以下文章

Web App 如何将日历事件添加到 Android 手机?

如何在本机日历中添加事件 - IONIC

使用 PhoneGap/jQuery Mobile 以编程方式在 iPhone/Android 日历中添加事件?

如何使用离子电容器将事件添加到移动设备的日历

如何在Android设备中获取设备日历事件列表?

如何使用android中的回收器视图将事件放在日历中[重复]