错误广播意图回调:result = CANCELED forIntent {act = com.google.android.c2dm.intent.RECEIVE pkg = com.flagg327.guicomaipu(has extras)}

时间:2016-09-14 00:43:26

标签: android push-notification google-cloud-messaging

我从Android Studio的Android Monitor收到该错误。当我通过GCM在真实设备中发送推送通知并且应用尚未启动或已被迫停止时,会出现此错误。昨天一切正常,今天根本不工作(仅当应用程序在后台或前台运行时才有效。)

我认为这可能是AndroidManifest错误,但我已经厌倦了寻找问题并找不到任何内容。

清单

<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

每天注册'令牌'更新。因此,每个使用GCM的Android应用程序都必须具有管理这些更新的InstanceIDListenerService。

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会自动显示推送通知,但前提是相关应用具有GCMListenerService

public class NotificacionsListenerService extends GcmListenerService {

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

        // Do something

    }
}

RegistrationService.java

GCM使用注册卡('令牌')识别Android设备。我的应用程序应该能够从安装它的每个Android设备注册。

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);
    }
}

错误

当我通过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) }

昨天工作......有什么想法吗?比你的时间。

10 个答案:

答案 0 :(得分:10)

我得到了相同的错误

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) }
杀死应用后

经过一番研究后,我意识到,这只是一个&#34; Debug-Issue&#34;。 A&#34;签名APK&#34;即使应用程序已关闭,也能正确处理广播。

希望它有所帮助!

答案 1 :(得分:6)

所以......我解决了这个问题。问题是如果应用程序强制关闭或者自设备启动以来从未打开应用程序,则设备未注册接收GCM。解决方案很简单,在手机启动时注册设备。为此,我实现了BroadcastReceiver并在其中启动了流程注册。

修改:

添加到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);
    }
}

因此,在启动时,设备将注册到GCM服务器,并能够从我的服务器接收任何推送通知。我希望它很有用。

答案 2 :(得分:6)

由于没有答案提供官方链接,所以我决定向火力基地团队询问并从他们那里获得官方答案

  

强制停止应用程序或   被杀。实际上,这按预期工作。 Android框架   告知已停止的应用(即已终止/强制停止)   来自“设置”)不应在没有明确用户的情况下启动   相互作用。 FCM遵循此建议并因此遵循其服务   也不会启动。这也意味着消息不会   应用程式收到时(FirebaseMessagingService将不会呼叫)   处于“被杀死”状态。这是一些有用的链接,因此您可以   对此主题有更好的理解:   https://developer.android.com/about/versions/android-3.1#launchcontrols   https://github.com/firebase/quickstart-android/issues/368#issuecomment-343567506

总之:

  • 该应用程序被用户杀死(从设置/强制停止),将被标记一个标记,该标记将无法自动触发包括Firebase消息服务在内的任何服务。这与应用被系统杀死或从最近的应用中刷卡不同。
  • 但是,在VIVO或ONEPLUS的某些ROM上,滑动功能(单击最近的应用程序按钮/滑动)被错误地实现,与设置/强制停止类似。这导致Firebase消息服务无法启动。
  • 这个问题在这里和许多地方都已经提出。 FCM小组已意识到此问题,并正在对此进行研究

注意:即使问题与GCM有关,但FCM在问题标题中也会引发完全相同的错误。

答案 3 :(得分:4)

在深入了解为什么会发生这种情况之后,如果您从Android Studio中删除应用程序,就会发生这种情况。

如果您从启动器中打开应用并将其轻扫,您的应用仍会收到通知。

(使用FCM而不是GCM在OnePlus One上测试)

答案 4 :(得分:1)

我也面临着这个问题。当我从堆栈中删除应用程序时,推送未收到的通知。经过大量的谷歌,我发现很少有手机具有电池优化功能,这将禁用应用程序的后台运行。当我启用时,我的应用程序也可以在后台运行。推送通知工作正常。只有少数应用程序如What's应用程序等只能具有默认启用功能。您可以查看以下网址。

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

答案 5 :(得分:1)

这是因为您的应用已针对电池使用进行了优化,即使在未在后台运行的情况下也可以禁用电池并接收通知

添加此权限以显示

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

首次启动应用时,请求用户获得忽略此应用的权限以进行电池优化

 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);
            }
        }

答案 6 :(得分:0)

对于我来说,就是为我的应用程序提供了自动启动功能。转到设置,选择已安装的应用程序并启用自动启动。这样可以解决问题。

答案 7 :(得分:0)

要解决此问题,没有官方的解决方案,但是您可以使用以下解决方法

管理自动启动和电池优化所需的2件事,您的问题将得到解决

  1. 自动启动 您需要在用户被杀死后要求自动启动权限才能在后台启动应用程序

您可以使用以下意图

 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. 电池优化/无背景/打DO模式

    要在许可的情况下使用以下代码来管理电池优化,它将在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();
    }
    

    }

对于自定义操作系统,您需要重定向用户以获取电池优化权限,如下所示 用于OPPO设备

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

按照上述意图进行调用,它将把您重定向到电池选项,“从“节能器-> youAPP”禁用后台冻结,异常的应用程序优化和打Do”

注意:调用上述意图后,您可能会获得不同的选项来关闭省电选项。 该电池优化选项可在设备设置的“电池”选项中找到,具体取决于ROM。

答案 8 :(得分:0)

在模拟器上安装我的应用程序时,我也遇到了这个问题。 我只使用FCM数据消息,因为我需要自己处理消息(也要进行静默推送)。

但是当我测试后台时,什么也没发生。而且我也观察到你的错误

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) }

我读了很多有关该内容的信息,因为我不敢相信当该应用程序被杀死时FCM不能正常工作,这会破坏推送通知的整个目的。 而且我还观察了即使在应用程序被杀死的情况下仍然收到我的消息的情况,但是我不知道为什么有时会发生这种情况。

在阅读完github上的firebase问题后,我停下了一个非常了不起的答案:

经过一些测试后,只有在我使用Android Studio启动应用程序的情况下,似乎stop = true。如果我手动启动该应用程序或使用adb shell am start -n然后将其杀死(从最近状态中清除),则状态为stop = false,并且推送通知就可以了!

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

因此,当您仍然遇到此问题时,请尝试以下操作:

  1. 通过Android Studio安装应用
  2. 关闭并杀死该应用程序(在未收到任何消息后,观察到错误发生)
  3. 重新启动应用
  4. 再次杀死(现在收到消息,一切正常)

答案 9 :(得分:0)

即使我的应用处于打开状态,我仍然遇到此错误。我最终发现清单中缺少一个com.google.android.c2dm.intent.RECEIVE接收者。

在我的情况下,这是由于与清单合并而意外删除了FirebaseInstanceIdReceiver

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

删除此元素可在清单合并期间正确添加接收方(通过检查最终apk的清单进行验证)