41

I'm receiving that error from Android Studio's Android Monitor. This error appears when I send a push notification through GCM, in a real device, and the app has not been started yet or has been forced to stop. Yesterday all works fine, today is not working at all (works only if the app is running in background or foreground).

I think this may be an AndroidManifest error, but I'm tired of looking for the problem and can not find anything.

Manifest

<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.flagg327.guicomaipu">

    ...

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        ...

        <!--GOOGLE CLOUD MESSAGE-->
        <receiver
            android:name="com.google.android.gms.gcm.GcmReceiver"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <!-- for Gingerbread GSF backward compat -->
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <category android:name="com.flagg327.guicomaipu" />
            </intent-filter>
        </receiver>

        <service
            android:name="com.flagg327.guicomaipu.gcm.RegistrationService"
            android:exported="false" />

        <service
            android:name="com.flagg327.guicomaipu.gcm.TokenRefreshListenerService"
        android:exported="false">
            <intent-filter>
                <action
                    android:name="com.google.android.gms.iid.InstanceID" />
            </intent-filter>
        </service>

        <service
            android:name="com.flagg327.guicomaipu.gcm.NotificacionsListenerService"
        android:exported="false" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </service>

    </aplication>

    <permission 
        android:name="com.flagg327.guicomaipu.C2D_MESSAGE"
            android:protectionLevel="signature" />
    <uses-permission android:name="com.flagg327.guicomaipu.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

TokenRefreshListenerService.java

The registration 'tokens' updates every day. It because that, each Android app that uses GCM must have an InstanceIDListenerService that manages those updates.

public class TokenRefreshListenerService extends InstanceIDListenerService{

    @Override
    public void onTokenRefresh() {
        // Launch the registration process.
        Intent i = new Intent(this, RegistrationService.class);
        startService(i);
    }
}

NotificacionsListenerService.java

GCM automatically shows up the push notifications, but only if the associated app has a GCMListenerService

public class NotificacionsListenerService extends GcmListenerService {

    @Override
    public void onMessageReceived(String from, Bundle data) {
        Log.d("A", "onMessageReceived()");

        // Do something

    }
}

RegistrationService.java

GCM identifies the Android devices using registration cards('tokens').My app should be able to register from each Android device on which it is installed.

public class RegistrationService extends IntentService {

    /**
     * Constructor
     */
    public RegistrationService() {
        super("RegistrationService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // Generate or download the registration 'token'.
        InstanceID myID = InstanceID.getInstance(this);

        String registrationToken = null;
        try {
            // Get the registration 'token'.
            registrationToken = myID.getToken(
                    getString(R.string.gcm_defaultSenderId),
                    GoogleCloudMessaging.INSTANCE_ID_SCOPE,
                    null
            );

            // Subscribe to a topic. The app is able now to receive notifications from this topic.
            GcmPubSub subscription = GcmPubSub.getInstance(this);
            subscription.subscribe(registrationToken, "/topics/guico_maipu_topic", null);
        } catch (IOException e) {
            e.printStackTrace();
        }

        Log.e("Registration Token", registrationToken);
    }
}

Error

This error appears when I send a push notification via python.

09-13 21:21:44.800 1851-1851/? W/GCM-DMM: broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.flagg327.guicomaipu (has extras) }

Yesterday was working... Any idea? Than you for your time.

Mr.Rebot
  • 6,703
  • 2
  • 16
  • 91
