5

アプリケーションに gcm 通知を実装しています。コードを使用してさまざまなパッケージ名で多くのアプリケーションを生成するため、標準の mypackage.GCMIntentService 名を使用できません。アプリケーションを生成するときは、マニフェストでのみ変更を行い、R クラスのインポートを変更します。だから私は自分のBroadcastReceiverを推進しました

public class GCMReceiver extends GCMBroadcastReceiver {
  @Override
  protected String getGCMIntentServiceClassName(Context context) {
    return GCMIntentService.class.getName();
  }
}

パッケージ名に関係なく GCMIntentService の名前を返します。

これが私のマニフェストです:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

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

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


    <service
        android:name="org.rferl.service.GCMIntentService"
        android:enabled="true" />


   <receiver
        android:name="org.rferl.GCMReceiver"
        android:enabled="true"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>

            <!-- Receives the actual messages. -->
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <!-- Receives the registration id. -->
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

            <category android:name="org.rferl" />
        </intent-filter>
    </receiver>

すべて正常に動作し、登録、登録解除、メッセージの受信ができます。ただし、アプリケーションが実行されていない場合、GCMIntentService.onMessage は呼び出されません。マニフェストに何か不足していますか? システムがサービスを開始しなかったのはなぜですか?

4

4 に答える 4

15

GCMIntentServiceapplication/ / GCMBroadcastReceiverfor Android GCMのパッケージ/クラス名を変更するには (Eclipse ADT を使用)

:次の変更を行う前に、GCM を介してメッセージを受信できることを確認することをお勧めします。アプリケーションのデフォルトのパッケージ名を使用して Android アプリに GCM を実装するには、 GCM: Getting Started を参照してください。


パッケージ名

アプリのパッケージ名を変更するには (例: new package name = com.example.newpackage)、

  • パッケージ エクスプローラーで、プロジェクトを右クリック → Android ツール → アプリケーション パッケージの名前を変更します。
    これにより、パッケージ名が自動的かつ便利に更新されます。
  • で、およびAndroidManifest.xmlのパッケージ名を更新します。permissionuses-permissionC2D_MESSAGE

    <permission android:name="com.example.newpackage.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="com.example.newpackage.permission.C2D_MESSAGE" />
    
  • AndroidManifest.xml、 のパッケージ名を更新しcategoryますreceiver

    <receiver
        android:name="com.example.oldpackage.GCMBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND" >  <!-- Not this one!! -->
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
    
            <category android:name="com.example.newpackage" />  <!-- This one!! -->
        </intent-filter>
    </receiver>
    

の名前GCMIntentService

アプリのパッケージ名が の場合、を呼び出す必要がありcom.example.newpackageます。そうでない場合は、GCMIntentServicecom.example.newpackage.GCMIntentService

  • extends GCMBroadcastReceiverオーバーライドする新しいクラスを作成しますgetGCMIntentServiceClassName()

    public class MyBroadcastReceiver extends GCMBroadcastReceiver
    {
        @Override
        protected String getGCMIntentServiceClassName(Context context)
        {
            return MyIntentService.class.getName(); // Don't hard-code like "com.example.oldpackage.MyIntentService", see http://stackoverflow.com/a/936696/1402846
        }
    }
    

    これは、GCMBroadcastReceiver に関する Google のドキュメントに基づいています。

    デフォルトでは、GCMBaseIntentServiceクラスはアプリケーションのメイン パッケージに属し、名前はDEFAULT_INTENT_SERVICE_CLASS_NAME. 新しいクラスを使用するには、 をgetGCMIntentServiceClassName(Context)オーバーライドする必要があります。

  • で、次AndroidManifest.xmlの名前を更新しreceiverます。

    <receiver
        android:name="com.example.oldpackage.MyBroadcastReceiver"
        ... >
    </receiver>
    
  • で、次AndroidManifest.xmlの名前を更新しserviceます。

    <service android:name="com.example.oldpackage.MyIntentService" />
    

の名前GCMBroadcastReceiver

のパッケージ/クラス名を変更した場合GCMBroadcastReceiver:

  • で、次AndroidManifest.xmlの名前を更新しreceiverます。

    <receiver
        android:name="com.example.oldpackage.NewBroadcastReceiver"
        ... >
    </receiver>
    

