5

正如问题所说,如何找出注册 ID何时在GoogleCloudMessaging API中变得无效?我已经阅读了关于类似主题的几个问题的答案:GCM 注册 ID 是否过期?Google Coud Mesaging (GCM) 和 registration_id 到期,我怎么知道?. 这些问题的问题在于,C2DM旧 GCM API 的答案是使用GCMRegistrar而不是 GoogleCloudMessaging API。前两种方法已贬值。

我将尝试逐步打破我的困惑/问题

1)在标题Enable GCM下,第二点说:

Google may periodically refresh the registration ID, so you should design your Android application with the understanding that the com.google.android.c2dm.intent.REGISTRATION intent may be called multiple times. Your Android application needs to be able to respond accordingly.

The registration ID lasts until the Android application explicitly unregisters itself, or until Google refreshes the registration ID for your Android application. Whenever the application receives a com.google.android.c2dm.intent.REGISTRATION intent with a registration_id extra, it should save the ID for future use, pass it to the 3rd-party server to complete the registration, and keep track of whether the server completed the registration. If the server fails to complete the registration, it should try again or unregister from GCM.

2)现在,如果是这种情况,那么我应该在 BroadcastReceiver 中处理意图并再次发送register()请求以获取新的注册 ID。但问题是在同一页面上的标题 ERROR_MAIN_THREAD下,它说: GCM methods are blocking. You should not run them in the main thread or in broadcast receivers.

3)我还了解注册 ID 更改时还有其他两种情况(如“保持注册状态同步”标题下的高级主题中所述):应用程序更新和备份和恢复。我已经在打开应用程序时处理它们。

4)在 GCMRegistrar API 中,在GCMBaseIntentService内部,曾经有一个回调 onRegistered()方法,该方法在设备注册时被调用。在这里,我曾经保留注册 ID 并发送到 3rd 方服务器。

但是,现在我应该如何处理注册 ID 的更新或更新,将其保存并发送到 3rd 方服务器?

可能是我读完所有内容感到困惑,或者我遗漏了一些东西。我会非常感谢你的帮助。

更新

即使在Android线程上处理Google Cloud Messaging中的注册ID更改,也没有提到如何处理Google定期刷新ID?

4

2 回答 2

4

我正在为我在应用程序中实现的内容提供方法

@Override
protected void onRegistered(Context context, String registrationId) {
     Log.i(TAG, "Device registered: regId = " + registrationId);
     //displayMessage(context, getString(R.string.gcm_registered));
     //ServerUtilities.register(context, registrationId);
     //1. Store this id to application Prefs on each request of device registration
     //2. Clear this id from app prefs on each request of device un-registration  
     //3. Now add an if check for new registartion id to server, you can write a method on server side to check if this reg-id matching for this device or not (and you need an unique identification of device to be stored on server)
     //4. That method will clear that if id is matching it meanse this is existing reg-id, and if not matching this is updated reg-id.
     //5. If this is updated reg-id, update on server and update into application prefs.
}

你也可以这样做

if reg_id exists_into prefrences then
    if stored_id equals_to new_reg_id then
        do nothing
    else
        say server to reg_id updated
        update prefrences with new id
    end if
else
    update this id to application prefs
    say server that your device is registered
end if

但是当用户清除应用程序数据并且您将丢失当前的 reg-id 时,就会出现问题。


更新新 API 示例Credits 转到Eran和 His Answer处理 Android 上 Google Cloud Messaging 中的注册 ID 更改

Google 更改了他们的Demo App以使用新界面。他们通过在应用程序本地保存的值上设置过期日期来刷新注册 ID。当应用程序启动时,它们会加载其本地存储的注册 ID。如果它“过期”(在演示中意味着它是在 7 天前从 GCM 收到的),他们会gcm.register(senderID)再次调用。

这不处理 Google 为长时间未启动的应用程序刷新注册 ID 的假设场景。在这种情况下,应用程序不会知道更改,第三方服务器也不会。

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;
}
于 2013-06-27T06:17:53.133 回答
1

只是为了补充Pankaj的答案:

  • This(the example on getting started documents by Google) doesn't handle the hypothetical scenario in which a registration ID is refreshed by Google for an app that hasn't been launched for a long time. In that case, the app won't be aware of the change, and neither will the 3rd party server.

    确实,入门文档中的示例并未处理这种情况。所以开发者需要自己处理。

  • 答案也说They refresh the registration ID by setting an expiration date on the value persisted locally by the app. When the app starts, they load their locally stored registration id. If it is "expired" they call gcm.register(senderID) again.

    问题是示例中的 7 天本地到期registration ID是为了避免设备将注册发送到 3rd 方服务器但服务器丢失的情况。它不处理从 Google 服务器刷新 ID。

  • 架构概述Enable GCM页面标题下的第二点,它说:

    Note that Google may periodically refresh the registration ID, so you should design your Android application with the understanding that the com.google.android.c2dm.intent.REGISTRATION intent may be called multiple times. Your Android application needs to be able to respond accordingly.

    因此,为了处理这一点,您应该有一个可以处理com.google.android.c2dm.intent.REGISTRATION意图的广播侦听器,当 Google 必须刷新注册 ID 时,它会发送给应用程序。

  • 问题的另一部分说明了有关the problem is that inside the Broadcast Listener I cannot call register the for Push ID again. This is because the 文档的内容: GCM methods are blocking. You should not run them in the main thread or in broadcast receiver.

    我认为这个问题与声明完全不同。当您注册广播接收器时,它将有一个Intent包含registration ID来自 Google 的新接收器。我不需要gcm.register()在广播监听器中再次调用方法。

希望这可以帮助某人了解如何处理注册ID的更新。

于 2013-07-26T23:49:02.543 回答