[android] Android의 Google 클라우드 메시징에서 등록 ID 변경 처리

Google 클라우드 메시징의 문서에서 다음과 같이 설명합니다.

Android 애플리케이션은 나중에 사용할 수 있도록이 ID를 저장해야합니다 (예 : 이미 등록 된 경우 onCreate () 확인). Google은 등록 ID를 주기적으로 새로 고침 할 수 있으므로 com.google.android.c2dm.intent.REGISTRATION 인 텐트가 여러 번 호출 될 수 있음을 이해하고 Android 애플리케이션을 설계해야합니다. Android 애플리케이션은 그에 따라 응답 할 수 있어야합니다.

다음 코드를 사용하여 장치를 등록합니다.

GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String regID = gcm.register(senderID);

GoogleCloudMessaging 클래스는 등록 프로세스를 캡슐화합니다. 그렇다면 GoogleCloudMessaging 클래스에 의해 내부적으로 처리되므로 com.google.android.c2dm.intent.REGISTRATION을 어떻게 처리한다고 가정합니까?



답변

흥미로운 질문입니다.

새 등록 절차로 전환하는 것이 좋습니다.

휴대 기기에서 실행되는 Android 애플리케이션은 GoogleCloudMessaging 메소드 register (senderID …)를 호출하여 메시지를 수신하도록 등록합니다. 이 메소드는 GCM 용 애플리케이션을 등록하고 등록 ID를 반환합니다. 이 간소화 된 접근 방식은 이전 GCM 등록 프로세스를 대체합니다.

라는 메모 Google may periodically refresh the registration ID는 이전 등록 프로세스를 보여주는 페이지에만 표시되므로이 메모가 더 이상 관련이 없을 수 있습니다.

안전을 원하면 이전 등록 프로세스를 계속 사용할 수 있습니다. 또는 새로운 프로세스를 사용할 수 있지만 com.google.android.c2dm.intent.REGISTRATIONGoogle이 등록 ID를 새로 고치기로 결정한 경우 보장되도록 인 텐트 를 처리하는 코드를 추가 할 수 있습니다 .

즉, 이러한 새로 고침을 경험 한 적이 없으며 등록 ID가 변경된 경우 (일반적으로 앱을 제거했다가 다시 설치 한 후 알림을 보낸 결과)에도 이전 등록 ID는 그대로 유지됩니다. (결과적으로 Google의 응답으로 전송 된 정식 등록 ID가 됨) 아무런 문제가 없었습니다.

수정 (2013 년 6 월 6 일) :

Google 은 새 인터페이스를 사용 하도록 데모 앱 을 변경했습니다 . 앱에서 로컬로 유지하는 값에 만료 날짜를 설정하여 등록 ID를 새로 고칩니다. 앱이 시작되면 로컬에 저장된 등록 ID를로드합니다. “만료”된 경우 (데모에서는 7 일 전에 GCM에서 수신했음을 의미 함) gcm.register(senderID)다시 전화를 겁니다 .

오랫동안 실행되지 않은 앱에 대해 Google에서 등록 ID를 새로 고치는 가상 시나리오는 처리하지 않습니다. 이 경우 앱은 변경 사항을 인식하지 못하며 타사 서버도 인식하지 못합니다.

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

수정 (2013 년 8 월 14 일) :

Google은 데모 앱을 다시 변경했습니다 (2 일 전). 이번에는 등록 ID가 7 일 후에 만료되는 것으로 간주하는 논리를 제거했습니다. 이제는 새 버전의 앱이 설치 될 때만 등록 ID를 새로 고칩니다.

수정 (2014.04.24) :

완전성을 위해 GCM 개발에 참여한 Google 개발자 인 Costin Manolache ( 여기 에서 가져옴)가이 문제에 대해 다음과 같이 말합니다 .

‘정기적’새로 고침은 발생하지 않았으며 등록 새로 고침은 새 GCM 라이브러리에 포함되지 않습니다.

