2

Я пытаюсь создать пользовательскую сборку моего приложения, которую я могу установить бок о бок с моим производственным приложением.Регистрация GCM после неудачной переупаковки

Я успешно получил свою собственную промежуточную версию, чтобы установить бок о бок, переупаковывая манифест с помощью AAPT согласно this answer. Моя проблема заключается в получении GCM для работы в обоих приложениях.

Я звоню GCMRegistrar.register, но я никогда не получаю ответа на промежуточную версию приложения (уведомления GCM все еще отлично работают для производственной версии приложения).

Я создал новое приложение для проектов в своей учетной записи разработчика Google Play (я хочу протестировать биллинг в приложении, поэтому вам нужно разместить приложение в виде черновика в Google Play) и новый проект в моей консоли API Google для промежуточного приложения.

Домены Я пытаюсь использовать выглядеть следующим образом:

  • производство = com.mydomain.myapp
  • постановка = com.mydomain.myapp.staging

Первая проблема Я ударил, что AAPT не изменяет разрешения GCM, так GCM потерпит неудачу с:

Application does not define permission com.mydomain.myapp.staging.permission.C2D_MESSAGE 

Я добавлен шаг пользовательской сборки для дальнейшего обновления моего AndroidManifest.xml. Вот соответствующие разделы в настоящее время:

<manifest 
    ... 
    package="com.mydomain.myapp"> 

    <permission 
     android:name="com.mydomain.myapp.staging.permission.C2D_MESSAGE" 
     android:protectionLevel="signature" /> 

    <uses-permission android:name="com.mydomain.myapp.staging.permission.C2D_MESSAGE" /> 

    <permission 
     android:name="com.mydomain.myapp.staging.MESSAGING_PERMISSION" 
     android:label="Blah" 
     android:protectionLevel="normal" > 
    </permission> 

    <receiver 
     android:name="com.google.android.gcm.GCMBroadcastReceiver" 
     android:permission="com.google.android.c2dm.permission.SEND" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
      <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 

      <category android:name="com.mydomain.myapp" /> 
     </intent-filter> 
    </receiver> 

<permission> В тегах, кажется, требует нового имени пакета, чтобы избежать ошибок, я уже упоминал выше.

Основной тег <manifest> должен содержать исходное имя пакета, иначе приложение сработает. Это связано с тем, что переупаковка, кажется, происходит динамически в точке установки (т. Е. Если вы декомпилируете свое приложение после переупаковки, вы увидите, что это имя пакета не изменилось), поэтому вы не должны изменять этот экземпляр имени пакета.

Я не уверен, что окончательный <receiver> должен быть оригинальным или переупакованным именем, но я пробовал оба, и ни один из них не работает.

Здесь информация Доступ к API из консоли API Google:

STAGING 
Key for Android apps (with certificates) 
API key: <key> 
Android apps: <SHA1>;com.mydomain.myapp.staging 

PRODUCTION 
Key for Android apps (with certificates) 
API key: <key> 
Android apps: <SHA1>;com.mydomain 

Оба также имеют "Ключ для браузерных приложений (с Referers)".

Я не уверен, что на самом деле требуется «Ключ для Android-приложений», но the GCM docs сделать это немного сложно понять.

У кого-нибудь есть идеи? Мне было интересно, вызывает ли проблема «ключ для приложений для Android», или, возможно, тот факт, что мое промежуточное приложение является субдоменом производственного приложения.

Еще одно осложнение заключается в том, как долго он переносит изменения из Консоли API Google для распространения - знает ли кто-нибудь, как долго мне нужно ждать до повторного тестирования, чтобы убедиться, что изменения на месте?

ответ

2

Я не уверен, как работает AAPT, но я знаю, как манифест должен быть определен для GCM.

Все указанные ниже места с PACKAGE должны содержать одно и то же название упаковки.

<manifest 
    ... 
    package="PACKAGE"> 

<permission 
    android:name="PACKAGE.permission.C2D_MESSAGE" 
    android:protectionLevel="signature" /> 

<uses-permission android:name="PACKAGE.permission.C2D_MESSAGE" /> 

<receiver 
    android:name="com.google.android.gcm.GCMBroadcastReceiver" 
    android:permission="com.google.android.c2dm.permission.SEND" > 
    <intent-filter> 
     <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
     <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 

     <category android:name="PACKAGE" /> 
    </intent-filter> 
</receiver> 

Другой проблемой может быть ваше намерение службы. Если вы используете класс обслуживания, который расширяет GCMBaseIntentService, GCMBroadCastReceiver ищет этот класс в основном пакете приложения, поэтому в вашей промежуточной версии, которая имеет другое имя пакета, она не найдет ее.

Решение в этом случае должно использовать подкласс класса GCMBroadCastReceiver и переопределить метод, указывающий путь вашего класса обслуживания.

Мой ответ here связан с вашей проблемой.

+0

Благодаря Эран - создание подкласс GCMBroadCastReceiver исправили проблему! Я опубликовал свою конфигурацию в отдельном ответе, так как манифест выглядит несколько иначе, если вы используете AAPT для его переупаковки. –

+0

Рад, что я мог бы помочь :) – Eran

0

Благодаря @Eran за его ответ! Если это помогает другим, я перечислил свою рабочую конфигурацию ниже (после выполнения моих собственных шагов сборки).

Название пакета в теге <manifest> по-прежнему должно содержать исходное имя пакета, но для всех остальных экземпляров необходимо использовать переупакованное имя.

AndroidManifest.xml:

<manifest 
    ... 
    package="ORIGINAL_PACKAGE_NAME"> 

    <permission 
     android:name="NEW_PACKAGE_NAME.permission.C2D_MESSAGE" 
     android:protectionLevel="signature" /> 

    <uses-permission android:name="NEW_PACKAGE_NAME.permission.C2D_MESSAGE" /> 

    <permission 
     android:name="NEW_PACKAGE_NAME.MESSAGING_PERMISSION" 
     android:label="Blah" 
     android:protectionLevel="normal" > 
    </permission> 

    <service android:name=".MyGCMIntentService" /> 

    <receiver 
     android:name=".MyGCMBroadcastReceiver" 
     android:permission="com.google.android.c2dm.permission.SEND" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
      <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 

      <category android:name="NEW_PACKAGE_NAME" /> 
     </intent-filter> 
    </receiver> 

Пользовательские GCMBroadcastReceiver:

public class MyGCMBroadcastReceiver extends GCMBroadcastReceiver { 

    public MyGCMBroadcastReceiver() { 
     super(); 
     Log.d("Creating MyGCMBroadcastReceiver"); 
    } 

    @Override 
    protected String getGCMIntentServiceClassName(Context context) { 
     String className = MyGCMIntentService.class.getName(); 
     Log.i("getGCMIntentServiceClassName", className); 
     return className; 
    } 
}