Android 11: DecoratedMediaCustomViewStyle игнорирует setCustomContentView

Мое приложение для Android используется для удаленного управления медиаплеером (Winamp на ПК). Чтобы позволить пользователю управлять удаленным проигрывателем, даже если приложение Android в настоящее время не активно, он использует MediaSession, связанный с фоновой службой и системным уведомлением. В системном уведомлении используется стиль DecoratedMediaCustomViewStyle, и я установил настраиваемое представление с помощью методов setCustomContentView() и setCustomBigContentView(). Я вызываю setPlaybackToRemote() в MediaSession с VolumeProviderCompat. Это важное различие, потому что мультимедиа воспроизводятся не на устройстве Android, а на удаленном устройстве. И нет, это не Chromecast, а что-то совсем другое (Winamp на ПК по кастомному протоколу).

Все это отлично работает в версиях Android до 11 (API 30). Но в Android 11 пользовательский вид (как "обычный", так и "большой") полностью игнорируется. Вот скриншоты "большого" уведомления, вверху на API 27 (то же, что и API 28 и 29), за которым следует API 30.

Обратите внимание, что в верхнем не упоминается дважды "Ampwifi", а справа есть кнопка "X". Эта кнопка "X" важна, поскольку она позволяет пользователю закрыть уведомление и выключить фоновую службу.

Я просмотрел документы и журналы изменений Android 11 и ничего не нашел об этом. У меня также есть более старый образ AVD из предварительной версии Android "R", где он также работал, как в API 29 и старше. Мне интересно, действительно ли это ошибка Android? Если нет, кто-нибудь еще сталкивался с этим, и у кого-нибудь есть предложения, как это обойти?

Я попытался просто не связывать MediaSession с уведомлением. Это фактически восстанавливает настраиваемый вид, но я теряю все преимущества MediaSession (интеграция Bluetooth/Google Assistant и автоматическая окраска кнопок действий с уведомлениями). Так что исправить это было бы здорово.

Вот код:

       /////

final ConnectionProfile profile = mSettings.getActiveConnectionProfile();
final String profileName = profile != null ? profile.name : "";
final RemoteViews contentView = getContent(profileName);
final RemoteViews bigContentView = getBigContent(profileName);

final NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(ServiceBackgroundMediapPlayer.this, NotificationChannelBackgroundMediaPlayerServiceId)
        .setColorized(true)
        .setOngoing(true)
        .setAutoCancel(false)
        .setContentIntent(getDefaultIntent())
        .setDeleteIntent(getDeleteIntent())
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setSmallIcon(R.drawable.ic_notification)
        .setLargeIcon(getBitmap())
        .setContentTitle("Ampwifi")
        .setContentText(profileName)
        .addAction(R.drawable.ic_media_previous, null, MediaButtonReceiver.buildMediaButtonPendingIntent(ServiceBackgroundMediapPlayer.this, PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS))
        .addAction(R.drawable.ic_media_play, null, MediaButtonReceiver.buildMediaButtonPendingIntent(ServiceBackgroundMediapPlayer.this, PlaybackStateCompat.ACTION_PLAY))
        .addAction(R.drawable.ic_media_pause, null, MediaButtonReceiver.buildMediaButtonPendingIntent(ServiceBackgroundMediapPlayer.this, PlaybackStateCompat.ACTION_PAUSE))
        .addAction(R.drawable.ic_media_stop, null, MediaButtonReceiver.buildMediaButtonPendingIntent(ServiceBackgroundMediapPlayer.this, PlaybackStateCompat.ACTION_STOP))
        .addAction(R.drawable.ic_media_next, null, MediaButtonReceiver.buildMediaButtonPendingIntent(ServiceBackgroundMediapPlayer.this, PlaybackStateCompat.ACTION_SKIP_TO_NEXT))
        .setStyle(getStyle())
        .setCustomContentView(contentView)
        .setCustomBigContentView(bigContentView)
        .setOnlyAlertOnce(true);

mNotification = notificationBuilder.build();

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(R.id.ServiceBackgroundMediapPlayerNotification, mNotification);


/////

public NotificationCompat.Style getStyle() {
    return new androidx.media.app.NotificationCompat.DecoratedMediaCustomViewStyle()
        .setShowCancelButton(true)
        .setCancelButtonIntent(getDeleteIntent())
        .setShowActionsInCompactView(1, 2, 4)
        .setMediaSession(getMediaSessionToken());
}

public RemoteViews getContent(String title) {
    final RemoteViews layout = new RemoteViews("com.blitterhead.ampwifi", R.layout.notification_media);

    if (layout != null) {
        layout.setTextViewText(R.id.title, title);
    }

    return layout;
}


public RemoteViews getBigContent(String title) {
    final RemoteViews layout = new RemoteViews("com.blitterhead.ampwifi", R.layout.notification_media_big);

    if (layout != null) {
        layout.setTextViewText(R.id.title, title);
        layout.setOnClickPendingIntent(R.id.dismiss, getDeleteIntent());
    }

    return layout;
}

private MediaSessionCompat.Token getMediaSessionToken() {
    if (_mediaSessionToken == null) {
        PlaybackStateCompat playbackState = mPlaybackStateBuilder
                .setActiveQueueItemId(1)
                .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS | PlaybackStateCompat.ACTION_SKIP_TO_NEXT)
                .setState(PlaybackStateCompat.STATE_PLAYING, 0, 1.0f)
                .build();

        ComponentName mediaButtonReceiver = new ComponentName(getApplicationContext(), MediaButtonReceiver.class);
        mMediaSession = new MediaSessionCompat(ServiceBackgroundMediapPlayer.this, MediaSessionTag, mediaButtonReceiver, null);
        mMediaSession.setPlaybackState(playbackState);
        mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mMediaSession.setMetadata(getMetaData());
        mMediaSession.setCallback(getMediaSessionCallback());
        mMediaSession.setActive(true);

        if (mSettings.getBackgroundMediaVolume()) {
            mMediaSession.setPlaybackToRemote(getVolumeProvider());
        }

        _mediaSessionToken = mMediaSession.getSessionToken();

        setSessionToken(_mediaSessionToken);
    }

    return _mediaSessionToken;
}

0 ответов

Другие вопросы по тегам