トラブルシューティング

  • AndroidManifest.xmlで、パッケージ名が少なくとも 4 回表示されることを確認します。

    • manifest

      <manifest ...
          package="com.example.newpackage" ...
      
    • permission

      <permission android:name="com.example.newpackage.permission.C2D_MESSAGE" android:protectionLevel="signature" />
      
    • uses-permission

      <uses-permission android:name="com.example.newpackage.permission.C2D_MESSAGE" />
      
    • In categorywithin intent-filterwithin receiverGCM ブロードキャスト レシーバの場合:

      <category android:name="com.example.newpackage" />
      
  • パッケージ名を変更した場合は、テストする前にデバイス/エミュレーターで古いアプリをアンインストールしてください。

  • パッケージ名を変更した場合は、登録 ID ( で受け取るonRegistered()) が変更されていることに注意してください。
  • で登録 ID を受け取った場合は、LogCat (タグ)に次onRegistered()のように表示されます。GCMBroadcastReceiver

    GCMBroadcastReceiver        onReceive: com.google.android.c2dm.intent.REGISTRATION
    GCMBroadcastReceiver        GCM IntentService class: com.example.oldpackage.MyIntentService
    

    インテント サービスのパッケージ/クラス名が正しいことを確認します。

  • getGCMIntentServiceClassName(Context)独自のでオーバーライドすると、LogCat (タグ)に次GCMBroadcastReceiverのように表示されます。GCMRegistrar

    GCMRegistrar        Setting the name of retry receiver class to com.example.oldpackage.MyBroadcastReceiver
    

    ブロードキャスト レシーバのパッケージ/クラス名が正しいことを確認します。

  • サーバーから GCM サーバーにメッセージが送信されたら、HTTP ステータス コードと HTTP 応答でエラーを確認します。
  • そして、あなたが絶望的な場合:
    • LogCat でエラーを確認します。
    • デバイス/エミュレーターを再起動してみてください。
    • デバイス/エミュレーターでアプリをアンインストールしてみてください。
    • Eclipse を再起動してみてください。
    • プロジェクトをきれいにして再構築してみてください。
    • ADT を更新してみてください (プルダウン メニュー → ウィンドウ → Android SDK Manager → インストール パッケージ)。
    • Eclipse を更新してみてください (プルダウン メニュー → ヘルプ → 更新プログラムの確認)。
    • コンピュータを再起動してみてください。
    • ぐっすり眠るか、祈りましょう。
于 2013-01-20T12:29:18.757 に答える
2

コードを使用してさまざまなパッケージ名で多くのアプリケーションを生成するため、標準の mypackage.GCMIntentService 名を使用できません。

ランタイムまたはビルド時のソリューションを要求するかどうかはわかりません。他の答えはランタイムソリューションなので、ビルド時に可能性に関する情報を追加すると思いました。


AndroidManifest では、ルート要素の属性で$PACKAGE_NAME指定したパッケージ名を参照する変数 (デフォルトで使用可能) を使用できます。packagemanifest

このpackage属性の値は、ハードコードされた文字列である必要はありませんが、次のようにリソース参照を介して動的に設定することもできます:

<manifest package="@string/app_package" ...>
    ...
    <service
        android:name="$PACKAGE_NAME.service.GCMIntentService"
        android:enabled="true" />
    ...
</manifest>

Note.serviceは、これらをどのように指定するかを示すために含めた単なるサブパッケージです。もちろん、このソリューションは、アプリケーションがサービス クラスを.serviceサブパッケージに入れるなどの一般的な規則に従っている場合にのみ機能します。

また、実際にはルート パッケージを完全にオフにしておくことができることに注意してください。Android によって拡張されます。

<manifest package="@string/app_package" ...>
    ...
    <service
        android:name=".service.GCMIntentService"
        android:enabled="true" />
    ...
</manifest>

実際には、上記と同じです。

AndroidManifest (または別のファイル) の値をより柔軟に置き換える方法を探している場合は、Ant Replace タスク ( http://ant.apache.org/manual/Tasks/replace. html ) またはMaven を使用したリソース フィルタリング ( http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html )。

于 2013-07-31T20:22:18.617 に答える
2

GCMIntentService クラスをルート アプリケーション パッケージに配置する必要があります。ここで org.rferl

<service
    android:name=".GCMIntentService"
    android:enabled="true" />

と受信機

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

                <!-- Receives the actual messages. -->
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <!-- Receives the registration id. -->
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

                <category android:name="com.EgoSecure.ma" />
            </intent-filter>
        </receiver>
于 2012-08-23T11:34:50.193 に答える
0

gcm ブロードキャスト レシーバー (GCMBroadcastReceiver.class) は、アプリケーションのルート ディレクトリからインテント サービス クラス (GCMIntentService.class) を呼び出します。現在、「org.rferl.service.GCMIntentService」は使用できません。GCMIntentService クラスの名前を返す GCMBroadcastReceiver の getGCMIntentServiceClassName メソッドをオーバーライドする必要があります。やり方はこちら

于 2012-08-26T11:35:05.603 に答える