flagg327
  • 967
  • 1
  • 10
  • 21
  • Based from this [thread](https://groups.google.com/forum/#!msg/android-gcm/MqVlA3Sj26c/6O4TdU1pm0UJ), this issue occurs when the receiving app is in stopped state on the device (for example by using force stop from the settings). It will only start to receive messages again when it is manually started. You can also check this [related SO post](http://stackoverflow.com/questions/11902947/broadcast-intent-callback-result-cancelled-forintent). – abielita Sep 14 '16 at 15:47
  • Sloved check this ..https://stackoverflow.com/a/45810771/1993001 – Rahul Devanavar Aug 22 '17 at 12:25
  • [Here](https://stackoverflow.com/a/50238790/2835520) the are some steps which could help you. – IgniteCoders May 09 '18 at 17:39

10 Answers10

27

Since none of answers provide official link, I decided to ask firebase team and got official answer from them

It looks like you have an issue when your app is force stopped or killed. Actually, this is working as intended. The Android framework advises that apps that have been stopped (i.e. killed/force-stopped from Settings) should not be started without explicit user interaction. FCM follows this recommendation and thus its services will not start as well. This also means that messages will not be received (FirebaseMessagingService will not be called) when the app is in "killed" state. Here are some useful links so you could have a better understanding on this topic: https://developer.android.com/about/versions/android-3.1#launchcontrols https://github.com/firebase/quickstart-android/issues/368#issuecomment-343567506

In sum:

  • the app is killed by user (from settings/force stop) will be marked with a flag that won't able to auto trigger any service included firebase message service. This is not the same with the app is killed by the system or swipe from recent app.
  • However, on some ROMs from VIVO or ONEPLUS, swipe feature (click recent app button/swipe) is wrongly implemented to be similar with settings/force stop. That caused firebase message service is not able to start.
  • The issue has been raised here and in many places. The FCM team is aware of the issue and is working on it

NOTE: even the question is about GCM, but FCM throw exact the same error in the question title.

thanhbinh84
  • 17,876
  • 6
  • 62
  • 69
20

I got the same Error

09-13 21:21:44.800 1851-1851/? W/GCM-DMM: broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.XXX.XXX (has extras) }

after killing the app.

After some research I realized, that this is only a "Debug-Issue". A "signed APK" handles the broadcast correctly even if the app has been shut down.

Hope it helps!

niggeulimann
  • 688
  • 6
  • 15
16

After digging into why this happens, it appears that it happens if you kill the app from Android Studio.

If you open the app from the launcher and swipe it away, your app will still receive notifications.

(Tested on OnePlus One with FCM not GCM)

natanavra
  • 2,100
  • 3
  • 18
  • 24
7

So... I solved the problem. The problem was that the device is not registered to receive GCM if the app is force closed or if the app has never been opened since device boot. The solution is simple, register the device on phone boot. For this, I implemented a BroadcastReceiver and started a process registration inside it.

The modifications:

Added to AndroidManifest

    <receiver android:name="com.flagg327.guicomaipu.gcm.OnBootBroadcastReceiver">
        <intent-filter >
            <action android:name="android.intent.action.BOOT_COMPLETED" />

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

OnBootBroadcastReceiver.java

public class OnBootBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        Intent i = new Intent("com.flagg327.guicomaipu.gcm.RegistrationService");
        i.setClass(context, RegistrationService.class);
        context.startService(i);
    }
}

So, on boot, the device will register into the GCM server and going to be able to receive any push notification from my server. I hope it is useful.

buczek
  • 2,011
  • 7
  • 29
  • 40
flagg327
  • 967
  • 1
  • 10
  • 21
4

I also ran into this problem when installing my app on an emulator. I'm working with FCM data messages only, because i need to handle the messages on my own (to also have silent push).

But when i was testing background receiving nothing happend. And i also observed your error

09-13 21:21:44.800 1851-1851/? W/GCM-DMM: broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.flagg327.guicomaipu (has extras) }

I read a lot about that because i couldn't believe that FCM is not working when the app is killed, that would destroy the whole purpose of push notifications. And i also observed scenarios where my messages were received, even when the app was killed, but i had no clue why this was happening from time to time.

After reading through the firebase issues on github i stopped at a very remarkable answer:

After some testing it looks like that stopped=true is only the case when I've started the app with Android Studio. If I start the app manually or using adb shell am start -n and then kill it (swipe from recents) then the state is stopped=false and push notifications work just fine!

https://github.com/firebase/quickstart-android/issues/822#issuecomment-611567389

So when you're still facing this issue try the following:

  1. Install app via Android Studio
  2. Close and kill the app (after that no messages are received, observed error occurs)
  3. Restart the app
  4. Kill again (now messages are received, everything is working fine)
JU5T1C3
  • 678
  • 1
  • 9
  • 26
2

To fix this issue there is no official solution but here is workaround you can use

2 things you need to manage Autostart and Battery Optimization then your issue will get fixed

  1. Autostart You need to ask to autostart permission for starting an app in the background after getting killed by the user

