2013-05-29 28 views
5

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

2

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?

+0

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

0

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.

+0

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

+0

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

4

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).

+0

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

+0

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

+0

Ý 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

3

Đô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.

+0

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

0

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.

2

đâ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 useridnewgcmid.

đây là việc triển khai các chức năng sendNotificationupdateGCMId.

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); 
} 
0

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.

0

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); 
      } 
     } 
    } 
} 
Các vấn đề liên quan