假设有一款应用可以帮助用户找到最佳的徒步路线。通过将徒步旅行计划添加为日历活动,用户可以自动获得许多帮助,从而保持井井有条。Google 日历可帮助他们分享计划并提醒他们,以便他们轻松做好准备。此外,由于 Google 产品可无缝集成,Google Now 会在他们应该出发的时间提醒他们,而 Google 地图会引导他们及时到达会议地点。
本文介绍了如何创建日历活动并将其添加到用户的日历中。
添加活动
如需创建活动,请调用 events.insert() 方法,并至少提供以下参数:
- calendarId是日历标识符,可以是用于创建活动的日历的电子邮件地址,也可以是特殊关键字- 'primary',该关键字将使用已登录用户的主日历。如果您不知道要使用的日历的电子邮件地址,可以在 Google 日历 Web 界面中的日历设置(在“日历地址”部分)中查看,也可以在- calendarList.list()调用的结果中查找。
- event是要创建的活动,其中包含所有必要的详细信息,例如开始时间和结束时间。只有- start和- end时间是必需的。如需查看完整的事件字段集,请参阅- event参考文档。
为了成功创建活动,您需要:
- 将 OAuth 范围设置为 https://www.googleapis.com/auth/calendar,以便您拥有对用户日历的修改权限。
- 确保经过身份验证的用户对您提供的 calendarId具有写入权限(例如,通过为calendarId调用calendarList.get()并检查accessRole来实现)。
添加活动元数据
您可以在创建日历活动时选择性添加活动元数据。如果您选择在创建期间不添加元数据,则可以使用 events.update() 更新许多字段;不过,某些字段(例如活动 ID)只能在 events.insert() 操作期间设置。
- 位置
- 在“地点”字段中添加地址后,即可使用“出发时间”等功能,或显示包含路线的地图。
- 事件 ID
- 创建活动时,您可以选择生成符合我们格式要求的自定义活动 ID。这样,您就可以使本地数据库中的实体与 Google 日历中的活动保持同步。如果操作在日历后端成功执行后在某个时间点失败,该方法还可以防止重复创建活动。如果未提供任何活动 ID,服务器会为您生成一个。如需了解详情,请参阅事件 ID 参考文档。
- 参加者
- 您创建的活动会显示在您添加的参会者的所有主 Google 日历中,且具有相同的活动 ID。如果您在插入请求中将 sendUpdates设置为"all"或"externalOnly",则相应参加者会收到有关您活动的电子邮件通知。如需了解详情,请参阅多人参加的活动。
以下示例演示了如何创建活动并设置其元数据:
Go
// Refer to the Go quickstart on how to setup the environment:
// https://developers.google.com/workspace/calendar/quickstart/go
// Change the scope to calendar.CalendarScope and delete any stored credentials.
event := &calendar.Event{
  Summary: "Google I/O 2015",
  Location: "800 Howard St., San Francisco, CA 94103",
  Description: "A chance to hear more about Google's developer products.",
  Start: &calendar.EventDateTime{
    DateTime: "2015-05-28T09:00:00-07:00",
    TimeZone: "America/Los_Angeles",
  },
  End: &calendar.EventDateTime{
    DateTime: "2015-05-28T17:00:00-07:00",
    TimeZone: "America/Los_Angeles",
  },
  Recurrence: []string{"RRULE:FREQ=DAILY;COUNT=2"},
  Attendees: []*calendar.EventAttendee{
    &calendar.EventAttendee{Email:"lpage@example.com"},
    &calendar.EventAttendee{Email:"sbrin@example.com"},
  },
}
calendarId := "primary"
event, err = srv.Events.Insert(calendarId, event).Do()
if err != nil {
  log.Fatalf("Unable to create event. %v\n", err)
}
fmt.Printf("Event created: %s\n", event.HtmlLink)
Java
// Refer to the Java quickstart on how to setup the environment:
// https://developers.google.com/workspace/calendar/quickstart/java
// Change the scope to CalendarScopes.CALENDAR and delete any stored
// credentials.
Event event = new Event()
    .setSummary("Google I/O 2015")
    .setLocation("800 Howard St., San Francisco, CA 94103")
    .setDescription("A chance to hear more about Google's developer products.");
