/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package androidx.media3.session;
import static androidx.media3.common.util.Assertions.checkNotNull;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.os.Bundle;
import androidx.annotation.IntRange;
import androidx.core.app.NotificationCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** A notification for media playbacks. */
public final class MediaNotification {
/**
* Creates {@linkplain NotificationCompat.Action actions} and {@linkplain PendingIntent pending
* intents} for notifications.
*/
@UnstableApi
public interface ActionFactory {
/**
* Creates a {@link NotificationCompat.Action} for a notification. These actions will be handled
* by the library.
*
* @param mediaSession The media session to which the action will be sent.
* @param icon The icon to show for this action.
* @param title The title of the action.
* @param command A command to send when users trigger this action.
*/
NotificationCompat.Action createMediaAction(
MediaSession mediaSession,
IconCompat icon,
CharSequence title,
@Player.Command int command);
/**
* Creates a {@link NotificationCompat.Action} for a notification with a custom action. Actions
* created with this method are not expected to be handled by the library and will be forwarded
* to the {@linkplain MediaNotification.Provider#handleCustomCommand notification provider} that
* provided them.
*
* @param mediaSession The media session to which the action will be sent.
* @param icon The icon to show for this action.
* @param title The title of the action.
* @param customAction The custom action set.
* @param extras Extras to be included in the action.
* @see MediaNotification.Provider#handleCustomCommand
*/
NotificationCompat.Action createCustomAction(
MediaSession mediaSession,
IconCompat icon,
CharSequence title,
String customAction,
Bundle extras);
/**
* Creates a {@link NotificationCompat.Action} for a notification from a custom command button.
* Actions created with this method are not expected to be handled by the library and will be
* forwarded to the {@linkplain MediaNotification.Provider#handleCustomCommand notification
* provider} that provided them.
*
* <p>The returned {@link NotificationCompat.Action} will have a {@link PendingIntent} with the
* extras from {@link SessionCommand#customExtras}. Accordingly the {@linkplain
* SessionCommand#customExtras command's extras} will be passed to {@link
* Provider#handleCustomCommand(MediaSession, String, Bundle)} when the action is executed.
*
* @param mediaSession The media session to which the action will be sent.
* @param customCommandButton A {@linkplain CommandButton custom command button}.
* @see MediaNotification.Provider#handleCustomCommand
*/
NotificationCompat.Action createCustomActionFromCustomCommandButton(
MediaSession mediaSession, CommandButton customCommandButton);
/**
* Creates a {@link PendingIntent} for a media action that will be handled by the library.
*
* @param mediaSession The media session to which the action will be sent.
* @param command The intent's command.
*/
PendingIntent createMediaActionPendingIntent(
MediaSession mediaSession, @Player.Command long command);
}
/**
* Provides {@linkplain MediaNotification media notifications} to be posted as notifications that
* reflect the state of a {@link MediaController} and to send media commands to a {@link
* MediaSession}.
*
* <p>The provider is required to create a {@linkplain androidx.core.app.NotificationChannelCompat
* notification channel}, which is required to show notification for {@code SDK_INT >= 26}.
*/
@UnstableApi
public interface Provider {
/** Receives updates for a notification. */
interface Callback {
/**
* Called when a {@link MediaNotification} is changed.
*
* <p>This callback is called when notifications are updated, for example after a bitmap is
* loaded asynchronously and needs to be displayed.
*
* @param notification The updated {@link MediaNotification}
*/
void onNotificationChanged(MediaNotification notification);
}
/**
* Creates a new {@link MediaNotification}.
*
* @param session The media session.
* @param actionFactory The {@link ActionFactory} for creating notification {@link
* NotificationCompat.Action actions}.
* @param customLayout The custom layout {@linkplain MediaSession#setCustomLayout(List) set by
* the session}.
* @param onNotificationChangedCallback A callback that the provider needs to notify when the
* notification has changed and needs to be posted again, for example after a bitmap has
* been loaded asynchronously.
*/
MediaNotification createNotification(
MediaSession session,
ImmutableList<CommandButton> customLayout,
ActionFactory actionFactory,
Callback onNotificationChangedCallback);
/**
* Handles a notification's custom command.
*
* @param session The media session.
* @param action The custom command action.
* @param extras A bundle {@linkplain SessionCommand#customExtras set in the custom command},
* otherwise {@link Bundle#EMPTY}.
* @return {@code false} if the action should be delivered to the session as a custom command or
* {@code true} if the action has been handled completely by the provider.
* @see ActionFactory#createCustomAction
*/
boolean handleCustomCommand(MediaSession session, String action, Bundle extras);
}
/** The notification id. */
@IntRange(from = 1)
public final int notificationId;
/** The {@link Notification}. */
public final Notification notification;
/**
* Creates an instance.
*
* @param notificationId The notification id to be used for {@link NotificationManager#notify(int,
* Notification)}.
* @param notification A {@link Notification} that reflects the state of a {@link MediaController}
* and to send media commands to a {@link MediaSession}. The notification may be used to start
* a service in the <a
* href="https://developer.android.com/guide/components/foreground-services">foreground</a>.
* It's highly recommended to use a {@linkplain
* androidx.media.app.NotificationCompat.MediaStyle media style} {@linkplain Notification
* notification}.
*/
public MediaNotification(@IntRange(from = 1) int notificationId, Notification notification) {
this.notificationId = notificationId;
this.notification = checkNotNull(notification);
}
}