web-dev-qa-db-ja.com

ブロードキャストインテントコールバックエラー:result = CANCELLED forIntent {act = com.google.Android.c2dm.intent.RECEIVE pkg = com.flagg327.guicomaipu(has extras)}

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

昨日は働いていました...何かアイデアはありますか?お時間をいただきありがとうございます。

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

アプリを殺した後。

いくつかの調査の後、これは単なる「デバッグの問題」であることがわかりました。 「署名されたAPK」は、アプリがシャットダウンされていてもブロードキャストを正しく処理します。

それが役に立てば幸い!

10
niggeulimann

回答のどれも公式リンクを提供していないので、私は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の一部のROMでは、スワイプ機能(最近のアプリボタン/スワイプをクリック)が誤って設定/強制停止と同様に実装されています。そのため、firebaseメッセージサービスを開始できません。
  • この問題は、ここと多くの場所で提起されています。 FCMチームは問題を認識しており、それに取り組んでいます

注:質問もGCMに関するものですが、FCMは質問のタイトルにまったく同じエラーをスローします。

7
thanhbinh84

だから...私は問題を解決しました。問題は、アプリが強制的に閉じられた場合、またはデバイスの起動後にアプリが開かれなかった場合、デバイスが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サーバーに登録され、サーバーからプッシュ通知を受信できるようになります。役に立つことを願っています。

6
flagg327

これが起こる理由を掘り下げた後、Android Studio。

ランチャーからアプリを開いてスワイプすると、アプリは引き続き通知を受け取ります。

(GCMではなくFCMを使用したOnePlus Oneでテスト済み)

5
natanavra

これは、アプリがバッテリ使用量に対して最適化されており、アプリがバックグラウンドで実行されていない場合でもそれを無効にして通知を受け取るためです

この許可をマニフェストに追加

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

私も問題に直面していました。スタックからアプリケーションを削除すると、プッシュ通知が受信されません。多くのGoogleの後、バッテリー最適化機能を備えた携帯電話はほとんどなく、これによりアプリケーションのバックグラウンド実行が無効になることがわかりました。有効にすると、アプリケーションもバックグラウンドで実行できます。プッシュ通知は正常に機能しています。 What's applicationなどのごく一部のアプリケーションのみが、デフォルトの有効化機能を持つことができます。これはURLの下で見ることができます。

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

1

私にとっては、アプリのAutoStart機能が提供されていました。設定に移動して、インストールしたアプリを選択し、自動起動を有効にします。これにより問題が修正されます。