2

実稼働アプリと並行してインストールできるアプリのカスタム ビルドを作成しようとしています。

この回答に従って AAPT を使用してマニフェストを再パッケージ化することにより、カスタム ステージング バージョンを並べてインストールすることに成功しました。私の問題は、両方のアプリで GCM を機能させることです。

を呼び出しますGCMRegistrar.registerが、アプリのステージング バージョンへの応答が得られないようです (GCM 通知は、アプリの製品版でも正常に機能します)。

Google Play 開発者アカウントで新しいドラフト アプリを作成し (アプリ内課金をテストしたいので、Google Play でアプリをドラフトとしてホストする必要があります)、Google API コンソールでステージング アプリ用の新しいプロジェクトを作成しました。 .

使用しようとしているドメインは次のようになります。

  • プロダクション = 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>のエラーを回避するために、タグには新しいパッケージ名が必要なようです。

main<manifest>タグは元のパッケージ名を保持する必要があります。そうしないと、アプリがクラッシュします。これは、再パッケージ化がインストール時に動的に行われるように見えるためです (つまり、再パッケージ化後にアプリを逆コンパイルすると、このパッケージ名が変更されていないことがわかります)。そのため、パッケージ名のこのインスタンスを変更しないでください。

最終的<receiver>に元の名前にするか、再パッケージ化した名前にするかはわかりませんが、両方を試しましたが、どちらも機能していないようです.

Google API コンソールからの API アクセス情報は次のとおりです。

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

どちらも「ブラウザアプリのキー(リファラーあり)」も持っています。

「Androidアプリのキー」が実際に必要かどうかはわかりませんが、GCMのドキュメントではそれを理解するのが少し難しくなっています.

誰かアイデアはありますか?「Android アプリのキー」が問題の原因なのか、それともステージング アプリが本番アプリのサブドメインであるという事実なのかと思っていました。

もう 1 つの複雑な問題は、Google API コンソールからの変更が反映されるまでにどれくらいの時間がかかるかということです。

4

2 に答える 2

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>

別の問題は、インテント サービスである可能性があります。を拡張するサービス クラスを使用している場合、 はアプリのメイン パッケージでこのクラスGCMBaseIntentServiceGCMBroadCastReceiver検索するため、別のパッケージ名を持つステージング バージョンではそれが見つかりません。

この場合の解決策は、サブクラスを使用してGCMBroadCastReceiver、サービス クラスのパスを指定するメソッドをオーバーライドすることです。

ここでの私の答えはあなたの問題に関連しています。

于 2013-06-28T19:11:49.123 に答える
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;
    }
}
于 2013-06-28T23:57:25.533 に答える