Android GCM адно прылада мае некалькі RegistrationID

У мяне ёсць сістэма, якая мае бок PHP сервера і на баку кліента прыкладання для Android. Android адпраўляе параметры праз вэб-сэрвіс і PHP апрацоўваць бок GCM. PHP адпраўляе апавяшчэнне штуршок і перад адпраўкай, ён атрымлівае ўсё RegistrationID з БД. Праблема, тое ж самае прылада можа мець два ці больш RegistrationID. З-за гэтага, штуршок апавяшчэнне адпраўлена самага ўсталяваньня для двух або больш раз. Ці ёсць рашэнне, каб справіцца з гэтай праблемай?

5

8 адказы

GCM можа змяніць RegistrationID і вы павінны абнавіць яго на боку сервера.

  • Пры адпраўцы паведамлення вынік можа ўтрымліваць новы RegistrationID, які будзе выкарыстоўвацца для прылады, так што вы павінны абнавіць старую RegistrationID для новага.

Look this link at Interpreting a success response section

<�Р> Калі message_id усталяваны, праверце registration_id: Калі registration_id усталяваны, заменіце зыходны ідэнтыфікатар з новым значэннем (кананічны ID) у базе дадзеных сервера. Звярніце ўвагу, што арыгінальны ID не з'яўляецца часткай выніку, так што вам трэба, каб атрымаць яго з спісу registration_ids, перададзены ў запыце (выкарыстоўваючы адзін і той жа індэкс).
4
дададзена
Дрэнная ідэя, таму што: (terminal1) ааа (г гл) уваходу user1 і user2, калі змяніць (terminal1) гсм (ГЭБ), калі вы адпраўляеце чэк GCM тэрмінал (ГЭБ) і user2 ці не user1 атрымаць гэта апавяшчэнне. зман!
дададзена аўтар delive, крыніца
Па GCM паслуг адзін RegistrationID ідэнтыфікуе прылада/дадатак, так што вы павінны мець 3 RegID, калі карыстальнік мае 3 прылад, падлучаных да сервера з дапамогай GCM. Праверце перад GCMRegistrar.register калі ваш RegID ўсё яшчэ захоўваецца на GCMRegistrar.getRegistrationId , вы ствараеце больш, чым трэба.
дададзена аўтар AlexBcn, крыніца
Дзякуй за ўсё, але асноўная праблема заключаецца не ў тым, каб абнавіць. У scenerio элемент можа мець шмат АНДРОІД прылад. З-за гэтага 3 прылады могуць мець 7 RegistrationID х. Я хачу адправіць 3 націскнога паведамленне, але GCM адправіць 7.
дададзена аўтар iravul, крыніца

Часам Google змяняе рэгістрацыйны нумар, і вы будзеце мець некалькі ідэнтыфікатараў, звязаных. Сервер, які адпраўляе апавяшчэнне (ваш сервер) павінен абнавіць базу дадзеных з новым ідэнтыфікатарам.

Для атрымання дадатковай інфармацыі праверыць гэты дакумент:

http://developer.android.com/google/gcm/adv.html

яны кажуць:

Гэта ідэнтыфікатары Canonical

На баку сервера, да таго часу, пакуль прыкладанне паводзіць сябе добра, усё павінна працаваць нармальна. Аднак, калі памылка ў дадатку запускае некалькі рэгістрацый для аднаго прылады, гэта можа быць цяжка ўзгадніць стан, і вы маглі б у канчатковым выніку з дубляваннем паведамленняў.

GCM прадастаўляе сродак, званае «кананічнае рэгістрацыі ВД» лёгка аднавіць з гэтых сітуацый. Кананічная рэгістрацыя ID вызначаюцца як ідэнтыфікатар апошняй рэгістрацыі запытанага дадаткам. Гэта ідэнтыфікатар, які сервер павінен выкарыстоўваць пры адпраўцы паведамленняў на прыладу.

Калі пазней вы спрабуеце адправіць паведамленне, выкарыстоўваючы іншы рэгістрацыйны нумар, GCM будзе апрацоўваць запыт, як звычайна, але яна будзе ўключаць у сябе кананічны рэгістрацыйны нумар у registration_id поля адказу. Пераканайцеся ў тым, каб замяніць рэгістрацыйны нумар, які захоўваецца на серверы з гэтай кананічнай ID, у канчатковым рахунку ідэнтыфікатара, які вы выкарыстоўваеце перастанеце працаваць.

3
дададзена
Я сутыкнуўся пытанне з 2-ма рознымі ідэнтыфікатарамі рэгістрацыі на адным прыладзе, але вяртаць 0 canonical_ids ..
дададзена аўтар neobie, крыніца

вось маё рашэнне гэтай праблемы. пры адпраўцы апавяшчэння 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, што азначае, што ў вас 4 карыстальнікаў спарадзілі новыя GCM ідэнтыфікатары, зараз усё, што вам трэба зрабіць, гэта замяніць іх gcmids на новы, які вы атрымалі ў прыведзеным вышэй масіве , у наступны раз, калі вы адпраўляеце апавяшчэнне GCM.

мой PHP прыкладанне пабудавана на рамках CodeIgniter дык вось што я зрабіў. У мяне ёсць мадэль пад назвай лагін і там у мяне ёсць функцыя, якая вяртае 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

