2013-06-27 17 views
5

由於問題說如何找出registration IDGoogleCloudMessaging API中何時失效? 我已經閱讀了有關類似主題的幾個問題的答案:Do GCM registration id's expire?Google Coud Mesaging (GCM) and registration_id expiry, how will I know?。這些問題的問題是,這裏的答案是C2DM或舊的GCM API,它使用GCMRegistrar代替GoogleCloudMessaging API。前兩種方法已折舊。在GoogleCloudMessaging API中,如何處理註冊ID的更新或過期?

我會試着打破我的困惑/問題逐步

1)在標題Enable GCM,在第二點,它說:

Google may periodically refresh the registration ID, so you should design your Android application with the understanding that the com.google.android.c2dm.intent.REGISTRATION intent may be called multiple times. Your Android application needs to be able to respond accordingly.

The registration ID lasts until the Android application explicitly unregisters itself, or until Google refreshes the registration ID for your Android application. Whenever the application receives a com.google.android.c2dm.intent.REGISTRATION intent with a registration_id extra, it should save the ID for future use, pass it to the 3rd-party server to complete the registration, and keep track of whether the server completed the registration. If the server fails to complete the registration, it should try again or unregister from GCM.

2)現在,如果是這種情況我應該處理BroadcastReceiver中的意圖,並再次發送register()請求以獲取新的註冊ID。但問題是,在標題ERROR_MAIN_THREAD下的同一頁上,它說: GCM methods are blocking. You should not run them in the main thread or in broadcast receivers

3)我也明白,還有其他兩種情況時的註冊ID的變化(品目Keeping the Registration State in Sync)根據下高級主題提到: 應用程序更新和備份&恢復。我已經在打開應用程序時處理它們。

4)在GCMRegistrar API,內部GCMBaseIntentService,過去有一個回調onRegistered()方法中,當設備註冊得到其中得到調用。在這裏我曾經堅持註冊ID併發送到第三方服務器。

但是,現在我應該如何處理註冊ID的更新或更新,堅持並將其發送到第三方服務器?

可能是因爲閱讀所有內容而感到困惑,或者我錯過了某些東西。我會非常感謝你的幫助。

更新

即使在Handling registration ID changes in Google Cloud Messaging on Android線程,不存在如何通過谷歌處理ID的週期性刷新提?

+0

此可能的重複 - http://stackoverflow.com/questions/16838654/handling-registration-id-changes-in-google-cloud-messaging-on-android/16839326#16839326 – Eran

回答

4

我給一個辦法,因爲我在我的應用程序

@Override 
protected void onRegistered(Context context, String registrationId) { 
    Log.i(TAG, "Device registered: regId = " + registrationId); 
    //displayMessage(context, getString(R.string.gcm_registered)); 
    //ServerUtilities.register(context, registrationId); 
    //1. Store this id to application Prefs on each request of device registration 
    //2. Clear this id from app prefs on each request of device un-registration 
    //3. Now add an if check for new registartion id to server, you can write a method on server side to check if this reg-id matching for this device or not (and you need an unique identification of device to be stored on server) 
    //4. That method will clear that if id is matching it meanse this is existing reg-id, and if not matching this is updated reg-id. 
    //5. If this is updated reg-id, update on server and update into application prefs. 
} 

實現你可以做這樣也

if reg_id exists_into prefrences then 
    if stored_id equals_to new_reg_id then 
     do nothing 
    else 
     say server to reg_id updated 
     update prefrences with new id 
    end if 
else 
    update this id to application prefs 
    say server that your device is registered 
end if 

但是問題出現時,用戶清除應用程序數據,你將失去當前的註冊ID。


更新爲新的API例如現金去Eran他的回答Handling registration ID changes in Google Cloud Messaging on Android

谷歌改變了他們的Demo App使用新界面。他們通過設置應用程序本地保存的值的到期日期來刷新註冊ID。當應用程序啓動時,它們會加載其本地存儲的註冊ID。如果它是「過期」(在演示中意味着它在7天前從GCM收到),他們再次呼叫gcm.register(senderID)

這並不處理假設的情況,其中註冊ID由Google刷新爲長時間未啓動的應用程序。在這種情況下,應用程序將不會意識到更改,第三方服務器也不會。

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 
    mDisplay = (TextView) findViewById(R.id.display); 

    context = getApplicationContext(); 
    regid = getRegistrationId(context); 

    if (regid.length() == 0) { 
     registerBackground(); 
    } 
    gcm = GoogleCloudMessaging.getInstance(this); 
} 

