2012-03-20 2 views
1

Я написал приложение, которое использует C2DM. Я могу регистрировать устройства и отправлять сообщения в порядке, однако я получаю устройства, которые неожиданно незарегистрированы, и поэтому перестают получать сообщения. Я думал, что смогу справиться с этим кодом ниже, но похоже, что «незарегистрированные» намерения не получены (это не подтверждено, но устройство не перерегистрировано).c2dm устройство незарегистрировано автоматически

Мои вопросы: это нормально, если устройства незарегистрированы из-под синего? Если это сообщение «отменить», отправленное на устройство? Как вы можете справиться с этим, не прерывая обслуживание? Другие испытывают это также? Я мог бы справиться с этим, когда пользователь нажал кнопку в приложении для повторной регистрации, но я не хочу этого делать, если только не придется. Также рассмотрели вопрос о сохранении статуса устройств (зарегистрированных, незарегистрированных) на сервере, а затем периодически проверяйте приложение, чтобы узнать, все еще зарегистрировано устройство.

Любая помощь будет оценена!

public class MyC2dmReceiver extends BroadcastReceiver { 
private static String KEY = "c2dmPref"; 
private static String REGISTRATION_KEY = "registrationKey"; 
SharedPreferences prefs; 

private Context context; 

@Override 
public void onReceive(Context context, Intent intent) { 
    this.context = context; 
    if (intent.getAction().equals(
      "com.google.android.c2dm.intent.REGISTRATION")) { 
     handleRegistration(context, intent); 
    } else if (intent.getAction().equals(
      "com.google.android.c2dm.intent.RECEIVE")) { 
     handleMessage(context, intent); 
    } 
} 

private void handleRegistration(Context context, Intent intent) { 
    final SharedPreferences sharedPrefs = Util.getSharedPreferences(this.context); 
    String email = sharedPrefs.getString(Util.ACCOUNT_NAME, "");// 

    prefs = context.getSharedPreferences(KEY, Context.MODE_PRIVATE); 
    //String email = prefs.getString("email_for_c2dm", "");// 
    String registration = intent.getStringExtra("registration_id"); 
    if (intent.getStringExtra("error") != null) { 
     // Registration failed, should try again later. 
     Log.d("c2dm", "registration failed"); 
     String error = intent.getStringExtra("error"); 
     if (error == "SERVICE_NOT_AVAILABLE") { 
      Log.d("c2dm", "SERVICE_NOT_AVAILABLE"); 
     } else if (error == "ACCOUNT_MISSING") { 
      Log.d("c2dm", "ACCOUNT_MISSING"); 
     } else if (error == "AUTHENTICATION_FAILED") { 
      Log.d("c2dm", "AUTHENTICATION_FAILED"); 
     } else if (error == "TOO_MANY_REGISTRATIONS") { 
      Log.d("c2dm", "TOO_MANY_REGISTRATIONS"); 
     } else if (error == "INVALID_SENDER") { 
      Log.d("c2dm", "INVALID_SENDER"); 
     } else if (error == "PHONE_REGISTRATION_ERROR") { 
      Log.d("c2dm", "PHONE_REGISTRATION_ERROR"); 
     } 
} else if (intent.getStringExtra("unregistered") != null) { 
     // unregistration done, new messages from the authorized sender will 
     // be rejected 
     Log.d("c2dm", "unregistered"); 
     SharedPreferences c2dmPrefs=context.getSharedPreferences(KEY,  Context.MODE_PRIVATE); 
     c2dmPrefs.edit().putString("registrationKey", ""); 
     c2dmPrefs.edit().commit(); 
        //RegisterDevice launches the registration intent to get a new regKey 
     RegisterDevice register=new  RegisterDevice(FirefighterLog.getInstance()); 
} else if (registration != null) { 
     Log.d("c2dm", registration); 
     updateServerRegId(registration)) //sends regID to server and stores 
      Editor editor = context.getSharedPreferences(KEY, 
        Context.MODE_PRIVATE).edit(); 
      editor.putString(REGISTRATION_KEY, registration); 
      editor.commit(); 
      Toast.makeText(context, "Device registered successfully", 
        Toast.LENGTH_LONG); 
     } 

ПРИМЕЧАНИЕ: updateServerRegId() посылает новый RegID к серверу и переписывает, если он уже существует. Я использую RequestFactory и отправляю его как объект для приложения.

Android Manifest:

<uses-permission android:name="com.xxx.someapp.permission.C2D_MESSAGE" /> 
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> 
    <permission android:name="com.xxx.someapp.permission.C2D_MESSAGE" 
       android:protectionLevel="signature" /> 

