/*
* 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 static java.lang.annotation.ElementType.TYPE_USE;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.os.Bundle;
import android.support.v4.media.session.PlaybackStateCompat;
import androidx.annotation.IntRange;
import androidx.annotation.LongDef;
import androidx.core.app.NotificationCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** A notification for media playbacks. */
public final class MediaNotification {
/**
* Creates {@link NotificationCompat.Action actions} and {@link PendingIntent pending intents} for
* notifications.
*/
@UnstableApi
public interface ActionFactory {
/**
* Commands that can be included in a media action. One of {@link #COMMAND_PLAY}, {@link
* #COMMAND_PAUSE}, {@link #COMMAND_STOP}, {@link #COMMAND_REWIND}, {@link
* #COMMAND_FAST_FORWARD}, {@link #COMMAND_SKIP_TO_PREVIOUS}, {@link #COMMAND_SKIP_TO_NEXT} or
* {@link #COMMAND_SET_CAPTIONING_ENABLED}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({TYPE_USE})
@LongDef({
COMMAND_PLAY,
COMMAND_PAUSE,
COMMAND_STOP,
COMMAND_REWIND,
COMMAND_FAST_FORWARD,
COMMAND_SKIP_TO_PREVIOUS,
COMMAND_SKIP_TO_NEXT,
COMMAND_SET_CAPTIONING_ENABLED
})
@interface Command {}
/** The command to start playback. */
long COMMAND_PLAY = PlaybackStateCompat.ACTION_PLAY;
/** The command to pause playback. */
long COMMAND_PAUSE = PlaybackStateCompat.ACTION_PAUSE;
/** The command to stop playback. */
long COMMAND_STOP = PlaybackStateCompat.ACTION_STOP;
/** The command to rewind. */
long COMMAND_REWIND = PlaybackStateCompat.ACTION_REWIND;
/** The command to fast forward. */
long COMMAND_FAST_FORWARD = PlaybackStateCompat.ACTION_FAST_FORWARD;
/** The command to skip to the previous item in the queue. */
long COMMAND_SKIP_TO_PREVIOUS = PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
/** The command to skip to the next item in the queue. */
long COMMAND_SKIP_TO_NEXT = PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
/** The command to set captioning enabled. */
long COMMAND_SET_CAPTIONING_ENABLED = PlaybackStateCompat.ACTION_SET_CAPTIONING_ENABLED;
/**
* Creates a {@link NotificationCompat.Action} for a notification. These actions will be handled
* by the library.
*
* @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(
IconCompat icon, CharSequence title, @Command long 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 {@link MediaNotification.Provider#handleCustomAction notification provider} that
* provided them.
*
* @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#handleCustomAction
*/
NotificationCompat.Action createCustomAction(
IconCompat icon, CharSequence title, String customAction, Bundle extras);
/**
* Creates a {@link PendingIntent} for a media action that will be handled by the library.
*
* @param command The intent's command.
*/
PendingIntent createMediaActionPendingIntent(@Command long command);
}
/**
* Provides {@link 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 {@link 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 mediaController The controller of the session.
* @param actionFactory The {@link ActionFactory} for creating notification {@link
* NotificationCompat.Action actions}.
* @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(
MediaController mediaController,
ActionFactory actionFactory,
Callback onNotificationChangedCallback);
/**
* Handles a notification's custom action.
*
* @param mediaController The controller of the session.
* @param action The custom action.
* @param extras Extras set in the custom action, otherwise {@link Bundle#EMPTY}.
* @see ActionFactory#createCustomAction
*/
void handleCustomAction(MediaController mediaController, 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 sate 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 {@link androidx.media.app.NotificationCompat.MediaStyle
* media style} {@link Notification notification}.
*/
public MediaNotification(@IntRange(from = 1) int notificationId, Notification notification) {
this.notificationId = notificationId;
this.notification = checkNotNull(notification);
}
}