Android-GCM:如何照顾注销的用户?

Posted

技术标签:

【中文标题】Android-GCM:如何照顾注销的用户?【英文标题】:Android-GCM: How to take care of a logged out user? 【发布时间】:2013-05-31 07:10:16 【问题描述】:

在我的应用中,一旦我注册了一个设备,它就会被存储为持久数据,以便检查设备是否已经注册。

在服务器端,我将它们与 user_id 一起存储在数据库中,user_id 是用户的唯一 ID。

[user_id] [gcm_registration_id]

现在我无法处理这个案子:

如果用户退出:

    必须清除存储在 SharedPreferences 中的registration_id,因为下次启动应用程序时可能会有其他用户登录。

    此外,我必须从我的数据库中删除与该 registration_id 对应的行,因为该设备(当前没有登录用户)不能再收到任何通知。

问题是我的数据库是使用 canonical_ids 更新的,或者说我在调用时得到的最新 registration_ids

https://android.googleapis.com/gcm/send

因此,我有可能找不到要删除的已注销用户的旧registration_id,这仍然允许向未登录用户发送通知。

此外,我无法删除与 user_id 匹配的数据库行,因为用户可能仅从 1 个设备注销,而他/她仍在登录的设备很少。

我如何知道对于这个特定的用户和设备,注册 ID 已更改?

我应该将所有旧的注册 ID 及其对应的 canonical_id 存储在我的数据库中吗?

【问题讨论】:

嘿……你走错了路……当用户注销时,你不应该清除或注销设备。 reg_id 是特定于设备的,而不是特定于用户的。在数据库逻辑中,它必须是所有用户的单一值......就像 one_to_many 关系...... 你应该做的是......你应该跟踪当前登录用户的标志......并将用户标识从服务器发送到消息中。当您从服务器收到消息时,您需要使用标志检查该标识并显示消息。 reg_id is device specific not the user_specific 是的。但是服务器端我会收到一个用户(即user_id)的通知,使用它我将从数据库中获取registration_id并发送通知。 那是真的.. 所以不需要清除 reg_id。请参阅我的第二条评论.. 告诉我这里有什么困惑 如果 user_1 退出并且我没有清除 reg_id,稍后 user_2 会登录并且应用程序会检查 reg_id 是否存在并且不会使用当前/新 reg_id 注册此 user_2。这意味着我不会有 user_2 的数据库条目,他将永远不会收到通知。 【参考方案1】:

你有两个选择:

    按照 cmets 中的建议 - 将注销的用户的注册 ID 保留在您的数据库中,但用一个标志标记它,表明它是注销的用户。您的服务器不会向标记为已注销的注册 ID 发送通知。

    当用户在设备上从您的应用注销时,该设备上的应用将从 GCM 注销并向您的服务器发送注销请求,其中包含用户 ID 和注册 ID。服务器将从数据库中删除该用户 ID/注册 ID 组合。即使由于某种原因您的服务器包含该设备的新注册 ID(导致删除尝试失败),您也无法向具有该注册 ID 的设备发送通知,因为该应用程序已从 GCM 取消注册该设备服务。但是这种情况不太可能发生,因为每当 GCM 更改给定设备上给定应用程序的注册 ID 时,都会将该注册 ID 发送到应用程序,并且应用程序应该发送到您的服务器。只有不这样做可能会导致您的服务器使用旧注册 ID 发送通知并在响应中获取新的规范注册 ID。

【讨论】:

按照您的第一个选项: 我为我的应用注册了一个设备,我得到了一个 reg_id x_id,它作为持久数据存储在设备上。现在一段时间后,reg_id 更改为y_id(canonical_id),只有服务器知道。现在,如果用户注销并且我告诉服务器mark the user_id with reg_id = x_id as logged out,即使这样我最终还是使用y_id 向同一设备发送通知,因为我无法确定x_id 必须被其canonical_id y_id 替换。还是应该将 canonical_id 与通知消息一起发送到我的 android 应用程序? ToUpdatePersistentData? @user1537779 如果 Google 将 reg_id 从 x_id 更改为 y_id,该信息将发送到您的应用程序,这应该会更改存储在设备上的值并将其发送到您的服务器(应该将x_id 替换为y_id)。这就是为什么当用户注销时,您应该能够告诉您的服务器将带有y_id 的user_id 标记为已注销。如果您的 Android 应用程序未能做到这一点,您可以按照您的建议进行操作(将规范 id 发送到您的应用程序以更新其持久数据),但这只能作为一种故障安全措施,因为它不应该如果您正确处理 reg-id 更改,就会发生这种情况。 that info is sent to your app 你能告诉我如何以及何时将其发送到应用程序。到目前为止,我认为只有我的服务器可以跟踪而不是通过接收 canonical_id。 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。您的应用应处理该意图,其中包含新的注册 ID。如果您在服务器中收到一个 canoncial_id 作为 GCM 服务器的响应,这意味着您的应用未能将新的注册 ID 传送到您的服务器。 这里有点晚了,但您应该在处理com.google.android.c2dm.intent.RECEIVE 的同一个BroadcastReceiver 中更新您的注册ID。例如,if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) mPrefs.edit().putString(Constants.Preferences.DEVICE_ID, intent.getStringExtra("registration_id")).apply(); else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) sendPushNotification(intent); 【参考方案2】:

private String android_id = Secure.getString(getContext().getContentResolver(),Secure.ANDROID_ID); 此行将为任何设备返回一个唯一的 android_id (thx) 对于任何用户,您可以存储设备数组,在记录时从客户端发送消息或每隔几分钟检查一次。 希望

【讨论】:

小心,使用 ANDROID_ID 并非 100% 安全。

以上是关于Android-GCM:如何照顾注销的用户?的主要内容,如果未能解决你的问题,请参考以下文章

语言 logout and redirect啥意思

Laravel 5 - 从他的所有设备中注销用户

当用户注销其中一个标签时,如何自动从所有打开的标签中注销用户?

如何更正 Shiro 注销代码(执行注销后用户仍然可以访问页面)?

当用户直接关闭浏览器时如何跟踪注销活动

如何在php中检测用户是不是已注销?