GCM not registering when changing package name wit

2019-02-20 20:04发布

问题:

In my regular build gcm works fine, but when I use flavors to change the com name things stop working. My IntentService is never being initialized. How should I set up my manifest files so that this happens?

  • I have added them to the developer console.
  • I am using gradle com.android.tools.build:gradle:0.11.+'

I get the logs

V/GCMBroadcastReceiver﹕ onReceive: com.google.android.c2dm.intent.REGISTRATION
V/GCMBroadcastReceiver﹕ GCM IntentService class: com.sample.app.dev.GCMIntentService
V/GCMBaseIntentService﹕ Acquiring wakelock

and then nothing. My custom IntentService class never gets initialized and my registrationId stays empty. My current implementation is similar to the one here: https://stackoverflow.com/a/20334397/198034

How should I set up my manifest to get gradle 0.11.+ flavors to work with gcm?

Below is a manifest in one of my flavors, I have more code in the main manifest (all needed permissions, etc), but nothing else dealing with gcm.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.sample.app"
    android:versionCode="45"
    android:versionName="0.6.5" >

    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />


    <permission android:name="com.sample.app.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.sample.app.permission.C2D_MESSAGE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name" >


        <service android:name=".GCMIntentService" />
        <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="${packageName}" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

回答1:

This was my solution:

<permission android:name="com.sample.app.permission.C2D_MESSAGE"
     android:protectionLevel="signature" />
 <uses-permission android:name="com.sample.app.permission.C2D_MESSAGE" />

...

<service android:name=".GCMIntentService" />
    <receiver
        android:name=".MyBroadcastReceiver"
        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.sample.app" />
        </intent-filter>
    </receiver>

in my manifest and mybroadcastReceiver

...

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


回答2:

From your manifest it looks like your app's package name is com.sample.app, which is consistent with your permission.C2D_MESSAGE definition. Your receiver's intent filter's category says ${packageName}. Hopefully that gets translated to com.sample.app too, as it should.

Other than that, your log posted above shows that your intent service is expected to be at com.sample.app.dev.GCMIntentService. That's a different package.

You seem to be using the old deprecated GCM client library, in which com.google.android.gcm.GCMBroadcastReceiver expects the intent service to be called GCMIntentService and be located in the main package of the app :

/**
 * Gets the default class name of the intent service that will handle GCM
 * messages.
 */
static final String getDefaultIntentServiceClassName(Context context) {
    String className = context.getPackageName() +
            DEFAULT_INTENT_SERVICE_CLASS_NAME;
    return className;
}

Your manifest declares the intent service class to be in the main package of your app :

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

All these things don't add up. Either your app's package name is com.sample.app.dev or com.sample.app. If it's the former, the manifest you posted is incorrect. If it's the latter, there is no reason for the broadcast receiver to expect the intent service class to be com.sample.app.dev.GCMIntentService.