등록 ID 변경의 유일한 알려진 원인은 업그레이드하는 동안 메시지를 받으면 앱이 자동으로 등록 취소되는 오래된 버그입니다. 이 버그가 수정 될 때까지 앱은 업그레이드 후에도 register ()를 호출해야하며 지금까지이 경우 등록 ID가 변경 될 수 있습니다. unregister ()를 명시 적으로 호출하면 일반적으로 등록 ID도 변경됩니다.

제안 / 해결 방법은 예를 들어 공유 기본 설정으로 저장된 자신의 임의 식별자를 생성하는 것입니다. 각 앱 업그레이드에서 식별자와 잠재적으로 새로운 등록 ID를 업로드 할 수 있습니다. 이것은 또한 서버 측에서 업그레이드 및 등록 변경을 추적하고 디버깅하는 데 도움이 될 수 있습니다.

이것은 공식 GCM 데모 애플리케이션의 현재 구현을 설명합니다.
등록하기 com.google.android.c2dm.intent.REGISTRATION위해 GoogleCloudMessaging클래스를 사용할 때 처리해서는 안됩니다 .


답변

새 InstanceID API를 읽고 토큰이 언제 변경 될 수 있는지에 대한 자세한 정보를 찾았습니다.

앱은 getToken () 메서드를 사용하여 필요에 따라 인스턴스 ID 서비스에서 토큰을 요청할 수 있으며 InstanceID와 마찬가지로 앱도 자체 서버에 토큰을 저장할 수 있습니다. 앱에 발급 된 모든 토큰은 앱의 InstanceID에 속합니다.

토큰은 고유하고 안전하지만 보안 문제가 발생하거나 사용자가 기기를 복원하는 동안 앱을 제거하고 다시 설치할 때 앱 또는 인스턴스 ID 서비스
가 토큰을 새로 고침해야 할 수 있습니다 . 앱은 인스턴스 ID 서비스의 토큰 새로 고침 요청에 응답하기 위해 리스너를 구현해야합니다.

자세한 내용은:

인스턴스 ID 서비스는 주기적으로 (예 : 6 개월마다) 콜백을 시작하여 앱에서 토큰을 새로 고치도록 요청합니다. 또한 다음과 같은 경우 콜백을 시작할 수 있습니다.

  • 보안 문제가 있습니다. 예 : SSL 또는 플랫폼 문제.
  • 장치 정보가 더 이상 유효하지 않습니다. 예를 들어, 백업 및 복원.
  • 그렇지 않으면 인스턴스 ID 서비스가 영향을받습니다.

출처 :

https://developers.google.com/instance-id/

https://developers.google.com/instance-id/guides/android-implementation


답변

SO를 포함하여 인터넷을 통해 오해의 소지가있는 수많은 답변을 살펴본 후 완전한 답변을 찾은 유일한 곳은 Eran의 답변과 여기에 언급 된 것뿐입니다 .

자동 등록 새로 고침이 발생하거나 발생하지 않았을 수도 있지만 Google은 성공적인 응답을 구문 분석하여 canocical_ids를 처리하는 간단한 알고리즘을 설명합니다.

If the value of failure and canonical_ids is 0, it's not necessary to parse the remainder of the response. Otherwise, we recommend that you iterate through the results field and do the following for each object in that list:

If message_id is set, check for registration_id:
If registration_id is set, replace the original ID with the new value (canonical ID) in your server database. Note that the original ID is not part of the result, so you need to obtain it from the list of code>registration_ids passed in the request (using the same index).
Otherwise, get the value of error:
If it is Unavailable, you could retry to send it in another request.
If it is NotRegistered, you should remove the registration ID from your server database because the application was uninstalled from the device or it does not have a broadcast receiver configured to receive com.google.android.c2dm.intent.RECEIVE intents.
Otherwise, there is something wrong in the registration ID passed in the request; it is probably a non-recoverable error that will also require removing the registration from the server database. See Interpreting an error response for all possible error values.

앞서 언급 한 링크에서.


답변