you can use below intents for it

 private void enableAutoStart() {
    if (Build.BRAND.equalsIgnoreCase("xiaomi")) {
      new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
        .content(
          "Please allow QuickAlert to always run in the background,else our services can't be accessed when you are in distress")
        .theme(Theme.LIGHT)
        .positiveText("ALLOW")
        .onPositive(new MaterialDialog.SingleButtonCallback() {
          @Override
          public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {

            Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.miui.securitycenter",
              "com.miui.permcenter.autostart.AutoStartManagementActivity"));
            startActivity(intent);
          }
        })
        .show();
    } else if (Build.BRAND.equalsIgnoreCase("Letv")) {
      new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
        .content(
          "Please allow QuickAlert to always run in the background,else our services can't be accessed when you are in distress")
        .theme(Theme.LIGHT)
        .positiveText("ALLOW")
        .onPositive(new MaterialDialog.SingleButtonCallback() {
          @Override
          public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {

            Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.letv.android.letvsafe",
              "com.letv.android.letvsafe.AutobootManageActivity"));
            startActivity(intent);
          }
        })
        .show();
    } else if (Build.BRAND.equalsIgnoreCase("Honor")) {
      new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
        .content(
          "Please allow QuickAlert to always run in the background,else our services can't be accessed when you are in distress")
        .theme(Theme.LIGHT)
        .positiveText("ALLOW")
        .onPositive(new MaterialDialog.SingleButtonCallback() {
          @Override
          public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.huawei.systemmanager",
              "com.huawei.systemmanager.optimize.process.ProtectActivity"));
            startActivity(intent);
          }
        })
        .show();
    } else if (Build.MANUFACTURER.equalsIgnoreCase("oppo")) {
      new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
        .content(
          "Please allow QuickAlert to always run in the background,else our services can't be accessed when you are in distress")
        .theme(Theme.LIGHT)
        .positiveText("ALLOW")
        .onPositive(new MaterialDialog.SingleButtonCallback() {
          @Override
          public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
            try {
              Intent intent = new Intent();
              intent.setClassName("com.coloros.safecenter",
                "com.coloros.safecenter.permission.startup.StartupAppListActivity");
              startActivity(intent);
            } catch (Exception e) {
              try {
                Intent intent = new Intent();
                intent.setClassName("com.oppo.safe",
                  "com.oppo.safe.permission.startup.StartupAppListActivity");
                startActivity(intent);
              } catch (Exception ex) {
                try {
                  Intent intent = new Intent();
                  intent.setClassName("com.coloros.safecenter",
                    "com.coloros.safecenter.startupapp.StartupAppListActivity");
                  startActivity(intent);
                } catch (Exception exx) {

                }
              }
            }
          }
        })
        .show();
    } else if (Build.MANUFACTURER.contains("vivo")) {
      new MaterialDialog.Builder(MainActivity.this).title("Enable AutoStart")
        .content(
          "Please allow QuickAlert to always run in the background.Our app runs in background to detect when you are in distress.")
        .theme(Theme.LIGHT)
        .positiveText("ALLOW")
        .onPositive(new MaterialDialog.SingleButtonCallback() {
          @Override
          public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
            try {
              Intent intent = new Intent();
              intent.setComponent(new ComponentName("com.iqoo.secure",
                "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity"));
              startActivity(intent);
            } catch (Exception e) {
              try {
                Intent intent = new Intent();
                intent.setComponent(new ComponentName("com.vivo.permissionmanager",
                  "com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
                startActivity(intent);
              } catch (Exception ex) {
                try {
                  Intent intent = new Intent();
                  intent.setClassName("com.iqoo.secure",
                    "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager");
                  startActivity(intent);
                } catch (Exception exx) {
                  ex.printStackTrace();
                }
              }
            }
          }
        })
        .show();
    }
  }

  public boolean checkServiceRunning() {
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
      Integer.MAX_VALUE)) {
      if ("com.sac.speechdemo.MyService".equals(service.service.getClassName())) {
        return true;
      }
    }
    return false;
  }
  1. Battery Optimization/Background Free/ DOZE Mode

    to manage battery optimization use below code with permission, it will work on Stock Android

    private void askIgnoreOptimization() {

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, IGNORE_BATTERY_OPTIMIZATION_REQUEST);
    } else {
        openNextActivity();
    }
    

    }

and for custom OS you need to redirect user for battery optimization permission like below intent for OPPO devices

intent.setClassName("com.coloros.oppoguardelf", "com.coloros.powermanager.fuelgaue.PowerConsumptionActivity"); startActivity(intent);

call above intent, it will redirect you to battery option, "Disable Background Freeze, Abnormal Apps Optimization and Doze from \"Energy Saver ->youAPP"

Note: Once you call the above intent, there you may get different options to turn off Battery saving options. This battery optimization option can be found in Battery option from device setting, it varies as per ROM.

Amin Pinjari
  • 2,129
  • 3
  • 25
  • 53
1

I was also facing the issue. When I remove application from stack, push notification not received. After lots of Google, I found that few phones have battery optimization feature and this will disable background run of applications. When I enable that my application can also run in background. Push notification working fine. Only few application like What's application etc can only have default enable feature. You can have a look on this below URL.

https://github.com/firebase/quickstart-android/issues/89

ParikshitSinghTomar
  • 417
  • 1
  • 4
  • 28
1

This is because your app is optimized for battery usage to disable that and receive notification even when your app isn't running in background

Add this permission to manifest

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

While first launch of your app request user for permission to ignore this app for battery optimization

 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Intent intent = new Intent();
            String packageName = getPackageName();
            PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
            if (!pm.isIgnoringBatteryOptimizations(packageName)) {
                intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + packageName));
                startActivity(intent);
            }
        }
Praveen
  • 388
  • 3
  • 7
1

For me it was the case that AutoStart functionality for my app was provided. Go to settings select your installed app and enable AutoStart. This will fix the issue.

Pradeep Kumar Kushwaha
  • 2,231
  • 3
  • 23
  • 34
0

I had this error even while my app was open. I eventually found that a com.google.android.c2dm.intent.RECEIVE receiver was missing from my manifest.

In my case this was caused by accidentally removing the FirebaseInstanceIdReceiver via manifest merger with:

  <receiver
            android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
            tools:node="remove" />

Deleting this element allowed the receiver to be added properly during manifest merger (verified by inspecting the final apk's manifest)

rockgecko
  • 4,127
  • 2
  • 18
  • 31