Google 云消息服务

Google 云消息服务(GCM)是一项用于 Android 设备和 Chrome 应用的服务,可以向服务器发送和接收数据。chrome.gcm API 允许 Chrome 应用或扩展程序以 Chrome 中登录用户的身份访问 GCM 服务。即使应用或扩展程序不在运行时该服务也能正常工作,例如即使日历应用没有打开,日历更新也可以推送至用户。

要使用这一 API 和服务,您必须同意 Google API 服务条款Google Cloud 平台服务条款

该文档描述了设置和使用 GCM 的方法,有关更多信息,请参见 GCM Chrome API 的参考文档和 GCM 服务。要想获取关于 GCM 的帮助或者给我们反馈,请参见反馈

API 示例:想要试试这些代码吗?请参见 gcm-notifications 示例。

启用 GCM

要想在您的应用或扩展程序中使用 GCM,请按照下列步骤操作:

  1. 将您的应用或扩展程序客户端上传至 Chrome 网上应用店
  2. 用户安装了您的应用或扩展程序。
  3. 您的应用或扩展程序客户端使用 gcm.register 函数请求注册标识符,并将该标识符连同用户标识信息一起发送至您的服务器。有关更多详情,请参见获取注册标识符

接收消息

粗略看来,接收消息的方式如下:

  1. 您的应用或扩展程序客户端应该注册处理程序,接收 gcm.onMessage 事件。
  2. 当您的服务器向用户发送消息时,需要指定与用户相关的所有注册标识符,并将消息传递给 GCM 服务。
  3. GCM 服务器将消息转发至运行应用或扩展程序并具有指定注册标识符的所有 Chrome 实例。
  4. 消息到达客户端时,Chrome 浏览器启动应用或扩展程序(如果不在运行的话),并调用注册的处理程序处理消息。

有关更多详情,请参见接收消息

发送消息

粗略看来,发送消息的方式如下:

  1. 您的应用或扩展程序生成一个唯一的消息标识符,这样可以找出哪些消息不能放入队列或传递。
  2. 您的应用或扩展程序调用 gcm.send 函数,传递一个对象,其中包含消息标识符、标志服务器的目标标识符以及由键值对列表组成的数据。在这一步中,您还可以提供可选的消息保留时间。
  3. 传递给 gcm.send 函数的回调函数用来提供结果,您的应用或扩展程序应该检查 runtime.lastError 判断消息是否成功放入队列等待投递。有关可能返回的错误代码,请参见错误参考
  4. 如果放入队列的消息由于 GCM 服务器(如网络错误)而无法投递,则会产生 gcm.onSendError 事件。您的应用或扩展程序可以监听该事件并作出反应,例如尝试再次发送消息。有关可能返回的错误代码,请参见错误参考

有关更多详情,请参见发送消息

以丰富的通知显示消息:
GCM 和丰富的通知 API 是最好的搭档,使用 GCM 发送和接收消息数据,使用丰富的通知在用户的系统托盘中显示数据(请参见随时通知用户)。

设置项目

创建 Google API 项目

  1. 使用您上传应用或扩展程序的同一个 Google 账户登录 Google 开发者控制台
  2. 如果您还没有创建 API 项目,请单击 Create Project(创建项目)。
  3. 输入项目名称并单击 Create(创建)。
  4. 项目创建后,出现的网页中会显示您的项目编号,例如 Project Number: 670330094152
  5. 复制并记下您的项目编号,以后您将使用它作为 GCM 发送方标识符。

启用 GCM 服务

  1. 在左边的侧边栏中选择 APIs & auth(API 与认证)。
  2. 在显示的 API 列表中,将 Google Cloud Messaging for Android 切换至 ON(开启)状态。

设置 Chrome 应用或扩展程序

在清单文件中添加权限

您必须在 manifest.json 中声明 gcm 权限才能使用 GCM 服务。


"permissions": [
  "gcm", "storage", ...
]

请注意,由于下列示例代码需要通过 chrome.storage API 保存一些数据,所以还提供了 storage 权限。

编写 Chrome 应用或扩展程序

获取注册标识符