    <receiver android:name=".C2DM.MyC2dmReceiver"  android:permission="com.google.android.c2dm.permission.SEND"> 
     <!-- Receive the actual message --> 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
      <category android:name="com.xxx.someapp" /> 
     </intent-filter> 
     <!-- Receive the registration id --> 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 
      <category android:name="com.xxx.someapp" /> 
     </intent-filter> 
    </receiver> 
+0

Как скоро после первоначальной регистрации происходят эти «нерегистрации»? Часы, дни, недели? – Squonk

+0

Можете ли вы опубликовать свой манифест Android, где определен приемник C2DM? –

+0

@MisterSquonk Время, похоже, меняется, но обычно недели. У меня не было достаточно тестирования, чтобы точно знать. – Patrick

ответ

2

Может ли это быть просто случай Google обновив регистрационный номер? Из C2DM Документами Lifecycle Flow в Благоприятная C2DM секции ...

...

2.Если регистрация прошла успешно, сервер C2DM транслирует Intent РЕГИСТРАЦИИ, который дает приложению регистрацию Я БЫ.

Приложение должно сохранить этот идентификатор для последующего использования. Обратите внимание, что Google может периодически обновлять регистрационный идентификатор, поэтому вы должны проектировать свое приложение с пониманием того, что намерение РЕГИСТРАЦИЯ может быть вызвано несколько раз. Ваше приложение должно быть в состоянии ответить соответствующим образом.

...

Регистрация ID продолжается, пока приложение явно не отменяет регистрацию себя, или пока Google не обновит регистрационный номер для вашего приложения.

Там нет ничего в документации, которая гласит, что Intent с «разрегистрировать» экстра будет отправлен в результате перерегистрации. Единственное время, о котором упоминалось, - это когда приложение явно не регистрирует себя.

При взгляде на ваш код это кажется неполным - неясно, как вы обрабатываете регистрацию или возможность перерегистрации (когда Google обновляет регистрационный идентификатор, например).

В своем ответе на мой комментарий по вашему вопросу вы говорите, что это «обычно недели». Если бы вы сказали часы (или, возможно, даже дни), я, вероятно, отклонил бы идею о том, что перерегистрация вызывает проблему. Однако неделям, кажется, совершенно разумный период времени, чтобы Google обновил идентификатор регистрации.

Просто мысль.

EDIT: Ну до тех пор, пока вы счастливы, что updateServerRegId() работает правильно и обновление с новым registration_id (если необходимо), то я не могу видеть многое другое, чтобы указать пальцем на.

Я все еще удивляюсь, если это случай сохранения недействительного (истекшего) регистрационного удостоверения. Просто посмотрите на документы далее ...

Приложение принимает широковещательную передачу РЕГИСТРАЦИИ, когда сервер приложений пытается отправить ему сообщение. Но регистрационные идентификаторы могут быть несуществующими или недействительными по целому ряду причин:

  • Если приложение работает в первый раз, он еще не имеет регистрационного удостоверения.
  • Если приложение не зарегистрировано, оно не имеет идентификатора регистрации.
  • Сервер C2DM периодически обновляет регистрационные идентификаторы.

Предполагая, что первые два не применяются, это оставляет только последние.

В своем первоначальном вопросе вы говорите, что «я получаю устройства, которые неожиданно незарегистрированы и поэтому перестают получать сообщения». Просмотрели ли вы возможные коды ошибок в ответе 200 при отправке сообщений на эти устройства? Посмотрите на код кода ответа How the Application Server Sends Messages, это может дать вам лучшее представление о том, что происходит.

Кстати, один, возможно, не связанные вещи (но я думал, что я бы упомянуть об этом) ...

if (error == "SERVICE_NOT_AVAILABLE") 

... не сравнить Strings с помощью ==, всегда используйте .equals(...). Если вы получаете ошибки на этом пути, сравнение строк ошибок таким образом не сработает, и вы можете что-то упустить.

+0

Хорошо, спасибо, что разместили этот текст. Я помнил, как читал эти строки. Это похоже на то, что происходит, однако, как мое приложение написано, оно должно быть зарегистрировано снова, когда оно обновляется. Я напишу больше кода, который показывает, как я обрабатываю намерение регистрации. – Patrick

+0

Посмотрев на источник ChromeToPhone, я задаюсь вопросом, может ли мне понадобиться wakelock. ChromeToPhone использует один на своем приемнике. В моем приложении первоначальная регистрация происходит, когда пользователь использует приложение. Когда произойдет обновление, телефон, скорее всего, будет спать, и, возможно, ресивер будет убит до того, как идентификатор регистрации будет отправлен на мой сервер ... – Patrick

+0

Извините, я не знаю о wakelock, но я действительно надеюсь, что это wasn ' В этом случае я бы не хотел, чтобы мое приложение не позволяло телефонному телефону «бодрствовать» каким-либо образом просто на основании неопределенной возможности, что Google может обновить регистрационный идентификатор. Кроме того, «BroadcastReceivers», зарегистрированный в манифесте, не нуждается в том, чтобы телефон не проснулся, чтобы получать сообщения. Во всяком случае, извините, что у меня закончились идеи, хотя я отредактировал конец своего сообщения - не уверен, что это поможет, хотя обратите внимание на бит о сравнении строк с '=='. Удачи. – Squonk

Смежные вопросы