在Google消息传递的文档中,它声明:
Android应用程序应该存储这个ID供以后使用(例如,检查onCreate()是否已经注册)。请注意,Google可能会定期刷新注册ID,因此您应该在设计安卓应用程序时了解com.google.android.c2dm.intent.REGISTRATION意图可能被多次调用。您的Android应用程序需要能够做出相应的响应。
我使用以下代码注册我的设备:
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String regID = gcm.register(senderID);GoogleCloudMessaging类封装注册过程。那么,我应该如何处理com.google.android.c2dm.intent.REGISTRATION,因为它是由GoogleCloudMessaging类在内部完成的?
发布于 2013-05-30 14:51:24
这是个有趣的问题。
Google鼓励您切换到新的注册流程:
运行在移动设备上的Android应用程序通过调用GoogleCloudMessaging方法寄存器(senderID.)注册接收消息。该方法注册GCM的应用程序并返回注册ID,这种简化的方法取代了以前的GCM注册过程。
上面写着Google may periodically refresh the registration ID的注释只出现在仍然显示旧注册过程的页面上,因此该注释可能不再相关。
如果您想要安全,仍然可以使用旧的注册过程。或者您可以使用新的进程,但是还可以使用处理com.google.android.c2dm.intent.REGISTRATION意图的代码,以确保如果Google确实决定刷新注册ID,就会覆盖您。
尽管如此,我从未经历过这样的刷新,即使我确实经历了注册ID的更改(通常是在卸载应用程序然后重新安装它之后发送通知的结果),旧的注册ID仍然有效(结果是在Google的回复中发送了一个规范的注册ID ),所以没有造成任何伤害。
编辑(06.06.2013) :
谷歌改变了他们的演示应用程序来使用新的界面。它们通过设置应用程序在本地保存的值的过期日期来刷新注册ID。当应用程序启动时,他们会加载本地存储的注册id。如果它是“过期的”(在演示中这意味着它是7天前从GCM收到的),他们再次调用gcm.register(senderID)。
这并不能处理假设的情况,即谷歌为一个很长时间没有发布的应用程序刷新注册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;
}编辑(08.14.2013) :
谷歌再次改变了他们的演示应用程序 (两天前)。这一次,他们删除了认为注册ID在7天后过期的逻辑。现在,它们只在安装了新版本的应用程序时刷新注册ID。
编辑(04.24.2014) :
为了完整起见,以下是参与开发GCM的Google开发人员Costin Manolache (摘自这里)关于这个问题的话:
“定期”刷新从未发生,注册刷新不包括在新的GCM库中。 注册ID更改的唯一已知原因是,如果应用程序在升级时收到消息,就会自动取消注册。在修复这个bug之前,应用程序在升级后仍然需要调用注册表(),到目前为止,注册ID在这种情况下可能会改变。调用unregister()通常也会显式地更改注册ID。 建议/解决方法是生成自己的随机标识符,例如,将其保存为共享首选项。在每次应用程序升级时,您都可以上传标识符和潜在的新注册ID。这也有助于跟踪和调试服务器端的升级和注册更改。
这就解释了官方GCM演示应用程序的当前实现。在使用com.google.android.c2dm.intent.REGISTRATION类注册时,不应该处理GoogleCloudMessaging。
发布于 2015-09-11 08:33:58
阅读新的InstanceID API后,我发现了更多关于令牌何时会更改的信息:
您的应用程序可以根据需要使用getToken()方法从实例ID服务请求令牌,与InstanceID一样,应用程序还可以在自己的服务器上存储令牌。颁发给应用程序的所有令牌都属于应用程序的InstanceID。 令牌是唯一和安全的,但是您的应用程序或实例ID服务可能需要在出现安全问题时或者当用户在设备恢复期间卸载和重新安装应用程序时刷新令牌。应用程序必须实现一个侦听器来响应来自实例ID服务的令牌刷新请求。
更多详细信息:
实例ID服务定期发起回调(例如,每6个月一次),请求应用程序刷新其令牌。它还可以在下列情况下启动回调:
资料来源:
https://developers.google.com/instance-id/
https://developers.google.com/instance-id/guides/android-implementation
发布于 2014-09-07 06:37:32
在网上浏览了无数个错误的答案之后,我找到一个完整答案的唯一地方就是埃兰的答案和这里
虽然自动注册刷新可能发生,也可能永远不会发生,但谷歌描述了一种通过解析成功响应来处理canocical_ids的简单算法:
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.从前面提到的链接。
https://stackoverflow.com/questions/16838654
复制相似问题