正如问题所说,如何找出 registration ID 何时执行?已在 GoogleCloudMessaging 中失效应用程序接口(interface)?
我已经阅读了关于类似主题的几个问题的答案:Do GCM registration id's expire?和 Google Coud Mesaging (GCM) and registration_id expiry, how will I know? .这些问题的问题在于,C2DM 或使用 GCMRegistrar 的旧 GCM API 的答案而不是 GoogleCloudMessaging API。前两种方法已被贬值。
我将尝试逐步打破我的困惑/问题:
1) 在 Enable GCM 标题下, 在第二点它说:
Google 可能会定期刷新注册 ID,因此您在设计 Android 应用程序时应了解 com.google.android.c2dm.intent.REGISTRATION Intent 可能会被多次调用。您的 Android 应用程序需要能够做出相应的响应。
注册 ID 一直有效,直到 Android 应用程序明确注销自身,或者直到 Google 为您的 Android 应用程序刷新注册 ID。每当应用程序收到带有 registration_id extra 的 com.google.android.c2dm.intent.REGISTRATION Intent 时,它应该保存 ID 以供将来使用,将其传递给 3rd 方服务器以完成注册,并跟踪是否服务器完成注册。如果服务器未能完成注册,则应重试或从 GCM 中注销。
2) 现在,如果是这种情况,那么我应该在 BroadcastReceiver 中处理 Intent 并发送 register()再次请求以获取新的注册 ID。但问题是在同一页标题下 ERROR_MAIN_THREAD ,它说:
GCM 方法是阻塞的。您不应在主线程或广播接收器中运行它们。
3) 我还了解到当注册 ID 更改时还有其他两种情况(如标题 Keeping the Registration State in Sync 下的高级主题所述): 应用程序更新和备份与恢复。我已经在打开应用程序时处理它们。
4) 在 GCMRegistrar API 中,GCMBaseIntentService 内, 曾经有一个回调 onRegistered()方法,在设备注册时调用。在这里,我曾经保留注册 ID 并发送到 3rd 方服务器。
但是,现在我应该如何处理注册 ID 的更新或续订,持久化并将其发送到 3rd 方服务器?
可能是我读完所有内容后感到困惑,或者我遗漏了什么。非常感谢您的帮助。
更新
即使在 Handling registration ID changes in Google Cloud Messaging on Android线程,没有提到如何处理Google定期刷新ID?
最佳答案
我正在提供一种方法作为我在我的应用程序中实现的方法
@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
但是当用户清除应用程序数据时就会出现问题,您将丢失当前的注册 ID。
Update for new API example Credits goes to Eran and His Answer Handling registration ID changes in Google Cloud Messaging on Android
Google 更改了他们的 Demo App使用新界面。他们通过为应用程序在本地保存的值设置到期日期来刷新注册 ID。当应用程序启动时,他们会加载本地存储的注册 ID。如果它“已过期”(在演示中意味着它是 7 天前从 GCM 收到的),他们会再次调用 gcm.register(senderID)。
这不会处理 Google 为长时间未启动的应用刷新注册 ID 的假设情况。在这种情况下,应用程序不会知道更改,第 3 方服务器也不会。
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;
}
关于java - GoogleCloudMessaging API中注册ID更新或过期如何处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17335572/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg