Как отобразить push-уведомления из фонового сервиса в Android O // как правильно использовать startForeground()

Я пытаюсь показать push-уведомление, вызванное GCM-сообщением. Сообщение GCM принимается приемником вещания в фоновом режиме, однако Push-уведомление не отображается.

Я уменьшил код для демонстрации:

BroadcastReceiver (Logging говорит мне, что onReceive() вызывается)

public class GcmBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = GcmBroadcastReceiver.class.getName();

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "received GCM intent: "+intent.toString());
        ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName());
        context.startForegroundService(intent.setComponent(comp));
    }
}

Намерение, которое должно запустить уведомление. Ведение журнала говорит, что onHandleIntent() вызывается.

@RequiresApi(api = Build.VERSION_CODES.O)
public class GcmIntentService extends IntentService {
    private static final String TAG = GcmIntentService.class.getName();

    public GcmIntentService() { super("GcmIntentService"); }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG,"received intent");
        String channelId = "MyChannelId";
        Notification notification = new NotificationCompat.Builder(getApplication(), channelId)
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle("MyTitle")
                .setContentText("MyText")
                .build();

        NotificationChannel channel = new NotificationChannel(channelId, "foo", NotificationManager.IMPORTANCE_HIGH);
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.createNotificationChannel(channel);

        startForeground(1, notification);
        manager.notify(1, notification);
    }
}

Мой AndroidManifest.xml:

    <receiver
        android:name=".cdmclient.GcmBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="${applicationId}.cdmclient" />
        </intent-filter>
    </receiver>

    <service android:name=".cdmclient.GcmIntentService" android:exported="false"/>

Когда приложение находится на переднем плане, когда получено событие GCM, журнал показывает:

D/de.locked.bob.cdmclient.GcmBroadcastReceiver: received GCM intent: Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=de.locked.bob.debug cmp=de.locked.bob.debug/de.locked.bob.cdmclient.GcmBroadcastReceiver (has extras) }
D/de.locked.bob.cdmclient.GcmIntentService: received intent
E/EnhancedIntentService: binding to the service failed

Когда приложение находится в фоновом режиме при получении события GCM, журнал показывает:

D/de.locked.bob.cdmclient.GcmBroadcastReceiver: received GCM intent: Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=de.locked.bob.debug cmp=de.locked.bob.debug/de.locked.bob.cdmclient.GcmBroadcastReceiver (has extras) }
D/de.locked.bob.cdmclient.GcmIntentService: received intent
W/EnhancedIntentService: Service took too long to process intent: com.google.android.c2dm.intent.RECEIVE App may get closed.

И, конечно, уведомление не появляется. Я думаю, что я использую startForeground(..) а также startForegroundService(...) неправильно, но у меня сейчас нет идей.

1 ответ

Решение

IntentServices не должны запускаться как Foreground Services (см.: Использование startForeground() с Intent Service)

Вы планируете запустить Сервис, когда приходит пуш-уведомление от GCM? Вам не нужна услуга, чтобы показать уведомление; Вы можете сделать это с помощью BroadcastReceiver, как вы это делали в Сервисе.