Android GCM和多个令牌
我使用GoogleCloudMessaging.getInstance(上下文)在GCM中注册;并将收到的令牌保存在设备上。然后将其发送到服务器,并将其与用户帐户关联。如果我卸载我的应用程序而不注销,然后再次安装并与其他用户登录,我将收到新令牌并将其发送到服务器。当推送被发送给第一个用户时,我会在和第二个用户登录时看到它们Android GCM和多个令牌,android,push-notification,google-cloud-messaging,Android,Push Notification,Google Cloud Messaging,我使用GoogleCloudMessaging.getInstance(上下文)在GCM中注册;并将收到的令牌保存在设备上。然后将其发送到服务器,并将其与用户帐户关联。如果我卸载我的应用程序而不注销,然后再次安装并与其他用户登录,我将收到新令牌并将其发送到服务器。当推送被发送给第一个用户时,我会在和第二个用户登录时看到它们 为什么GCM会向我发送不同的令牌,我如何处理这些令牌?欢迎来到谷歌云消息的重复消息的奇妙世界。发生这种情况时,GCM引擎将启用规范ID来解决此问题。这可能是因为您为同一设备注
为什么GCM会向我发送不同的令牌,我如何处理这些令牌?欢迎来到谷歌云消息的重复消息的奇妙世界。发生这种情况时,
GCM
引擎将启用规范ID
来解决此问题。这可能是因为您为同一设备注册了多个ID,或者是因为卸载应用程序时,GCM
服务器未获得unregister()
调用。使用规范ID会将您的ID设置为您进行的最后一次注册
根据《GCM参考资料》,关于这一点:
规范ID
在服务器端,只要应用程序运行良好,一切都应该正常工作。然而,如果应用程序中的一个bug触发了同一设备的多个注册,则很难协调状态,最终可能会出现重复消息
GCM提供了一种称为“规范注册ID”的工具,可以轻松地从这些情况中恢复。规范注册ID定义为应用程序请求的最后一次注册的ID。这是服务器向设备发送消息时应使用的ID
如果稍后您尝试使用不同的注册ID发送消息,GCM将一如既往地处理该请求,但它将在响应的注册ID字段中包含规范注册ID。请确保使用此规范ID替换存储在服务器中的注册ID,因为您使用的ID最终将停止工作
更多信息
此外,还有一个关于如何处理的实际案例,可能会有所帮助:
未注册
错误),然后再次安装
谷歌的Costin Manolache以这种方式处理注册ID变更:
建议/解决方法是生成您自己的随机标识符,例如保存为共享首选项。在每次应用程序升级中,您可以上载标识符和可能的新注册ID。这也可能有助于跟踪和调试服务器端的升级和注册更改
当然,这仅在应用程序保持安装状态时有效(因为共享首选项会随应用程序一起删除)。但是,如果设备具有外部存储器,则可以将您的标识符存储在该存储器中,并且在再次安装应用程序时,从外部存储器加载存储的标识符。这样,您将知道新注册ID和旧注册ID属于同一设备
此外,如另一个答案中所述,您应该在服务器中处理来自谷歌的规范注册ID响应。您可以将Android设备ID与注册ID一起发送。Android设备ID是唯一的,在应用程序卸载重新安装期间保持不变,只有在设备出厂重置时才会更改
示例:向多个设备发送推送通知与向单个设备发送推送通知相同。 只需将所有已注册设备的注册令牌存储到服务器。 当使用curl调用push通知时(我假设您使用php作为服务器端),将所有注册id放入一个数组中。 这是一个示例代码
<?php
//Define your GCM server key here
define('API_ACCESS_KEY', 'your server api key');
//Function to send push notification to all
function sendToAll($message)
{
$db = new DbOperation();
$tokens = $db->getAllToken();
$regTokens = array();
while($row = $tokens->fetch_assoc()){
array_push($regTokens,$row['token']);
}
sendNotification($regTokens,$message);
}
//function to send push notification to an individual
function sendToOne($email,$message){
$db = new DbOperation();
$token = $db->getIndividualToken($email);
sendNotification(array($token),$message);
}
//This function will actually send the notification
function sendNotification($registrationIds, $message)
{
$msg = array
(
'message' => $message,
'title' => 'Android Push Notification using Google Cloud Messaging',
'subtitle' => 'www.simplifiedcoding.net',
'tickerText' => 'Ticker text here...Ticker text here...Ticker text here',
'vibrate' => 1,
'sound' => 1,
'largeIcon' => 'large_icon',
'smallIcon' => 'small_icon'
);
$fields = array
(
'registration_ids' => $registrationIds,
'data' => $msg
);
$headers = array
(
'Authorization: key=' . API_ACCESS_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://android.googleapis.com/gcm/send');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
curl_close($ch);
$res = json_decode($result);
$flag = $res->success;
if($flag >= 1){
header('Location: index.php?success');
}else{
header('Location: index.php?failure');
}
}
发送通知时,首先发送用户id,并询问SharedReference==comming
中的id或否
如果您向所有用户发送通知,可能有人会收到2个通知,而他应该只收到一个
在您的服务器上创建一个文件,使用任何数字,比如0,然后当您要发送通知时,使用它发送此numebr,然后将一个添加到此数字++
下一次通知中的新编号与每个新编号相同
在android应用程序中,添加变量,并让此变量=添加通知后来自服务器的提交变量
但您需要询问是否(您服务中的号码!=服务器号码)
//添加通知
您发送的任何数量的通知(仅一个)都将出现
public class GcmIntentService extends IntentService {
public static int openintent;
public static final int NOTIFICATION_ID = 1;
private static final String TAG = "GcmIntentService";
private static String number_in_your_service="somethingneversend";
NotificationCompat.Builder builder;
public GcmIntentService() {
super("GcmIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// This loop represents the service doing some work.
for (int i = 0; i < 5; i++) {
Log.i(TAG, "Working... " + (i + 1) + "/5 @ " + SystemClock.elapsedRealtime());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
// Post notification of received message.
sendNotification(extras);
Log.i(TAG, "Received: " + extras.toString());
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(Bundle extras) {
if((extras.getString("server_number")).equals(number_in_your_service)) {
Intent intent = new Intent(this, Main_Page_G.class);
intent.putExtra("frame",100);
intent.putExtra("bundle",extras);
final PendingIntent contentIntent = PendingIntent.getActivity(this,
120, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager mNotificationManager;
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
GcmIntentService.this).setContentTitle("name")
.setContentText("content")
.setDefaults(Notification.DEFAULT_SOUND)
.setContentInfo("Test")
.setSmallIcon(R.drawable.rehablogo2)
.setAutoCancel(true);
mBuilder.setContentIntent(contentIntent);
mNotificationManager = (NotificationManager) GcmIntentService.this
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, mBuilder.build());
id=Integer.parseInt(extras.getString("id"));
}
}
}
公共类gcminentservice扩展了IntentService{
公共静态开放意图;
公共静态最终整数通知_ID=1;
私有静态最终字符串TAG=“gcminentservice”;
您的\u服务中的私有静态字符串编号\u=“somethingneversend”;
通知建筑商;
公共GCMinentService(){
超级(“GCMinentService”);
}
@凌驾
受保护的手部内容无效(意图){
Bundle extras=intent.getExtras();
GoogleCloudMessaging gcm=GoogleCloudMessaging.getInstance(this);
字符串messageType=gcm.getMessageType(intent);
如果(!extras.isEmpty()){//具有解包的效果
if(GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)){
}else if(GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)){
//如果是常规GCM消息,请执行一些操作。
}else if(GoogleCloudMessaging.MESSAGE\u TYPE\u MESSAGE.equals(messageType)){
//此循环表示正在执行某些工作的服务。
对于(int i=0;i<5;i++){
Log.i(标记“Working…”+(i+1)+“/5@”+SystemClock.elapsedRealtime());
试一试{
睡眠(100);
}捕捉(中断异常e){
}
}
Log.i(标记“Completed work@”+SystemClock.elapsedRealtime());
//接收到消息的Post通知。
发送通知(临时通知);
Log.i(标记“Received:+extras.toString());