Tôi có hệ thống có ứng dụng bên Máy chủ PHP và Ứng dụng khách của Android. Android gửi thông số qua webservice và PHP xử lý phía GCM. PHP gửi thông báo đẩy và trước khi gửi đi, nó nhận tất cả đăng ký từ DB. Vấn đề là, cùng một thiết bị có thể có hai hoặc nhiều đăng ký. Bởi vì điều này, đẩy thông báo được gửi đến các thiết bị tương tự cho hai hoặc nhiều lần. Có giải pháp nào để xử lý vấn đề này không?Android GCM một thiết bị có nhiều đăng ký
Trả lời
Bạn chỉ cần lưu trữ id uniq cho từng thiết bị trong cơ sở dữ liệu của mình. Sau đó, bạn chỉ có thể gửi một thông báo đẩy cho mọi thiết bị.
Tôi chưa bao giờ thấy nhiều ID đăng ký cho cùng một thiết bị. Điều kỳ lạ.
Bạn có quản lý cập nhật id đăng ký chính xác không?
Tôi nghĩ rằng vấn đề của bạn là cách bạn lấy id đăng ký từ thiết bị. Bạn phải chắc chắn rằng nó gửi một lần regID và khi máy chủ GCM yêu cầu làm mới, bạn phải gửi lại regID tới máy chủ web của bạn và lưu trữ nó, ghi đè lên redID cũ. Xem this một phần tham chiếu Android.
Cảm ơn tất cả các bạn nhưng vấn đề chính không phải là để cập nhật. Trong scenerio người dùng có thể có nhiều thiết bị Android. Vì 3 thiết bị này có thể có 7 đăng ký của. Tôi muốn gửi 3 tin nhắn push nhưng GCM sẽ gửi 7. – iravul
YOu không hiểu câu trả lời của tôi ... cho mọi thiết bị, máy chủ GCM của Google muốn làm mới định kỳ ID ... kiểm tra tài liệu api android ... lỗi là ở đầu: mỗi thiết bị phải có chỉ có một regid tại thời điểm. – trullallero
GCM có thể thay đổi registrationId và bạn phải cập nhật nó ở phía máy chủ của bạn.
- Khi bạn gửi thư, kết quả có thể chứa đăng ký mới sẽ được sử dụng cho thiết bị, vì vậy bạn phải cập nhật thông tin đăng ký cũ cho thiết bị mới.
Look này link at Interpreting a success response section
Nếu message_id được thiết lập, kiểm tra registration_id: Nếu registration_id được thiết lập, thay thế ID ban đầu với giá trị mới (kinh điển ID) trong cơ sở dữ liệu máy chủ của bạn. Lưu ý rằng ID gốc không phải là một phần của kết quả, vì vậy bạn cần lấy nó từ danh sách các registration_ids được chuyển trong yêu cầu (sử dụng cùng một chỉ mục).
Cảm ơn tất cả các bạn nhưng vấn đề chính không phải là để cập nhật. Trong scenerio người dùng có thể có nhiều thiết bị Android. Vì 3 thiết bị này có thể có 7 đăng ký của. Tôi muốn gửi 3 tin nhắn push nhưng GCM sẽ gửi 7. – iravul
Bằng dịch vụ GCM, một đăng ký sẽ xác định thiết bị/ứng dụng, vì vậy bạn nên có 3 regId nếu người dùng có 3 thiết bị được kết nối với máy chủ của bạn bằng GCM. Kiểm tra trước 'GCMRegistrar.register' nếu regId của bạn vẫn được lưu trữ trên' GCMRegistrar.getRegistrationId', bạn đang tạo ra nhiều hơn mức cần thiết. – AlexBcn
Ý tưởng tồi, vì: (terminal1) gcm (aaa) đăng nhập user1 và user2, nếu bạn thay đổi (terminal1) gcm (bbb) nếu bạn gửi thiết bị đầu cuối kiểm tra GCM (bbb) và user2 hoặc user1 không nhận được thông báo này. quan niệm sai lầm! – delive
Đôi khi Google thay đổi ID đăng ký và bạn sẽ có nhiều ID được liên kết. Máy chủ gửi thông báo (máy chủ của bạn) phải cập nhật cơ sở dữ liệu bằng ID mới.
Để biết thêm thông kiểm tra tài liệu này:
http://developer.android.com/google/gcm/adv.html
họ nói:
Đây là một ID Canonical
Về phía server, miễn là ứng dụng được cư xử tốt, tất cả mọi thứ nên hoạt động bình thường. Tuy nhiên, nếu một lỗi trong ứng dụng kích hoạt nhiều đăng ký cho cùng một thiết bị, có thể khó hòa hợp trạng thái và bạn có thể kết thúc với các thư trùng lặp.
GCM cung cấp cơ sở được gọi là "ID đăng ký kinh điển" để dễ dàng khôi phục từ những tình huống này. ID đăng ký kinh điển được định nghĩa là ID của lần đăng ký cuối cùng do ứng dụng của bạn yêu cầu. Đây là ID mà máy chủ sẽ sử dụng khi gửi tin nhắn đến thiết bị.
Nếu sau này bạn cố gửi thư bằng ID đăng ký khác, GCM sẽ xử lý yêu cầu như bình thường, nhưng sẽ bao gồm ID đăng ký chuẩn trong trường registration_id của phản hồi. Đảm bảo thay thế ID đăng ký được lưu trữ trong máy chủ của bạn bằng ID chính tắc này, vì cuối cùng ID bạn đang sử dụng sẽ ngừng hoạt động.
Tôi đang gặp vấn đề với 2 ID đăng ký khác nhau trên cùng một thiết bị nhưng 0 canonical_ids trả về .. – neobie
Bạn sẽ nhận được Id chính tắc trong phản hồi đẩy của mình. Bạn cần cập nhật Id cũ của mình bằng Id chuẩn mới.
Còn một giải pháp nữa. Giống như một miếng vá. Bạn có thể chuyển tham số 'dry_run' trong JSON yêu cầu GCM. Khi chúng ta đặt nó thành true, nó sẽ gửi một thông báo giả đến Id thiết bị và tạo ra một phản hồi.
Thiết bị sẽ không nhận được tin nhắn nhưng bạn sẽ nhận được phản hồi của bạn, do đó bạn có thể kiểm tra ID thiết bị nào có registration_ids trong kết quả của chúng và xóa chúng khỏi cơ sở dữ liệu của bạn.
$fields = array(
'registration_ids' => $deviceId,
'data' => array("message" =>'fake_message'),
'dry_run'=>true
);
Hy vọng điều đó sẽ hữu ích.
đây là giải pháp của tôi cho vấn đề này. khi bạn gửi một thông báo gcm bạn nhận được một câu trả lời như thế này
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
)
)
)
trong mảng có một chỉ số canonical_ids
đó là 4 có nghĩa là u có 4 người dùng đã tạo ra id gcm mới, bây giờ tất cả các bạn cần làm là thay thế gcmids của họ bằng gcmids mới mà bạn nhận được trong mảng trên, lần sau khi bạn gửi thông báo gcm.
ứng dụng php của tôi được xây dựng trên khuôn khổ mã vạch nên đây là những gì tôi đã làm. tôi có một mô hình gọi là đăng nhập và trong đó tôi có một hàm trả về gcmids từ cơ sở dữ liệu cùng với userid của người sử dụng như một chỉ số của mảng
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;
}
}
mảng trông như thế này
Array(
[29] => APA91bEYda3DVb...
[1] => APA91bF0yfdZjX4...
[12] => APA91bG-9fsBGT-...
[11] => APA91bGNRh_VWF...
[3] => APA91bGXo_gnfBZ...
[2] => APA91bH3WdWwqFC...
[26] => APA91bHn8Ufwe4...
)
index là userid với giá trị gcmid
chức năng này được gọi là bên trong chức năng điều khiển, đây là việc thực hiện
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);
}
như bạn trong các nhận xét tôi đã chia mảng thành 1000 id vì gcm có thể gửi tin nhắn tới 1000ids cùng một lúc và gọi hàm sendNotification
trả về phản hồi nhận được bởi gcm, đó là mảng tôi đã dán ở trên có tất cả các id chuẩn.
sau đó tôi kiểm tra nếu tình trạng này là không có sản phẩm nào và là một mảng, foreach tình trạng vì nó có thể có nhiều mảng phản ứng, vì tôi đang gửi thông báo trong khối 1000 ids, xem việc thực hiện sendNotification
dưới
sau đó tôi được kiểm tra nếu nó có chỉ mục canonical_ids
và lớn hơn 0, có nghĩa là có các id cần được thay thế, sau đó tôi đã kiểm tra nếu nó có chỉ mục result
, không trống và là một mảng.
foreach result
và lấy chìa khóa và giá trị của những chỉ số có registration_id
chỉ mục trong nó, có nghĩa là các id này cần phải được thay thế trong db của chúng tôi
được userid
của người dùng có gcmid
cần phải được thay thế bằng tìm kiếm trên mảng result
, với id oldgcm của người dùng ($chunks[$key][$k]
, tham số đầu tiên là chìa khóa của đoạn mà có gcmid
bạn cần và thứ hai là index
đó gcmid
)
lấy mới gcmid
từ mảng results
gọi hàm mẫu updateGCMId
, chuyển userid
và newgcmid
.
đây là việc triển khai các chức năng sendNotification
và 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
chức năng:
public function updateGCMId($userid,$gcmid){
$query = 'UPDATE users_app SET
gcmid = "'.$gcmid.'"
WHERE id = "'.$userid.'"';
$this->db->query($query);
}
Cuối cùng có giải pháp làm việc cho Duplicate Registration Id. Tất cả về việc cập nhật id đăng ký hiện tại với id chuẩn.
Mã mẫu của Google đi kèm với chương trình phụ trợ được tạo từ mẫu trong Android Studio thực hiện điều này cho bạn. Kiểm tra lớp MessageEndpoint và bạn sẽ nhận thấy rằng họ đang kiểm tra một id chuẩn và nếu nó tồn tại thì giả định là regid đã thay đổi và do đó lý tưởng cần được cập nhật cho thiết bị cụ thể đó.
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 Một số thiết bị không đăng ký
- 2. Tin nhắn GCM của Android cho một thiết bị khác
- 3. Cách gửi tin nhắn GCM tới nhiều thiết bị cùng một lúc
- 4. Thiết bị Android 4.x nhận tin nhắn GCM, nhưng thiết bị Android 2.3 Không
- 5. ID đăng ký GCM đã thay đổi
- 6. Hết hạn đăng ký GCM của bạn?
- 7. ID đăng ký GCM của android dài tối đa
- 8. Android-GCM: Cách chăm sóc người dùng đã đăng xuất?
- 9. GCM: MulticastResult - kết quả nào từ thiết bị nào?
- 10. Gửi thông báo GCM vào một thiết bị ẩn
- 11. Android: Trong Trình chọn thiết bị Android, cùng một thiết bị hiển thị nhiều lần
- 12. Android GCM SERVICE_NOT_AVAILABLE
- 13. Phát triển nhiều thiết bị Android
- 14. Android GCM time_to_live issue
- 15. Thử nghiệm nhiều thiết bị Android trên một máy
- 16. Gửi push tới nhiều thiết bị Android với một POST
- 17. mục đích phát sóng đã bị hủy. Android GCM
- 18. Lỗi GCM không hợp lệ của Android GCM với PHP
- 19. Đặt thiết bị Android làm máy chủ để gửi tin nhắn tới GCM trực tiếp
- 20. Làm cách nào tôi có thể nhận được thiết bị ID đăng ký
- 21. Đăng ký một tệp nhiều gigabyte
- 22. Android GCM mã hóa
- 23. Id dự án Android GCM, cái nào?
- 24. Android - Cách cài đặt APK đã ký trên thiết bị?
- 25. rollback/hủy thông báo android-gcm
- 26. Cách đăng nhập tự động bằng Thiết bị sau khi đăng ký?
- 27. Thiết bị Android không có JIT
- 28. WiFi Direct (Android 4.0) với nhiều thiết bị (3+)
- 29. Kiến trúc P6 - Đăng ký đổi tên sang một bên, sổ đăng ký người dùng bị hạn chế có dẫn đến nhiều op hơn chi tiêu/tải không?
- 30. Android Google Cloud Messaging (GCM) và id người gửi bị bỏ lỡ
Cảm ơn tất cả nhưng vấn đề chính không phải là để cập nhật. Trong scenerio người dùng có thể có nhiều thiết bị Android. Vì 3 thiết bị này có thể có 7 đăng ký của. Tôi muốn gửi 3 tin nhắn push nhưng GCM sẽ gửi 7. – iravul