当前位置: 首页 > 知识库问答 >
问题:

在Android上处理Google Cloud消息传递中的注册ID更改

屠振濂
2023-03-14

在谷歌云消息的文档中,它指出:

Android应用程序应该存储此ID以供以后使用(例如,如果已注册,请检查oncreate())。请注意,Google可能会定期刷新注册ID,因此您应该在设计Android应用程序时了解com.google.android.c2dm.intent.注册意图可能会被多次调用。您的Android应用程序需要能够相应地响应。

我使用以下代码注册我的设备:

GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String regID = gcm.register(senderID);

GoogleCloudMessaging类封装了注册过程。那么我该如何处理com呢。谷歌。Androidc2dm。意图注册,因为处理是由GoogleCloudMessaging类内部完成的?

共有3个答案

伏业
2023-03-14

在网上浏览了数吨误导性的答案后,包括SO,我唯一找到完整答案的地方是埃兰的答案,这里:

虽然自动注册刷新可能发生,也可能永远不会发生,但google描述了一种通过解析成功响应来处理canocical_ID的类似算法:

If the value of failure and canonical_ids is 0, it's not necessary to parse the remainder of the response. Otherwise, we recommend that you iterate through the results field and do the following for each object in that list:

If message_id is set, check for registration_id:
If registration_id is set, replace the original ID with the new value (canonical ID) in your server database. Note that the original ID is not part of the result, so you need to obtain it from the list of code>registration_ids passed in the request (using the same index).
Otherwise, get the value of error:
If it is Unavailable, you could retry to send it in another request.
If it is NotRegistered, you should remove the registration ID from your server database because the application was uninstalled from the device or it does not have a broadcast receiver configured to receive com.google.android.c2dm.intent.RECEIVE intents.
Otherwise, there is something wrong in the registration ID passed in the request; it is probably a non-recoverable error that will also require removing the registration from the server database. See Interpreting an error response for all possible error values.

来自上述链接。

巢安澜
2023-03-14

在阅读新的InstanceID API时,我发现了有关令牌何时可能更改的更多信息:

您的应用程序可以根据需要使用getToken()方法从实例ID服务请求令牌,并且与InstanceID一样,您的应用程序也可以在您自己的服务器上存储令牌。向应用程序颁发的所有令牌都属于应用程序的InstanceID。

令牌是唯一且安全的,但如果出现安全问题,或者在设备恢复期间用户卸载并重新安装应用时,您的应用或实例ID服务可能需要刷新令牌。您的应用程序必须实现侦听器,以响应来自实例ID服务的令牌刷新请求。

更多详情:

实例ID服务定期(例如,每6个月)发起回调,请求应用刷新其令牌。它还可以在以下情况下启动回调:

  • 存在安全问题;例如,SSL或平台问题。
  • 设备信息不再有效;例如,备份和恢复。
  • 实例ID服务会受到其他影响。

来源:

https://developers.google.com/instance-id/

https://developers.google.com/instance-id/guides/android-implementation

萧献
2023-03-14

这是一个有趣的问题。

谷歌鼓励您切换到新的注册流程:

在移动设备上运行的Android应用程序通过调用GoogleCloudMessaging方法register(senderID…)注册接收消息。此方法为GCM注册应用程序并返回注册ID。此简化方法取代以前的GCM注册过程

上面写着Google可能会定期刷新注册ID的注释只出现在仍然显示旧注册过程的页面上,因此该注释可能不再相关。

如果你想安全,你仍然可以使用旧的注册流程。或者您可以使用新流程,但除此之外,您还可以使用处理注册意图com.google.android.c2dm.intent.代码,以确保如果Google决定刷新注册ID,您将被覆盖。

也就是说,我从未经历过这样的刷新,即使我经历了注册ID的更改(通常是在卸载应用程序并重新安装后发送通知的结果),旧的注册ID仍然有效(导致规范的注册ID从谷歌发送的响应),所以没有造成伤害。

编辑(06.06.2013):

谷歌改变了他们的演示应用程序以使用新的界面。他们通过设置应用程序在本地保留的值的过期日期来刷新注册ID。当应用程序启动时,他们加载本地存储的注册id。如果注册id“过期”(在演示中表示它是7天前从GCM收到的),他们会调用GCM。再次注册(senderID)

这并不能处理假设的场景,即谷歌为一个很长时间没有推出的应用程序刷新注册标识。在这种情况下,应用程序不会知道更改,第三方服务器也不会。

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);
    mDisplay = (TextView) findViewById(R.id.display);

    context = getApplicationContext();
    regid = getRegistrationId(context);

    if (regid.length() == 0) {
        registerBackground();
    }
    gcm = GoogleCloudMessaging.getInstance(this);
}

/**
 * Gets the current registration id for application on GCM service.
 * <p>
 * If result is empty, the registration has failed.
 *
 * @return registration id, or empty string if the registration is not
 *         complete.
 */