DateTime startDateTime = new DateTime("2015-05-28T09:00:00-07:00");
EventDateTime start = new EventDateTime()
    .setDateTime(startDateTime)
    .setTimeZone("America/Los_Angeles");
event.setStart(start);
DateTime endDateTime = new DateTime("2015-05-28T17:00:00-07:00");
EventDateTime end = new EventDateTime()
    .setDateTime(endDateTime)
    .setTimeZone("America/Los_Angeles");
event.setEnd(end);
String[] recurrence = new String[] {"RRULE:FREQ=DAILY;COUNT=2"};
event.setRecurrence(Arrays.asList(recurrence));
EventAttendee[] attendees = new EventAttendee[] {
    new EventAttendee().setEmail("lpage@example.com"),
    new EventAttendee().setEmail("sbrin@example.com"),
};
event.setAttendees(Arrays.asList(attendees));
EventReminder[] reminderOverrides = new EventReminder[] {
    new EventReminder().setMethod("email").setMinutes(24 * 60),
    new EventReminder().setMethod("popup").setMinutes(10),
};
Event.Reminders reminders = new Event.Reminders()
    .setUseDefault(false)
    .setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders);
String calendarId = "primary";
event = service.events().insert(calendarId, event).execute();
System.out.printf("Event created: %s\n", event.getHtmlLink());
JavaScript
// Refer to the JavaScript quickstart on how to setup the environment:
// https://developers.google.com/workspace/calendar/quickstart/js
// Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
// stored credentials.
const event = {
  'summary': 'Google I/O 2015',
  'location': '800 Howard St., San Francisco, CA 94103',
  'description': 'A chance to hear more about Google\'s developer products.',
  'start': {
    'dateTime': '2015-05-28T09:00:00-07:00',
    'timeZone': 'America/Los_Angeles'
  },
  'end': {
    'dateTime': '2015-05-28T17:00:00-07:00',
    'timeZone': 'America/Los_Angeles'
  },
  'recurrence': [
    'RRULE:FREQ=DAILY;COUNT=2'
  ],
  'attendees': [
    {'email': 'lpage@example.com'},
    {'email': 'sbrin@example.com'}
  ],
  'reminders': {
    'useDefault': false,
    'overrides': [
      {'method': 'email', 'minutes': 24 * 60},
      {'method': 'popup', 'minutes': 10}
    ]
  }
};
const request = gapi.client.calendar.events.insert({
  'calendarId': 'primary',
  'resource': event
});
request.execute(function(event) {
  appendPre('Event created: ' + event.htmlLink);
});
Node.js
// Refer to the Node.js quickstart on how to setup the environment:
// https://developers.google.com/workspace/calendar/quickstart/node
// Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
// stored credentials.
const event = {
  'summary': 'Google I/O 2015',
  'location': '800 Howard St., San Francisco, CA 94103',
  'description': 'A chance to hear more about Google\'s developer products.',
  'start': {
    'dateTime': '2015-05-28T09:00:00-07:00',
    'timeZone': 'America/Los_Angeles',
  },
  'end': {
    'dateTime': '2015-05-28T17:00:00-07:00',
    'timeZone': 'America/Los_Angeles',
  },
  'recurrence': [
    'RRULE:FREQ=DAILY;COUNT=2'
  ],
  'attendees': [
    {'email': 'lpage@example.com'},
    {'email': 'sbrin@example.com'},
  ],
  'reminders': {
    'useDefault': false,
    'overrides': [
      {'method': 'email', 'minutes': 24 * 60},
      {'method': 'popup', 'minutes': 10},
    ],
  },
};
calendar.events.insert({
  auth: auth,
  calendarId: 'primary',
  resource: event,
}, function(err, event) {
  if (err) {
    console.log('There was an error contacting the Calendar service: ' + err);
    return;
  }
  console.log('Event created: %s', event.htmlLink);
});
PHP
$event = new Google_Service_Calendar_Event(array(
  'summary' => 'Google I/O 2015',
  'location' => '800 Howard St., San Francisco, CA 94103',
  'description' => 'A chance to hear more about Google\'s developer products.',
  'start' => array(
    'dateTime' => '2015-05-28T09:00:00-07:00',
    'timeZone' => 'America/Los_Angeles',
  ),
  'end' => array(
    'dateTime' => '2015-05-28T17:00:00-07:00',
    'timeZone' => 'America/Los_Angeles',
  ),
  'recurrence' => array(
    'RRULE:FREQ=DAILY;COUNT=2'
  ),
  'attendees' => array(
    array('email' => 'lpage@example.com'),
    array('email' => 'sbrin@example.com'),
  ),
  'reminders' => array(
    'useDefault' => FALSE,
    'overrides' => array(
      array('method' => 'email', 'minutes' => 24 * 60),
      array('method' => 'popup', 'minutes' => 10),
    ),
  ),
));
$calendarId = 'primary';
$event = $service->events->insert($calendarId, $event);
printf('Event created: %s\n', $event->htmlLink);
Python
# Refer to the Python quickstart on how to setup the environment:
# https://developers.google.com/workspace/calendar/quickstart/python
# Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
# stored credentials.
event = {
  'summary': 'Google I/O 2015',
  'location': '800 Howard St., San Francisco, CA 94103',
  'description': 'A chance to hear more about Google\'s developer products.',
  'start': {
    'dateTime': '2015-05-28T09:00:00-07:00',
    'timeZone': 'America/Los_Angeles',
  },
  'end': {
    'dateTime': '2015-05-28T17:00:00-07:00',
    'timeZone': 'America/Los_Angeles',
  },
  'recurrence': [
    'RRULE:FREQ=DAILY;COUNT=2'
  ],
  'attendees': [
    {'email': 'lpage@example.com'},
    {'email': 'sbrin@example.com'},
  ],
  'reminders': {
    'useDefault': False,
    'overrides': [
      {'method': 'email', 'minutes': 24 * 60},
      {'method': 'popup', 'minutes': 10},
    ],
  },
}
event = service.events().insert(calendarId='primary', body=event).execute()
print 'Event created: %s' % (event.get('htmlLink'))
Ruby
event = Google::Apis::CalendarV3::Event.new(
  summary: 'Google I/O 2015',
  location: '800 Howard St., San Francisco, CA 94103',
  description: 'A chance to hear more about Google\'s developer products.',
  start: Google::Apis::CalendarV3::EventDateTime.new(
    date_time: '2015-05-28T09:00:00-07:00',
    time_zone: 'America/Los_Angeles'
  ),
  end: Google::Apis::CalendarV3::EventDateTime.new(
    date_time: '2015-05-28T17:00:00-07:00',
    time_zone: 'America/Los_Angeles'
  ),
  recurrence: [
    'RRULE:FREQ=DAILY;COUNT=2'
  ],
  attendees: [
    Google::Apis::CalendarV3::EventAttendee.new(
      email: 'lpage@example.com'
    ),
    Google::Apis::CalendarV3::EventAttendee.new(
      email: 'sbrin@example.com'
    )
  ],
  reminders: Google::Apis::CalendarV3::Event::Reminders.new(
    use_default: false,
    overrides: [
      Google::Apis::CalendarV3::EventReminder.new(
        reminder_method: 'email',
        minutes: 24 * 60
      ),
      Google::Apis::CalendarV3::EventReminder.new(
        reminder_method: 'popup',
        minutes: 10
      )
    ]
  )
)
result = client.insert_event('primary', event)
puts "Event created: #{result.html_link}"
向活动添加云端硬盘附件
您可以将 Google 云端硬盘文件(例如 Google 文档中的会议记录、Google 表格中的预算、Google 幻灯片中的演示文稿或任何其他相关的 Google 云端硬盘文件)附加到日历活动中。您可以在使用 events.insert() 创建活动时添加附件,也可以稍后通过更新(例如使用 events.patch())添加附件
将 Google 云端硬盘文件附加到活动的流程分为两部分:
- 从 
Drive API 文件资源中获取文件 alternateLink网址、title和mimeType,通常使用files.get()方法。
- 创建或更新活动,其中请求正文中设置了 attachments字段,且supportsAttachments参数设置为true。
以下代码示例演示了如何更新现有活动以添加附件:
Java
public static void addAttachment(Calendar calendarService, Drive driveService, String calendarId,
    String eventId, String fileId) throws IOException {
  File file = driveService.files().get(fileId).execute();
  Event event = calendarService.events().get(calendarId, eventId).execute();
  List<EventAttachment> attachments = event.getAttachments();
  if (attachments == null) {
    attachments = new ArrayList<EventAttachment>();
  }
  attachments.add(new EventAttachment()
      .setFileUrl(file.getAlternateLink())
      .setMimeType(file.getMimeType())
      .setTitle(file.getTitle()));
  Event changes = new Event()
      .setAttachments(attachments);
  calendarService.events().patch(calendarId, eventId, changes)
      .setSupportsAttachments(true)
      .execute();
}
PHP
function addAttachment($calendarService, $driveService, $calendarId, $eventId, $fileId) {
  $file = $driveService->files->get($fileId);
  $event = $calendarService->events->get($calendarId, $eventId);
  $attachments = $event->attachments;
  $attachments[] = array(
    'fileUrl' => $file->alternateLink,
    'mimeType' => $file->mimeType,
    'title' => $file->title
  );
  $changes = new Google_Service_Calendar_Event(array(
    'attachments' => $attachments
  ));
  $calendarService->events->patch($calendarId, $eventId, $changes, array(
    'supportsAttachments' => TRUE
  ));
}
Python
def add_attachment(calendarService, driveService, calendarId, eventId, fileId):
    file = driveService.files().get(fileId=fileId).execute()
    event = calendarService.events().get(calendarId=calendarId,
                                         eventId=eventId).execute()
    attachments = event.get('attachments', [])
    attachments.append({
        'fileUrl': file['alternateLink'],
        'mimeType': file['mimeType'],
        'title': file['title']
    })
    changes = {
        'attachments': attachments
    }
    calendarService.events().patch(calendarId=calendarId, eventId=eventId,
                                   body=changes,
                                   supportsAttachments=True).execute()
