it-swarm.com.ru

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

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

Вчера работал ... Есть идеи? Чем ты уделил время.

18
flagg327

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

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» правильно обрабатывает трансляцию, даже если приложение было закрыто. 

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

10
niggeulimann

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

6
flagg327

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

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

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

4
natanavra

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

Похоже, у вас есть проблема, когда ваше приложение принудительно остановлено или убит. На самом деле, это работает как задумано. Фреймворк Android советует, чтобы приложения, которые были остановлены (то есть убиты/принудительно остановлены .__ из настроек), не должны запускаться без явного пользователя взаимодействие. FCM следует этой рекомендации и, следовательно, своим услугам также не начнется. Это также означает, что сообщения не будут получил (FirebaseMessagingService не будет вызываться), когда приложение в "убитом" состоянии. Вот несколько полезных ссылок, чтобы вы могли иметь лучшее понимание по этой теме: https://developer.Android.com/about/versions/Android-3.1#launchcontrolshttps://github.com/firebase/quickstart-Android/issues/368#issuecomment-343567506

В сумме:

  • приложение, убитое пользователем (из настроек/принудительной остановки), будет помечено флажком, который не сможет автоматически запускать любую службу, включающую службу сообщений firebase. Это не то же самое с приложением, убитым системой или проведением из недавнего приложения. 
  • Однако на некоторых ПЗУ от VIVO или ONEPLUS функция смахивания (нажмите кнопку недавнего приложения/смахивание) ошибочно реализована, чтобы быть похожей с настройками/принудительной остановкой. Из-за этого служба сообщений Firebase не может запуститься. 
  • Вопрос был поднят здесь и во многих местах. Команда FCM знает об этой проблеме и работает над ней 

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

3
thanhbinh84

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

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

1
ParikshitSinghTomar

Это потому, что ваше приложение оптимизировано для использования батареи, чтобы отключить это и получать уведомления, даже если ваше приложение не работает в фоновом режиме

Добавить это разрешение для манифеста

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