【问题标题】:Google push notifications java handler谷歌推送通知 java 处理程序
【发布时间】:2017-03-11 18:21:42
【问题描述】:

我已订阅我的应用以收听 Google 推送通知。频道详细信息已保留。我可以从 google 接收通知到我的端点。

@PostMapping("/google/calendars/")
public void watch(HttpServletRequest request,
  @RequestHeader(value = "X-Goog-Channel-ID", required = false) String googleChannelId,
  @RequestHeader(value = "X-Goog-Channel-Token", required = false) String googleChannelToken,
  @RequestHeader(value = "X-Goog-Channel-Expiration", required = false) String googleChannelExpiration,
  @RequestHeader(value = "X-Goog-Resource-ID", required = false) String googleResourceId,
  @RequestHeader(value = "X-Goog-Resource-URI", required = false) String googleResourceUri,
  @RequestHeader(value = "X-Goog-Resource-State", required = false) String googleResourceState,
  @RequestHeader(value = "X-Goog-Message-Number", required = false) String googleMessageNumber,

使用收到的信息我可以打开client 到谷歌服务。但我不知道如何更改。

googleChannelId=354a78aa-0cc0-4b5b-96c5-e54e03a51e68
googleChannelToken=<null>
googleChannelExpiration=Sat, 18 Mar 2017 17:01:56 GMT
googleResourceId=eVHbdUeaWhfQPpvJPU7VZRxYzUs
googleResourceUri=https://www.googleapis.com/calendar/v3/calendars/sergii_vlasiuk@ukr.net/events?maxResults=250&alt=json
googleResourceState=exists
googleMessageNumber=403802722

exists 表示 googleResourceId 已更改。

使用googleChannelId 加载我的频道详细信息并打开客户端。


  1. 如何在我的拉取更改请求中使用googleResourceId(可能是请求示例)?
  2. 理解是否正确: not_exists 表示资源被删除; exists 表示资源已创建或编辑?

添加详细信息

我试过了

client.events().get(originalCalendarId, googleResourceId).execute()

地点:

  1. client 是具有正确标记的 com.google.api.services.calendar.Calendar 对象。
  2. ginalCalendarId - 众所周知的谷歌日历 ID,用于订阅。
  3. googleResourceId - 来自标头消息X-Goog-Resource-ID 值。 ->

    404 未找到 { “代码”:404, “错误”:[{ “域”:“全球”, “未找到信息”, “原因”:“未找到” }], “未找到信息” }

【问题讨论】:

  • "X-Goog-Resource-State" 可以有声明的值:sync, exists
  • 也许我应该使用etag 来映射更改数据的通知,或者谷歌为X-Goog-Message-Number 提供API?

标签: java push-notification google-api google-calendar-api google-api-java-client


【解决方案1】:

如果 Google 没有方便的方法来区分哪些实体已被更新,我想我们应该考虑一种解决方法。在我看来,通过遍历和重写所有数据来获取所有事件并更新数据库状态会导致一些性能问题。

为了解决这个问题,我会选择使用每个事件所具有的 "etag" 值。每次更新事件时,ETag 都会更改(在 CalDav 协议中工作)

http://cdn.nsoftware.com/help/IP9/cs/CalDAV_p_ETag.htm

如果您将 etag 与您的事件一起保存到数据库中,那么一旦您从 Google 获得事件列表,您就可以检查 etag 值并仅更新真正更改的元素。当您更新条目时,必须优化该部分。

Google 支持 etag。 你可以在这里找到它:

https://developers.google.com/google-apps/calendar/v3/reference/events/list

{
  "kind": "calendar#events",
  "etag": etag,
  "summary": string,
  "description": string,
  "updated": datetime,
  "timeZone": string,
  "accessRole": string,
  "defaultReminders": [
    {
      "method": string,
      "minutes": integer
    }
  ],
  "nextPageToken": string,
  "nextSyncToken": string,
  "items": [
    events Resource
  ]
}

更新:

有一种更方便的方式来执行同步。 您可以使用增量同步方法。增量同步允许您检索自上次同步请求以来已修改的所有资源。

https://developers.google.com/google-apps/calendar/v3/sync#initial_full_sync

您只需要在每次更新数据时保存同步令牌并在请求中使用它来获取新数据。在这种情况下,您将仅获得已修改的数据。

Calendar.Events.List request = client.events().list("primary");
request.setSyncToken(syncToken);

如果你打电话那么:

events = request.execute();
List<Event> items = events.getItems();

您将只获得更新的数据。

【讨论】:

    【解决方案2】:

    但我不知道如何更改。

    Google 日历 API 提供推送通知,让您可以监视资源的更改。您可以使用此功能来提高应用程序的性能。它允许您消除轮询资源所涉及的额外网络和计算成本,以确定它们是否已更改。每当监视的资源发生变化时,Google Calendar API 都会通知您的应用程序

    一旦您正确设置了手表,您的应用程序将在发生更改时收到通知。你不需要检查它。

    示例

    POST https://www.googleapis.com/calendar/v3/calendars/my_calendar@gmail.com/events/watch
    Authorization: Bearer auth_token_for_current_user
    Content-Type: application/json
    
    {
      "id": "01234567-89ab-cdef-0123456789ab", // Your channel ID.
      "type": "web_hook",
      "address": "https://example.com/notifications", // Your receiving URL.
      ...
      "token": "target=myApp-myCalendarChannelDest", // (Optional) Your channel token.
      "expiration": 1426325213000 // (Optional) Your requested channel expiration time.
      }
    }
    

    有一篇完整的文章介绍了如何设置文档Push Notifications

    注意:

    此语句不起作用,因为 Events.get 需要 event Id 作为其第二个参数,而不是您的 GoogleResourceId

     client.events().get(originalCalendarId, googleResourceId).execute()
    

    手表的工作原理:

    1. 您决定要监视用户事件的变化。您创建一个watch on the events。 Google 会向您返回用于识别手表的 resourceId。
    2. 进行了更改,Google 以 HTTP 帖子的形式向您发送了 notification。它包含您手表中的资源 ID。
    3. 您知道具有此资源 ID 的手表被用户事件喜欢。您使用刷新令牌来访问用户帐户。您执行events list 并扫描每个事件以查找哪些事件发生了变化。

    资源 ID 不能用于请求事件。手表不会告诉您更改的具体内容或时间。您必须查询 API 才能找到答案。

    【讨论】:

    • @dimto,我已经使用了这个文档,并且我在接收推送通知方面没有问题(请参阅我的示例)。为了给你提供一个例子,我改变了我的谷歌事件,得到了一个带有 resourceId 的通知答案(没有事件信息)。我知道我使用了错误的 API 来获取更改,但在 google api 中没有对此案例的更多解释,这就是我提出问题的原因。现在我需要知道如何使用资源 ID 来获取谷歌日历更改(我有 channelId,我有 calendarId)!
    • 我想我不明白你的问题。你没有得到改变。更改将按您提供的地址发送给您。您无需轮询服务器进行更改。
    • 好的,建议你是对的(我非常需要它)!我发布的信息 - 如果我更改了谷歌日历活动时间,我会收到。此信息不包含有关更改时间的信息,我在这里也没有看到任何指向该事件的链接。 我可能错过了什么吗?可能我不仅要听标题信息吗?可能我应该再尝试一个请求来获得更改? 如果你已经完成了,那么你应该知道我错过了什么。
    • 试试这个更新 谷歌只告诉你一些事情已经改变了,你可以通过你创建的手表类型来确定你应该知道什么,然后能够运行正确的查询在正确的用户身上找出发生了什么变化。
    • 我的频道收听日历。如果我收到推送通知,我可以将通知映射到我的频道信息,我可以为正确的用户构建谷歌客户端。但是我很困惑是否必须在每个通知捕获时间从谷歌加载所有事件。我希望能够仅针对已更改的元素进行更改(在我的情况下为事件)。如果我正确理解您的提议与我的ugly answer 相同
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 2015-03-08
    • 1970-01-01
    • 2012-04-25
    相关资源
    最近更新 更多