/** 
* Gets the current registration id for application on GCM service. 
* <p> 
* If result is empty, the registration has failed. 
* 
* @return registration id, or empty string if the registration is not 
*   complete. 
*/ 
private String getRegistrationId(Context context) { 
    final SharedPreferences prefs = getGCMPreferences(context); 
    String registrationId = prefs.getString(PROPERTY_REG_ID, ""); 
    if (registrationId.length() == 0) { 
     Log.v(TAG, "Registration not found."); 
     return ""; 
    } 
    // check if app was updated; if so, it must clear registration id to 
    // avoid a race condition if GCM sends a message 
    int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE); 
    int currentVersion = getAppVersion(context); 
    if (registeredVersion != currentVersion || isRegistrationExpired()) { 
     Log.v(TAG, "App version changed or registration expired."); 
     return ""; 
    } 
    return registrationId; 
} 

/** 
* Checks if the registration has expired. 
* 
* <p>To avoid the scenario where the device sends the registration to the 
* server but the server loses it, the app developer may choose to re-register 
* after REGISTRATION_EXPIRY_TIME_MS. 
* 
* @return true if the registration has expired. 
*/ 
private boolean isRegistrationExpired() { 
    final SharedPreferences prefs = getGCMPreferences(context); 
    // checks if the information is not stale 
    long expirationTime = 
      prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1); 
    return System.currentTimeMillis() > expirationTime; 
} 
+0

感謝您的答案Pankaj。您是否在服務[GCMBaseIntentService](http://developer.android.com/reference/com/google/android/gcm/GCMBaseIntentService.html)中執行此操作?當我使用[GCMRegistrar](http://developer.android.com/reference/com/google/android/gcm/GCMRegistrar.html)時,我確實使用過這種意圖服務。 –

+0

否。這是'GCMIntentService'的方法。 –

+0

Oh Yaa ..抱歉,我的意思是'GCMIntentService',它擴展了'GCMBaseIntentService'?這已被貶值了嗎? (但仍然有效) –

0

只需添加到潘卡的回答是:

  • This(the example on getting started documents by Google) doesn't handle the hypothetical scenario in which a registration ID is refreshed by Google for an app that hasn't been launched for a long time. In that case, the app won't be aware of the change, and neither will the 3rd party server.

    。的確,在Getting started文件的例子不處理這種情況。所以開發商 需要處理自己。

  • 而且回答說,They refresh the registration ID by setting an expiration date on the value persisted locally by the app. When the app starts, they load their locally stored registration id. If it is "expired" they call gcm.register(senderID) again.

    的問題是,樣品中的registration ID的七天當地到期是爲了避免場景的設備發送 註冊到第三方服務器,但服務器丟失它。它不會處理從Google服務器刷新ID的 。

  • 的標題下,Enable GCMArchitectural Overview頁第二點,它說:

    Note that Google may periodically refresh the registration ID, so you should design your Android application with the understanding that the com.google.android.c2dm.intent.REGISTRATION intent may be called multiple times. Your Android application needs to be able to respond accordingly.

    所以,處理,你應該有一個廣播監聽器 可以處理com.google.android.c2dm.intent.REGISTRATION意圖, 其中谷歌發送當它必須刷新註冊 ID的應用程序。

  • 有問題的另一部分其中規定有關the problem is that inside the Broadcast Listener I cannot call register the for Push ID again. This is because the documentation說: GCM methods are blocking. You should not run them in the main thread or in broadcast receiver

    我認爲這個問題是完全不同的聲明。當您註冊廣播接收器時,它將有一個Intent,其中將包含來自Google的新registration ID。我不需要在Broadcast監聽器中再次調用gcm.register()方法。

希望這可以幫助別人瞭解如何處理註冊ID的更新。

+0

它的一個簡單的要求,如果你是投票的答案,請評論進一步解釋。這將幫助我改進答案,並讓我理解您對答案內容的看法。雖然以前的答案有所幫助,但實際上並沒有回答/解決混亂,所以我再次回答。如果你認爲答案中有任何批評,請說出來。它會清楚更多的概念。再次感謝! –

+1

我不確定爲什麼這會降低投票率。這是非常清楚和有益的。 Upvote從我。 – KyleT

+0

無論你寫什麼都不回答問題,你在新舊api之間感到困惑。要麼使用舊的,要麼使用新的 –

相關問題