向活动添加视频和电话会议
您可以将活动与 Hangouts 和 Google Meet 会议相关联,以便用户通过电话或视频通话进行远程会议。
conferenceData 字段可用于读取、复制和清除现有会议详细信息;还可用于请求生成新会议。如需允许创建和修改会议详细信息,请将 conferenceDataVersion 请求参数设置为 1。
目前支持三种类型的 conferenceData,如 conferenceData.conferenceSolution.key.type 中所示:
- 面向消费者的 Hangouts (eventHangout)
- 面向 Google Workspace 用户的传统版 Hangouts(已弃用;eventNamedHangout)
- Google Meet (hangoutsMeet)
您可以查看 calendars 和 calendarList 集合中的 conferenceProperties.allowedConferenceSolutionTypes,了解用户的任何给定日历支持哪种会议类型。您还可以通过检查 settings 集合中的 autoAddHangouts 设置,了解用户是否希望为所有新创建的活动创建环聊。
除了 type 之外,conferenceSolution 还提供了 name 和 iconUri 字段,您可以使用这些字段来表示会议解决方案,如下所示:
JavaScript
const solution = event.conferenceData.conferenceSolution;
const content = document.getElementById("content");
const text = document.createTextNode("Join " + solution.name);
const icon = document.createElement("img");
icon.src = solution.iconUri;
content.appendChild(icon);
content.appendChild(text);
您可以提供 createRequest 并使用新生成的 requestId(可以是随机 string)为活动创建新的会议。会议是异步创建的,但您可以随时查看请求的状态,以便让用户了解情况。
例如,如需为现有活动请求生成会议,请执行以下操作:
JavaScript
const eventPatch = {
  conferenceData: {
    createRequest: {requestId: "7qxalsvy0e"}
  }
};
gapi.client.calendar.events.patch({
  calendarId: "primary",
  eventId: "7cbh8rpc10lrc0ckih9tafss99",
  resource: eventPatch,
  sendUpdates: "all",
  conferenceDataVersion: 1
}).execute(function(event) {
  console.log("Conference created for event: %s", event.htmlLink);
});
对该调用的立即响应可能尚未包含完全填充的 conferenceData;这由 status 字段中的状态代码 pending 指示。填充会议信息后,状态代码会更改为 success。entryPoints 字段包含有关哪些视频和电话 URI 可供用户拨入的信息。
如果您想安排多个具有相同会议详细信息的日历活动,可以将一个活动中的整个 conferenceData 复制到另一个活动中。
在某些情况下,复制非常有用。例如,假设您正在开发一个招聘应用,该应用会为候选人和面试官分别设置活动,您希望保护面试官的身份,但同时也希望确保所有参与者加入同一电话会议。