гэтая функцыя выклікаецца ўнутры функцыі кантролера, тут рэалізацыя

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 ідэнтыфікатарамі, таму што гсм можа адправіць паведамленне 1000ids у той час, і завецца функцыяй sendNotification , які вяртае адказ, атрыманы ад ГКМ, які з'яўляецца масівам я ўставіў вышэй, які мае ўсе кананічныя ідэнтыфікатары.

Затым я праверыў, калі стан не пуста і з'яўляецца масівам, Foreach статус, паколькі ён можа мець некалькі масіваў адказу, таму што я пасылаю апавяшчэнне ў кавалкі 1000 ідэнтыфікатараў, см sendNotification рэалізацыі ніжэй

Затым я праверыў, калі ён мае індэкс canonical_ids і больш 0, што азначае, што ёсць ідэнтыфікатары, якія павінны быць замененыя, то я праверыў, калі ён мае індэкс вынік , не пуста і з'яўляецца масівам.

Еогеасп вынік і атрымаць ключы і значэння гэтых індэксаў, які мае registration_id індэкс ў ім, што азначае, што гэтыя ідэнтыфікатары неабходна замяніць у нашай БД

атрымаць ідэнтыфікатар карыстальніка карыстальніка, для якога gcmid павінен быць заменены з дапамогай функцыі пошуку вынік масіў з oldgcm ідэнтыфікатарам карыстальніка ( $ лусты [$ ключ] [$ да] , першы параметр з'яўляецца ключом фрагмента, які мае gcmid вам трэба, і другі з'яўляецца індэкс з што gcmid )

атрымаць новы gcmid з Вынікі масіў

выклік функцыі мадэлі updateGCMId , перадайце ідэнтыфікатар карыстальніка і 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 function:

public function updateGCMId($userid,$gcmid){
      $query = 'UPDATE users_app SET 
                  gcmid = "'.$gcmid.'" 
                WHERE id = "'.$userid.'"';
      $this->db->query($query);
}
2
дададзена

Вы проста павінны захоўваць Uniq ідэнтыфікатар для кожнага прылады ў базе дадзеных. Затым, вы можаце адправіць толькі адзін штуршок апавяшчэнне для кожнага прылады.

Я ніколі не ўбачыць некалькі рэгістрацыі ідэнтыфікатар для таго ж самага прылады. Дзіўная рэч.

Ці ўдалося вам абнаўленне ідэнтыфікатар рэгістрацыі правільна?

2
дададзена
Дзякуй за ўсё, але асноўная праблема заключаецца не ў тым, каб абнавіць. У scenerio элемент можа мець шмат АНДРОІД прылад. З-за гэтага 3 прылады могуць мець 7 RegistrationID х. Я хачу адправіць 3 націскнога паведамленне, але GCM адправіць 7.
дададзена аўтар iravul, крыніца

Вы атрымаеце кананічныя Ідэнтыфікатары ў вашым націскной адказ. Вам неабходна абнавіць стары ідэнтыфікатар з новымі кананічнымі ідэнтыфікатарамі.

Існуе яшчэ адно рашэнне. Больш падобна на патч. Вы можаце перадаць параметр «dry_run» ў запыце GCM JSON. Калі мы яго так, ён адправіць фальшывае паведамленне для ідэнтыфікатара прылады і згенераваць адказ.

Прылада не атрымае паведамленне, але вы атрымаеце адказ, такім чынам, вы можаце праверыць, якія Ідэнтыфікатары прылад маюць registration_ids ў іх выніку, і выдаліць іх з базы дадзеных.

        $fields = array(
                    'registration_ids'  => $deviceId,
                    'data' => array( "message" =>'fake_message'),
                    'dry_run'=>true
                    );

Спадзяюся, што гэта дапамагае.

0
дададзена

Прыклад кода Google, які пастаўляецца з сервернай, які атрымлівае генеруецца з шаблону ў Android Studio робіць гэта для вас. Праверце клас MessageEndpoint, і вы ўбачыце, што яны правяраюць для кананічнага ідэнтыфікатара, і калі ён існуе, то здагадка аб тым, што 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 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);
            }
        }
    }
}
0
дададзена

Я думаю, ваша праблема ў тым, як вы атрымаеце рэгістрацыйны ідэнтыфікатар з прылады. Вы павінны быць упэўнены, што ён пасылае адзін раз RegID і калі запыт GCM Сервер абнаўлення, вы павінны паўторна адправіць RegID на свой вэб-сервер і захаваць яго, перапісаўшы старую перарабіў. См гэтай часткі андроіда спасылкі.

0
дададзена
Вы не разумееце, мой адказ ... для кожнага прылады, сервер Google GCM жадае час ад часу абнаўляць па ID ... праверце дакументацыю андроіда АПА ... памылка ў пачатку: кожнае прылада павінна мець толькі адзін RegID ў час.
дададзена аўтар trullallero, крыніца
Дзякуй за ўсё, але асноўная праблема заключаецца не ў тым, каб абнавіць. У scenerio элемент можа мець шмат АНДРОІД прылад. З-за гэтага 3 прылады могуць мець 7 RegistrationID х. Я хачу адправіць 3 націскнога паведамленне, але GCM адправіць 7.
дададзена аўтар iravul, крыніца

Нарэшце атрымаў працоўнае рашэнне для Дублікат рэгістрацыі Id . Яго ўсё пра абнаўленне існуючай рэгістрацыі ідэнтыфікатара з кананічнымі ідэнтыфікатарамі.

0
дададзена