您的应用或扩展程序接收消息之前,需要与 GCM 服务器注册。应用或扩展程序注册时,获得一个注册标识符。这一步通过 gcm.register 调用实现,同时还需要指定发送方标识符,即 Google 开发者控制台中的项目编号。您的应用或扩展程序应该传递一个回调函数,以便确认注册成功。如果成功的话,获得的注册标识符应该以安全的方式(例如使用 https)发回您的应用程序服务器。否则,您的应用或扩展程序应该处理 chrome.runtime.lastError 中指明的错误并在一段时间后重试。

如果您的应用或扩展程序希望从不同的发送方接收消息,它可以再次调用 gcm.register 并提供新的发送方列表,返回新的注册标识符。


function registerCallback(registrationId) {
  if (chrome.runtime.lastError) {
    // 注册失败时处理错误并在一段时间后重试。
    return;
  }

  // 将注册标识符发送至您的应用程序服务器。
  sendRegistrationId(function(succeed) {
    // 您的服务器接收到注册标识符后,设置标志,
    // 这样下次应用启动时就不会重新注册。
    if (succeed)
      chrome.storage.local.set({registered: true});
  });
}

function sendRegistrationId(callback) {
  // 以安全的方式将注册标识符发送至您的应用程序服务器。
}

chrome.runtime.onStartup.addListener(function() {
  chrome.storage.local.get("registered", function(result) {
    // 如果已经注册则取消操作。
    if (result["registered"])
      return;

    // 最多允许 100 个发送方。
    var senderIds = ["Your-Sender-ID"];
    chrome.gcm.register(senderIds, registerCallback);
  });
});

如果您的应用或扩展程序在不同的配置文件和/或不同的 Chrome 实例中安装,其中的每一个都会获得不同的注册标识符。

您的应用或扩展程序可以调用 gcm.unregister 撤销注册标识符。只有在罕见的情况下才应该撤销注册,例如如果您的应用或扩展程序不希望继续接收消息,或者注册标识符可能遭到攻击。


function unregisterCallback() {
  if (chrome.runtime.lastError) {
    // 取消注册失败时,处理错误并且
    // 过一段时间后重试。
    return;
  }
}

chrome.gcm.unregister(unregisterCallback);

用户卸载您的应用或扩展程序时会自动取消 GCM 服务的注册。

接收消息

当您的服务器向用户发送消息时,它需要指定有关用户的所有注册标识符,并将消息传递给 GCM 服务。GCM 服务器将消息转发至运行应用或扩展程序并具有指定注册标识符的所有 Chrome 实例。如果您的应用或扩展程序在单一 Chrome 实例的不同配置文件中安装,它们都能基于各自唯一的注册标识符独立地接收消息。

来自服务器的消息通过 gcm.onMessage 事件传递,您的应用或扩展程序必须注册处理程序接收该事件。


chrome.gcm.onMessage.addListener(function(message) {
  // 消息是一个对象,由键值对组成。
});

只要 Chrome 浏览器还在运行,即使扩展程序或应用不在运行,它也会被唤醒以便投递消息。

发送消息

要发送消息,您的应用或扩展程序应该调用 gcm.send,并传递一个包含如下信息的对象:

  • 消息标识符,在放入队列或投递失败时标志消息。消息标识符可以是任何字符串,但是建议在您的应用或扩展程序的整个生命周期内确保它的唯一性,即使在重新启动后。如果您使用相同的消息标识符,之前的消息有可能被覆盖。如果使用自增计数器创建消息标识符,您的应用或扩展程序应该使用 chrome.storage API 保存计数器值,并在应用重新载入时恢复它。
  • 目标标识符,标识服务器,即 Google 开发者控制台中的项目编号加上 "@gcm.googleapis.com" 后缀。
  • 由字符串-字符串键值对列表组成(总计不超过 4KB)。
  • 留存时间(TTL,可选)。该属性值必须在 0~2,419,200 秒(4 周)之间,对应于 GCM 存储并尝试投递消息的最长时间。如果没有设置该属性则默认为最大值。如果 TTL 设置为 0,GCM 立即尝试投递消息,如果投递失败则丢弃该消息。

gcm.send 中的回调函数调用时如果没有运行时错误,这并不意味着消息已经投递到 GCM 服务器,而是它已经放入队列等待投递。如果消息无法在指定的 TTL 时间内到达目标,例如由于网络错误,则产生 gcm.onSendError 事件。


