D Ferra
D Ferra

Reputation: 1233

Google Cloud Messaging: duplicate token in database

I use the Google Cloud Messaging to send notifications. My app sends the token (given obviously from Google) to my server database... the problem is that the save token request is being sent two times to the server at the same time (exact the same, like a clone)! So, via server I can't cure this problem (because the timing is the same, I can't tell insert if not exist)... via app I don't know if I have a problem.

I think the problem is from Google, but i don't know.

This is my code for registration:

        GCMRegistrar.checkDevice(this);
        GCMRegistrar.checkManifest(this);
        registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION));
        regId = GCMRegistrar.getRegistrationId(this);
        if (regId.equals("")) {
            new registra_background().execute();
        } else {
            if (!GCMRegistrar.isRegisteredOnServer(this)) {
                mRegisterTask = new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... params) {
                        ServerUtilities.register(context, regId);
                        return null;
                    }
                    @Override
                    protected void onPostExecute(Void result) {
                        mRegisterTask = null;
                    }
                };
                mRegisterTask.execute(null, null, null);
            }
        }

This is the called class

private class registra_background extends AsyncTask<Void, Integer, Void> {
    int progress_status;
    @Override
    protected void onPreExecute(){
        super.onPreExecute();
    }
    @Override
    protected Void doInBackground(Void... params){
        try{
            if (gcm == null) {
                gcm = GoogleCloudMessaging.getInstance(context);
            }
            regId = gcm.register(SENDER_ID);
            Log.e("TOKEN",regId);
        }catch(Exception ex){
            System.out.println("Errore dati");
        }
        return null;
    }
    @Override
    protected void onProgressUpdate(Integer... values){
    }
    @Override
    protected void onPostExecute(Void result){
        mRegisterTask = new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                ServerUtilities.register(context, regId);
                return null;
            }
            @Override
            protected void onPostExecute(Void result) {
                mRegisterTask = null;
            }
        };
        mRegisterTask.execute(null, null, null);
    }
}

and this is the server class

public final class ServerUtilities {
private static final int MAX_ATTEMPTS = 5;
private static final int BACKOFF_MILLI_SECONDS = 2000;
private static final Random random = new Random();
static public void register(final Context context, final String regId) {
    Database db;
    db = new Database(context);
    try {
        db.open();
    } catch (SQLException sqle) {
        throw sqle;
    }
    Cursor variabili=db.variabili();
    int x=1;
    String pvPref="",pvPrefProv="",pvPrefCitta="",pvPrefIndirizzo="";
    while(variabili.moveToNext()){
        if(x==1){
            pvPref=variabili.getString(variabili.getColumnIndex("valore"));
        }else if(x==2){
            pvPrefProv=variabili.getString(variabili.getColumnIndex("valore"));
        }else if(x==3){
            pvPrefCitta=variabili.getString(variabili.getColumnIndex("valore"));
        }else if(x==4){
            pvPrefIndirizzo=variabili.getString(variabili.getColumnIndex("valore"));
        }
        x++;
    }
    String serverUrl = SERVER_URL;
    Map<String, String> params = new HashMap<String, String>();
    params.put("regId", regId);
    params.put("token_push", regId);
    params.put("pvPref", pvPref);
    params.put("device",android.os.Build.MODEL);
    params.put("pvPrefProv", pvPrefProv);
    params.put("pvPrefCitta", pvPrefCitta);
    params.put("pvPrefIndirizzo", pvPrefIndirizzo);
    params.put("app_version", "2.0");
    params.put("os", Build.VERSION.RELEASE);
    long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
    for (int i = 1; i <= MAX_ATTEMPTS; i++) {
        try {
            post(serverUrl, params);
            SystemClock.sleep(500);
            GCMRegistrar.setRegisteredOnServer(context, true);
            return;
        } catch (IOException e) {
            if (i == MAX_ATTEMPTS) {
                break;
            }
            try {
                Thread.sleep(backoff);
            } catch (InterruptedException e1) {
                Thread.currentThread().interrupt();
                return;
            }
            backoff *= 2;
        }
    }
}
public static void unregister(final Context context, final String regId) {
    String serverUrl = SERVER_URL + "/unregister";
    Map<String, String> params = new HashMap<String, String>();
    params.put("regId", regId);
    try {
        post(serverUrl, params);
        GCMRegistrar.setRegisteredOnServer(context, false);
    } catch (IOException e) {
    }
}
private static void post(String endpoint, Map<String, String> params) throws IOException {
    URL url;
    try {
        url = new URL(endpoint);
    } catch (MalformedURLException e) {
        throw new IllegalArgumentException("invalid url: " + endpoint);
    }
    StringBuilder bodyBuilder = new StringBuilder();
    Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
    while (iterator.hasNext()) {
        Entry<String, String> param = iterator.next();
        bodyBuilder.append(param.getKey()).append('=').append(param.getValue());
        if (iterator.hasNext()) {
            bodyBuilder.append('&');
        }
    }
    String body = bodyBuilder.toString();
    byte[] bytes = body.getBytes();
    HttpURLConnection conn = null;
    try {
        conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setFixedLengthStreamingMode(bytes.length);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
        OutputStream out = conn.getOutputStream();
        out.write(bytes);
        out.close();
        int status = conn.getResponseCode();
        if (status != 200) {
            throw new IOException("Errore " + status);
        }
    } finally {
        if (conn != null) {
            conn.disconnect();
        }
    }
}
}

Upvotes: 1

Views: 247

Answers (2)

Amit
Amit

Reputation: 381

when you are checking

 if(regId==""){
        //here simply put
 GCMRegistrar.register(this, SENDER_ID);

 }else{
 ServerUtilities.register(context, regId);
   }

rest you should take care in server utilities only

for more information check GCMDemo available in Apidemo

above code will hit register service only once

Merry chrismas

Upvotes: 0

Eran
Eran

Reputation: 393936

Your code mixes the new registration method (GoogleCloudMessaging.register) with the old deprecated GCMRegistrar class. And the nested usage of two Async Tasks is very confusing.

If you get two requests with the same registration ID at your server, then your client code is the sole responsible. Instead of trying to debug this too complicated code, I suggest you use the current Google GCM Demo as a reference.

Upvotes: 1

Related Questions