2013-12-20 3 views
1

Google 클라우드 메시징을 사용하여 알림을 보냅니다. 내 응용 프로그램은 내 서버 데이터베이스에 토큰을 보낸다. 문제는 save token request이 서버에 동시에 두 번 전송된다는 것이다 (복제본과 동일 함). 그래서 서버를 통해이 문제를 해결할 수 없습니다 (타이밍이 동일하기 때문에 insert if not exist을 말할 수 없습니다) ... 문제가있는 경우 앱을 통해 알 수 없습니다.Google 클라우드 메시징 : 데이터베이스의 중복 토큰

문제는 Google에서 발생한다고 생각하지만 잘 모르겠습니다.

이 등록 내 코드입니다 :

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

이 호출 된 클래스

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

이며,이 서버 클래스

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

답변

1

귀하의 코드는 신규 등록 방법을 혼합에게 있습니다 (GoogleCloudMessaging.register)를 사용되지 않는 GCMRegistrar 클래스와 비교합니다. 그리고 두 가지 비동기 작업의 중첩 된 사용법은 매우 혼란 스럽습니다.

서버에서 동일한 등록 ID로 두 개의 요청을받는 경우 클라이언트 코드가 유일한 책임입니다. 이 너무 복잡한 코드를 디버깅하는 대신 현재 Google GCM Demo을 참조로 사용하는 것이 좋습니다.

+0

왜이 일이 onClick에 있는지 서 있으십시오. gcm.send (SENDER_ID + "@ gcm.googleapis.com", id, data); @ wuth 부분은 무엇입니까? –

+0

@DFerra 데모에서는 GCM - 기기 대 클라우드 메시징의 새로운 기능을 사용합니다. 이는 GCM 서버 (GCM XMPP 프로토콜 사용 필요)를 통해 앱에서 내 서버로 메시지를 보내는 방법입니다. 서버에서 앱으로 메시지를 보내는 경우에만 필요하지 않습니다. 'SENDER_ID @ gcm.googleapis.com'은 GCM을 통해 앱에서 메시지를 보내려는 경우 서버를 식별하는 방법입니다. – Eran

0

당신이

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

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

나머지 만

ApiDemo를 제공 자세한 내용은 체크 GCMDemo에 대한 서버 유틸리티에주의를 기울여야 확인하는

코드 위

는 서비스를 등록 칠 것이다 번만

메리 크리스마스

관련 문제