// 在此处使用您自己的发送方标识符,即 Google 开发者
// 控制台中获得的项目编号。
var senderId = "Your-Sender-ID";

// 确保消息标识符在您的应用的整个生命周期内唯一。实现
// 这一点的一种方式就是使用自增计数器,并将计数值保存
// 在本地存储中。

// 消息标识符通过本地存储保存和恢复。
var messageId = 0;
chrome.storage.local.get("messageId", function(result) {
  if (chrome.runtime.lastError)
    return;
  messageId = parseInt(result["messageId"]);
  if (isNaN(messageId))
    messageId = 0;
});

// 设置事件监听器,处理发送错误。
chrome.gcm.onSendError.addListener(sendError);

// 返回新的标识符标识消息。
function getMessageId() {
  messageId++;
  chrome.storage.local.set({messageId: messageId});
  return messageId.toString();
}

function sendMessage() {
  var message = {
    messageId: getMessageId(),
    destinationId: senderId + "@gcm.googleapis.com",
    timeToLive: 86400,    // 1 天
    data: {
      "key1": "value1",
      "key2": "value2"
    }
  };
  chrome.gcm.send(message, function(messageId) {
    if (chrome.runtime.lastError) {
      // 发生了一些错误,妥善处理或者再次发送。
      return;
    }

    // 消息已接受,准备投递。如果消息无法到达目标
    // 则产生 onSendError 事件。
  });
}

function sendError(error) {
  console.log("无法发送消息 " + error.messageId +
      ":" + error.errorMessage);
}

消息删除事件

GCM 最多存储 100 条不可折叠的消息,在此之后,所有消息都会被 GCM 丢弃,并产生 gcm.onMessagesDeleted 事件,告诉客户端消息滞后了。您的应用或扩展程序应该响应该事件,并与应用程序服务器同步,恢复丢弃的消息。


chrome.gcm.onMessagesDeleted.addListener(messagesDeleted);

function messagesDeleted() {
  // 所有消息被 GCM 丢弃,与应用程序服务器同步,
  // 从这种情况下恢复正常。
}

可折叠的消息

GCM 消息通常很简单,只是告诉应用或扩展程序从服务器获取新数据。这种情况下可以在 GCM 中创建可折叠的消息,使新消息替代旧消息。当您提供了折叠键后,如果同一用户 的多条消息放入 GCM 服务器队列中,只有包含指定折叠键的最后一条消息才会传递到您的应用或扩展程序。这样传递给 gcm.onMessage 事件的 message 对象包含 collapseKey 字段。有关发送可折叠消息的更多详情,请参见 GCM 高级主题

发布您的应用

要想使用 GCM 服务,您必须在 Chrome 网上应用店中发布您的应用。

错误参考

调用 GCM API 函数时可能会发生错误,您的应用或扩展程序应该在回调函数中检查 runtime.lastError 获取更多信息,错误代码还会作为参数传递给 gcm.onSendError 事件。

如下是 GCM 错误的简要概述:

  • Function was called with invalid parameters(调用函数时传递的参数无效):GCM 函数调用时传递不正确的参数时就会发生该错误。
  • Profile was not signed in(配置文件未登录):GCM 函数在未登录的配置文件中调用时就会发生该错误。
  • Asynchronous operation is pending(异步操作待定):如果之前传递的回调函数还未调用时就再次调用某些 GCM 函数则会发生该错误。
  • Network error occurred(发生网络错误):由于网络问题(例如 Internet 连接断开)无法连接到 GCM 服务器时就会发生该错误。
  • Server error occurred(发生服务器错误):由于服务器问题(例如服务器忙)无法连接到 GCM 服务器时就会发生该错误。
  • Time-to-live exceeded(超过留存期):如果不能在指定的留存期内投递消息就会产生该错误。
  • Unknown error occurred(发生未知错误):任何其他内部错误都可能发生该错误。

反馈

您可以通过 GCM for Chrome Feedback Google 网上论坛提供关于 Google 云消息服务及 chrome.gcm API 的反馈,您可以使用论坛寻求帮助、报告问题、请求特性。