我有PHP服務器端和Android客戶端應用程序的系統。 Android通過webservice發送參數,PHP處理GCM端。 PHP發送推送通知,在發送之前,它從DB獲取所有registrationid。問題是,相同的設備可能有兩個或更多的註冊ID。因此,推送通知發送到同一設備兩次或更多次。有沒有解決方案來解決這個問題?Android GCM一個設備有多個註冊ID
回答
您只需在數據庫中存儲每個設備的uniq標識。然後,您可以爲每個設備發送一個推送通知。
我從來沒有看到同一設備的多個註冊ID。奇怪的事情。
您是否正確管理註冊ID更新?
我認爲你的問題是你如何從設備獲得註冊ID。 您必須確保它發送一次REGID,並且GCM服務器請求刷新時,您必須將REGID重新發送到您的網絡服務器並存儲它,覆蓋舊的redID。 請參閱this部分android參考。
謝謝所有,但主要問題並不是要更新。在scenerio用戶可能有許多Android設備。由於這3個設備可能有7個註冊ID。我想發送3條推送消息,但GCM將發送7個。 – iravul
我不明白我的迴應...對於每個設備,Google GCM服務器都希望定期刷新ID ...檢查android api文檔...錯誤在一開始:每個設備必須在一次只有一個REGID。 – trullallero
GCM可以更改registrationId,並且您必須在服務器端更新它。
- 當您發送消息時,結果可能包含將用於設備的新registrationId,因此您必須更新舊的registrationId。
看看這個link at Interpreting a success response section
如果MESSAGE_ID設置,檢查registration_id:如果registration_id設置,在您的服務器數據庫中的新值(規範ID)取代原來的ID。請注意,原始ID不是結果的一部分,因此您需要從請求中傳遞的registration_ids列表中獲取它(使用相同的索引)。
謝謝大家,但主要問題並不是要更新。在scenerio用戶可能有許多Android設備。由於這3個設備可能有7個註冊ID。我想發送3條推送消息,但GCM將發送7條。 – iravul
通過GCM服務,一個registrationId可識別設備/應用,因此如果用戶使用GCM將3個設備連接到服務器,則應該有3個註冊ID。在'GCMRegistrar.register'之前檢查,如果您的regId仍然存儲在'GCMRegistrar.getRegistrationId'中,那麼您生成的是超過需要的。 – AlexBcn
壞主意,因爲:(terminal1)gcm(aaa)登錄user1和user2,如果您更改(terminal1)gcm(bbb),如果您發送GCM檢查終端(bbb)並且user2或user1未收到此通知。誤解! – delive
有時Google會更改註冊ID,並且您將擁有多個關聯的ID。發送通知的服務器(您的服務器)必須使用新ID更新數據庫。
欲瞭解更多信息查看本文檔:
http://developer.android.com/google/gcm/adv.html
他們說:
這是一個典型的ID
在服務器端,只要應用程序表現很好,一切應該正常工作。但是,如果應用程序中的某個錯誤會觸發同一設備的多個註冊,則可能很難調和狀態,並且最終可能會出現重複的消息。
GCM提供了一種稱爲「規範註冊ID」的功能,可以輕鬆從這些情況中恢復。規範註冊ID被定義爲您的應用程序請求的最後一次註冊的ID。這是服務器在向設備發送消息時應使用的ID。
如果稍後嘗試使用不同的登記ID來發送消息,GCM將處理該請求如常,但將包括在該響應的registration_id字段規範註冊ID。請確保使用此規範ID替換存儲在您的服務器中的註冊ID,因爲您最終使用的ID將停止工作。
我面臨與同一設備上的兩個不同註冊ID的問題,但0 canonical_ids返回.. – neobie
你會在你的推響應得到規範標識。您需要用新的規範ID更新您的舊ID。
還有一個解決方案。更像是一個補丁。您可以在GCM請求JSON中傳遞參數'dry_run'。當我們將其設置爲true時,它會向設備ID發送假消息並生成響應。
設備不會得到一個消息,但你會得到您的回覆,因此你可以檢查哪些設備ID具有registration_ids在他們的結果,並從數據庫中刪除它們。
$fields = array(
'registration_ids' => $deviceId,
'data' => array("message" =>'fake_message'),
'dry_run'=>true
);
希望它有幫助。
這裏是我的解決這個問題。 當您發送GCM通知你得到這樣
Array
(
[multicast_id] => 12345678910
[success] => 8
[failure] => 3
[canonical_ids] => 4
[results] => Array
(
[0] => Array
(
[error] => NotRegistered
)
[1] => Array
(
[message_id] => 0:1412242641156904%3dc89e2df9fd7ecd
)
[2] => Array
(
[registration_id] => APA91bH3WdWwqFCVKbvZXsf-gj28iWU5oYbSCRZYFp987CHasxwT_HOiE7dp8212XID0FMGVG2n4NLohFsEGYJ-LEA07xsgsKfT00xModQcx5QgTBmJtxlWgeaWFpz29z-iCPYbvOHEhqfwHmN-HIps7DiWntcs-Qg
[message_id] => 0:1412242641155639%3dc89e2df9fd7ecd
)
[3] => Array
(
[registration_id] => APA91bH3WdWwqFCVKbvZXsf-gj28iWU5oYbSCRZYFp987CHasxwT_HOiE7dp8212XID0FMGVG2n4NLohFsEGYJ-LEA07xsgsKfT00xModQcx5QgTBmJtxlWgeaWFpz29z-iCPYbvOHEhqfwHmN-HIps7DiWntcs-Qg
[message_id] => 0:1412242641155809%3dc89e2df9fd7ecd
)
[4] => Array
(
[message_id] => 0:1412242641157971%3dc89e2df9fd7ecd
)
[5] => Array
(
[registration_id] => APA91bGXo_gnfBZsvPoqJTYy1BWz0FQIkwlD1EmBtcxgWWfceYvd0ehWqVCtfd8n56VGYrvXCS2v48kTiA69BD7Sci0BA9a9bKTIg_MUEnDd79ssCK-miPG88DDGL4oKtB14cPbh-_xbgVRZllMOzwNZf_w5uJGR8g
[message_id] => 0:1412242641157969%3dc89e2df9fd7ecd
)
[6] => Array
(
[registration_id] => APA91bGXo_gnfBZsvPoqJTYy1BWz0FQIkwlD1EmBtcxgWWfceYvd0ehWqVCtfd8n56VGYrvXCS2v48kTiA69BD7Sci0BA9a9bKTIg_MUEnDd79ssCK-miPG88DDGL4oKtB14cPbh-_xbgVRZllMOzwNZf_w5uJGR8g
[message_id] => 0:1412242641157967%3dc89e2df9fd7ecd
)
)
)
陣列中
的響應有一個索引canonical_ids
是4,這意味着u有4個用戶都產生了新的GCM IDS,現在你需要做的是將您的gcmids替換爲您在上述陣列中收到的新gcmids,下次您發送gcm通知時。
我的PHP應用是建立在笨框架所以這裏是我做的。 我有一個模型稱爲登錄,並在那裏我有與該用戶的用戶ID一起返回從數據庫gcmids作爲數組
function getAllRegIds(){
$query = "SELECT gcmid,id FROM users_app WHERE gcmid IS NOT NULL AND gcmid != '' GROUP BY gcmid"; //group by incase a user loggedin with multiple userids in your a
$query = $this->db->query($query);
if($query->num_rows() > 0){
$result = $query->result_array();
$regids = array();
foreach($result as $row){
$regids[$row['id']] = $row['gcmid'];
}
return $regids;
}else{
return false;
}
}
陣列看起來像這樣
Array(
[29] => APA91bEYda3DVb...
[1] => APA91bF0yfdZjX4...
[12] => APA91bG-9fsBGT-...
[11] => APA91bGNRh_VWF...
[3] => APA91bGXo_gnfBZ...
[2] => APA91bH3WdWwqFC...
[26] => APA91bHn8Ufwe4...
)
的索引的函數
指標是價值gcmid
用戶ID調用此函數控制器功能裏面,這裏是實現
public function sendtoall(){
$this->load->model('app/login');
$result = $this->login->getAllRegIds(); //here i got all gcmids with userids as index
$message = $this->input->post('message');
$chunks = array_chunk($result,1000); //broken the array into chunks of 1000 ids because gcm can only send message to 1000 ids at a time
$status = $this->sendNotification($chunks,$message);
if(!empty($status) && is_array($status)){
foreach($status as $key=>$row){
if(array_key_exists('canonical_ids',$row) && $row['canonical_ids'] > 0){
$canonical_ids = $row['canonical_ids'];
if(array_key_exists('results',$row) && !empty($row['results']) && is_array($row['results'])){
foreach($row['results'] as $k=>$v){
if(array_key_exists('registration_id',$v)){
$userid = array_search($chunks[$key][$k], $result);
$newgcmid = $v['registration_id'];
$this->login->updateGCMId($userid,$newgcmid);
}
}
}
}
}
}
echo json_encode($status);
}
你在評論中我已經把數組分成了1000個ID,因爲gcm一次可以發送消息給1000ids,並且調用一個函數sendNotification
,返回gcm接收到的響應,這是我粘貼的那個數組擁有所有規範ID。
然後我檢查如果狀態不爲空並且是一個數組,FOREACH狀態,因爲它可以有多個響應陣列因爲我在1000個IDS塊發送通知,見下文
則sendNotification
實施我檢查它是否有索引canonical_ids
並且大於0,這意味着有需要被替換的id,然後我檢查它是否具有索引result
,而不是空的並且是一個數組。
的foreach result
並獲得具有registration_id
指數在它的指數,這意味着這些ID的鍵和值需要在我們的數據庫
得到其gcmid
需要被替換爲用戶的userid
被替換搜索result
陣列,與用戶的oldgcm ID($chunks[$key][$k]
,第一個參數是有你需要的gcmid
和第二塊的關鍵是在於gcmid
的index
)
得到新gcmid
所述results
陣列
呼叫模型函數updateGCMId
,通過userid
和newgcmid
。
這裏是執行sendNotification
和updateGCMId
的功能。
private function sendNotification($regids,$message){
$status = array();
$result = $regids;
if($result){
foreach($result as $thousandids){
$registatoin_ids=$thousandids;
$msg=array("message"=>$message);
$url='https://android.googleapis.com/gcm/send';
$fields=array
(
'registration_ids'=>$registatoin_ids,
'data'=>$msg
);
$headers=array
(
'Authorization: key=AIza..............',
'Content-Type: application/json'
);
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
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);
$result = json_decode($result,1);
$status[] = $result;
}
}
return $status;
}
update
功能:
public function updateGCMId($userid,$gcmid){
$query = 'UPDATE users_app SET
gcmid = "'.$gcmid.'"
WHERE id = "'.$userid.'"';
$this->db->query($query);
}
最後得到了Duplicate Registration Id工作方案。其全部是關於使用規範ID更新現有註冊ID。
Google的示例代碼隨附在Android Studio中的模板中生成的後端爲您執行此操作。檢查MessageEndpoint類,你會注意到他們正在檢查規範的id,如果它存在,那麼假設是regid已經改變,因此理想情況下需要針對該特定設備進行更新。
public void sendMessage(@Named("message") String message) throws IOException {
if (message == null || message.trim().length() == 0) {
log.warning("Not sending message because it is empty");
return;
}
// crop longer messages
if (message.length() > 1000) {
message = message.substring(0, 1000) + "[...]";
}
Sender sender = new Sender(API_KEY);
Message msg = new Message.Builder().addData("message", message).build();
List<RegistrationRecord> records = ofy().load().type(RegistrationRecord.class).limit(10).list();
for (RegistrationRecord record : records) {
Result result = sender.send(msg, record.getRegId(), 5);
if (result.getMessageId() != null) {
log.info("Message sent to " + record.getRegId());
String canonicalRegId = result.getCanonicalRegistrationId();
if (canonicalRegId != null) {
// if the regId changed, we have to update the datastore
log.info("Registration Id changed for " + record.getRegId() + " updating to " + canonicalRegId);
record.setRegId(canonicalRegId);
ofy().save().entity(record).now();
}
} else {
String error = result.getErrorCodeName();
if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
log.warning("Registration Id " + record.getRegId() + " no longer registered with GCM, removing from datastore");
// if the device is no longer registered with Gcm, remove it from the datastore
ofy().delete().entity(record).now();
} else {
log.warning("Error when sending message : " + error);
}
}
}
}
- 1. Android的GCM註冊設備
- 2. Android GCM註冊ID
- 3. Android GCM註冊ID
- 4. Google Cloud Messaging(GCM)問題每個設備和用戶有多少個註冊ID?
- 5. 設備上的不同GCM註冊ID
- 6. Android GCM給予每次同一設備的新註冊ID
- 7. GCM - 一個註冊ID正在工作,但因多個註冊ID失敗
- 8. Android GCM:檢索設備註冊標識
- 9. Android中的Gcm設備註冊問題
- 10. Android GCM某些設備未註冊
- 11. Android GCM:空註冊ID
- 12. Android GCM註冊ID錯誤
- 13. Android GCM檢索註冊ID
- 14. android GCM註冊ID空白
- 15. GCM註冊ID
- 16. SQLite在多個設備上註冊 - Android
- 17. Gcm android應用程序觸發同一設備的多個註冊
- 18. Android GCM-每次在不同的設備上註冊相同的註冊ID
- 19. 註冊 - 從Android GCM取消註冊設備
- 20. GCM(Google雲消息傳遞) - 我可以使用相同的註冊ID註冊多個設備嗎?
- 21. 如果一個能夠沒有得到關於「複製」註冊一個ID canoncial同一設備多次註冊?
- 22. App Engine的註冊設備GCM
- 23. Android GCM註冊
- 24. 明確重新註冊設備到GCM
- 25. 每個設備或每個設備的GCM限制爲100個消息/ 4個合攏鍵註冊ID
- 26. 無法在GCM中註冊設備
- 27. 什麼是GCM註冊ID?
- 28. GCM:註冊設備[GCMRegistrar.register(this,SENDER_ID)]
- 29. GCM不在某些設備中註冊
- 30. 在操作系統更新中更新設備gcm註冊ID
謝謝大家,但主要問題不在於更新。在scenerio用戶可能有許多Android設備。由於這3個設備可能有7個註冊ID。我想發送3條推送消息,但GCM將發送7. – iravul