Подтвердить что ты не робот

Ошибка обратного вызова для трансляции: result = CANCELED forIntent {act = com.google.android.c2dm.intent.RECEIVE pkg = com.flagg327.guicomaipu(есть дополнительные функции)}

Я получаю эту ошибку от Android Studio Android Monitor. Эта ошибка появляется, когда я отправляю push-уведомление через 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

Обновления "токенов" регистрации каждый день. Это потому, что каждое приложение для Android, использующее GCM, должно иметь 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 автоматически отображает push-уведомления, но только если связанное приложение имеет 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);
    }
}

Ошибка

Эта ошибка появляется, когда я отправляю push-уведомление через 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) }

Вчера работала... Любая идея? Чем вы на какое-то время.

4b9b3361

Ответ 1

Я получил ту же ошибку

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

после убийства приложения.

После некоторых исследований я понял, что это всего лишь "Debug-Issue". "Подписанный APK" корректно обрабатывает трансляцию, даже если приложение было отключено.

Надеюсь, что это поможет!

Ответ 2

Поскольку ни один из ответов не дает официальной ссылки, я решил спросить команду Firebase и получил официальный ответ от них.

Похоже, у вас есть проблема, когда ваше приложение было принудительно остановлено или убито. На самом деле, это работает как задумано. Платформа 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 функция смахивания (нажмите кнопку недавнего приложения/смахивание) неправильно реализована, чтобы быть похожей с настройками/принудительной остановкой. Из-за этого служба сообщений Firebase не может запуститься.
  • Вопрос был поднят здесь и во многих местах. Команда FCM знает об этой проблеме и работает над ней

ПРИМЕЧАНИЕ: даже вопрос касается GCM, но FCM выдает точно такую же ошибку в заголовке вопроса.

Ответ 3

Итак... Я решил проблему. Проблема заключалась в том, что устройство не зарегистрировано для получения 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 и будет иметь возможность получать любые push-уведомления с моего сервера. Надеюсь, это полезно.

Ответ 4

После того, как это произошло, выяснилось, что это произойдет, если вы убьете приложение из Android Studio.

Если вы откроете приложение из панели запуска и проведите по нему, ваше приложение все равно получит уведомления.

(Протестировано на OnePlus One с FCM не GCM)

Ответ 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);
            }
        }

Ответ 6

Я тоже столкнулся с проблемой. Когда я удаляю приложение из стека, push-уведомление не получено. После многих Google я обнаружил, что у немногих телефонов есть функция оптимизации батареи, и это отключит фоновый запуск приложений. Когда я включаю, что мое приложение также может работать в фоновом режиме. Push-уведомление работает нормально. Только небольшое приложение, такое как "Приложение" и т.д., Может иметь только функцию включения по умолчанию. Вы можете посмотреть этот ниже URL.

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

Ответ 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. Оптимизация заряда аккумулятора/Без фона/Режим DOZE

    для управления оптимизацией батареи используйте приведенный ниже код с разрешения, он будет работать на стоковой 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);

звоните выше намерения, он перенаправит вас к параметру батареи "Отключить фоновое замораживание, оптимизацию ненормальных приложений и Doze от \" Энергосбережение → youAPP "

Примечание. После того, как вы вызовете вышеуказанное намерение, у вас могут появиться различные варианты отключения параметров экономии заряда батареи. Этот параметр оптимизации аккумулятора можно найти в разделе "Параметры аккумулятора" в настройках устройства, он зависит от ПЗУ.