【问题标题】:Error broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.flagg327.guicomaipu (has extras) }错误广播意图回调:result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.flagg327.guicomaipu (has extras) }
【发布时间】:2017-01-21 16:45:56
【问题描述】:

我从 Android Studio 的 Android 监视器收到了该错误。当我通过 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) }

昨天还在工作……有什么想法吗?比你花时间。

【问题讨论】:

  • 基于此thread,当接收应用程序在设备上处于停止状态时会发生此问题(例如,通过使用设置中的强制停止)。只有在手动启动时才会再次开始接收消息。您也可以查看related SO post
  • Here 这些步骤可以帮助您。

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


【解决方案1】:

所以...我解决了这个问题。问题是如果应用程序被强制关闭或应用程序自设备启动后从未打开过,则设备未注册以接收 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 服务器并能够接收来自我的服务器的任何推送通知。希望有用。

【讨论】:

  • 谢谢@flagg327,我也是同样的问题,你的回答解决了。
  • 打瞌睡模式也会出现问题
  • 如果您的应用针对电池使用进行了优化,则无法运行。
  • 希望stackoverflow.com/a/58162451/7579041能解决你的问题
  • 你好,可以分享一下注册服务的代码吗?
【解决方案2】:

我遇到了同样的错误

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

杀死应用程序后。

经过一些研究,我意识到这只是一个“调试问题”。即使应用程序已关闭,“签名的 APK”也会正确处理广播。

希望对你有帮助!

【讨论】:

  • 请为您的资源链接来源
  • @natanavra 你是什么意思?完整的来源在原始问题中 - 不是吗?
  • @niggeulimann 我是为了你的研究。添加指向支持您的发现的文档的链接...
  • 不起作用。如果我强制停止应用程序,将不会收到消息。
  • 这个答案是对的。在许多手机上进行了测试,并且始终具有相同的行为。即使您杀死应用,已签名的应用也会收到推送。
【解决方案3】:

在深入了解为什么会发生这种情况后,如果您从 Android Studio 中终止应用,似乎就会发生这种情况。

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

(在 OnePlus One 上使用 FCM 而非 GCM 进行测试)

【讨论】:

  • 这对我帮助很大。谢谢。
  • 你能解释一下吗?
  • @amin 当然,单击 Android Studio 中的“停止”按钮会完全终止应用程序并完全删除其后台服务(例如,类似于“强制停止”)。
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

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

    将此权限添加到清单

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

    【讨论】:

    • 它无法在 OPPO、Realme 等设备上运行,它们需要自动启动权限
    【解决方案6】:

    由于没有答案提供官方链接,我决定询问 firebase 团队并从他们那里得到官方答案

    当您的应用被强制停止或 被杀。实际上,这是按预期工作的。安卓框架 建议已停止的应用程序(即杀死/强制停止 来自设置)不应在没有明确用户的情况下启动 相互作用。 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 在问题标题中抛出完全相同的错误。

    【讨论】:

    • 不过,我猜他们没有任何解决方案
    【解决方案7】:

    对我来说,为我的应用程序提供了自动启动功能。转到设置选择您安装的应用程序并启用自动启动。这将解决问题。

    【讨论】:

      【解决方案8】:

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

      您需要管理自动启动和电池优化的 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. 电池优化/无背景/打盹模式

        管理电池优化使用下面的代码获得许可,它将在 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”

      注意:调用上述意图后,您可能会获得不同的选项来关闭省电选项。 这个电池优化选项可以在设备设置的电池选项中找到,它根据ROM而有所不同。

      【讨论】:

        【解决方案9】:

        我在模拟器上安装我的应用程序时也遇到了这个问题。 我只处理 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 启动应用程序时才会出现停止 = true 的情况。如果我手动启动应用程序或使用 adb shell am start -n 然后将其终止(从最近删除),则状态为停止 = false 并且推送通知工作正常!

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

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

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

        【讨论】:

          【解决方案10】:

          即使我的应用程序处于打开状态,我也遇到了这个错误。我最终发现我的清单中缺少一个com.google.android.c2dm.intent.RECEIVE 接收器。

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-06
            • 1970-01-01
            • 2023-03-18
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多