private String getRegistrationId(Context context) {
    final SharedPreferences prefs = getGCMPreferences(context);
    String registrationId = prefs.getString(PROPERTY_REG_ID, "");
    if (registrationId.length() == 0) {
        Log.v(TAG, "Registration not found.");
        return "";
    }
    // check if app was updated; if so, it must clear registration id to
    // avoid a race condition if GCM sends a message
    int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
    int currentVersion = getAppVersion(context);
    if (registeredVersion != currentVersion || isRegistrationExpired()) {
        Log.v(TAG, "App version changed or registration expired.");
        return "";
    }
    return registrationId;
}

/**
 * Checks if the registration has expired.
 *
 * <p>To avoid the scenario where the device sends the registration to the
 * server but the server loses it, the app developer may choose to re-register
 * after REGISTRATION_EXPIRY_TIME_MS.
 *
 * @return true if the registration has expired.
 */
private boolean isRegistrationExpired() {
    final SharedPreferences prefs = getGCMPreferences(context);
    // checks if the information is not stale
    long expirationTime =
            prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1);
    return System.currentTimeMillis() > expirationTime;
}

编辑(08.14.2013):

谷歌再次更改了他们的演示应用程序(两天前)。这一次,他们删除了认为注册ID在7天后过期的逻辑。现在,他们只在安装了新版本的应用程序时刷新注册ID。

编辑(2014年4月24日):

为了完整起见,以下是参与GCM开发的谷歌开发人员Costin Manolache(摘自此处)就此事所说的话:

'定期'刷新从未发生,并且注册刷新不包括在新的GCM库中。

注册ID更改的唯一已知原因是旧的bug,即如果应用程序在升级时收到消息,就会自动取消注册。在修复此错误之前,升级后的应用程序仍然需要调用register(),到目前为止,在这种情况下,注册ID可能会更改。显式调用unregister()通常也会更改注册ID。

建议/解决方法是生成您自己的随机标识符,例如保存为共享首选项。在每次应用升级时,您都可以上传标识符和潜在的新注册ID。这也可能有助于跟踪和调试服务器端的升级和注册更改。

这解释了官方GCM Demo应用程序的当前实现。当使用GoogleCloudMessage类进行注册时,永远不应该处理com.google.android.c2dm.intent.REGISTRATION。

 类似资料:
  • 问题内容: 在Google Cloud Messaging的文档中,它指出: Android应用程序应存储此ID供以后使用(例如,检查onCreate()是否已注册)。请注意,Google可能会定期刷新注册ID,因此您在设计android应用程序时应了解com.google.android.c2dm.intent.REGISTRATION意图可能会多次调用。您的Android应用程序需要能够做出相

  • 当用户退出我的应用程序并且我不再希望他接收到设备通知时,我如何处理这种情况。 我试过了 但我仍然会收到设备注册id的通知。 我还确保这是我应该删除的令牌: 或者干脆)。 我还尝试了,但下一次调用时,我收到空值(在第二次尝试时有效)。 我想,在之后,我可以立即再次调用,但这看起来像是一个黑客。还有一个答案是不应该这样做,但它建议删除显然不起作用的令牌。 那么,正确的处理方法是什么呢?

  • 我想知道如何将应用程序/设备通知,如果GCM服务器决定刷新之前从GCM服务器检索的应用程序的注册ID。目前,我保存第一个检索到的注册ID,并将其保存在数据库中,并将此注册ID发送到应用服务器。所以,从下一次应用程序将不会说话的GCM服务器。在这种情况下,应用程序永远不会知道注册ID是否被GCM服务器更改。谷歌文件提出了一些处理此案的建议,但没有提到应该采取什么步骤。引用谷歌- 虽然是com。谷歌。

  • 好的,事情是这样的,我已经在Stackoverflow中问了几个与firebase相关的问题,即使没有任何答案,我还是设法让firebase工作,并收到了一系列通知。我真的不知道我做了什么使它工作,这是一个结合了很多东西。 (之前发布的相关问题:如何使用webpack将Firebase云消息传送到ReactJS项目中|ReactJS和Webpack不工作的Firebase FCM:我们无法注册默认

  • 我正在使用JavaMail应用编程接口来获取一些电子邮件。我想得到一个消息流,然后在另一边得到一个电子邮件流。此外,我不想失去任何属性,如附件、目的地、发送者、正文等... 如何才能做到这一点?

  • 我使用新的GCM API来注册。方法的留档明确指出: 为GCM注册应用程序并返回注册ID。安装应用程序后,必须调用此函数一次,然后将返回的注册ID发送到服务器。 重复调用此方法将返回原始注册ID。 然而,在阅读本文时(http://developer.android.com/google/gcm/adv.html#reg-州),它指出有两种情况需要特殊处理: 另外还有两种情况需要特别注意: 应用程