java.lang.Object
↳androidx.media2.MediaUtils
Gradle dependencies
compile group: 'androidx.media2', name: 'media2', version: '1.0.0-alpha04'
- groupId: androidx.media2
- artifactId: media2
- version: 1.0.0-alpha04
Artifact androidx.media2:media2:1.0.0-alpha04 it located at Google repository (https://maven.google.com/)
Androidx artifact mapping:
androidx.media2:media2 com.android.support:media2
Summary
Methods |
---|
public static java.util.List<ParcelImpl> | convertCommandButtonListToParcelImplList(java.util.List<MediaSession.CommandButton> commandButtonList)
Convert a list of MediaSession.CommandButton to a list of ParcelImpl. |
public static java.util.List<MediaItem> | convertMediaItemListToMediaItemList(java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem> items)
Convert a list of to a list of MediaItem. |
public static ParcelImplListSlice | convertMediaItemListToParcelImplListSlice(java.util.List<MediaItem> mediaItemList)
Convert a list of MediaItem to a list of ParcelImplListSlice. |
public static java.util.List<MediaItem> | convertParcelImplListSliceToMediaItemList(ParcelImplListSlice listSlice)
Convert a ParcelImplListSlice to a list of MediaItem. |
public static java.util.List<MediaItem> | convertQueueItemListToMediaItemList(java.util.List<android.support.v4.media.session.MediaSessionCompat.QueueItem> items)
Convert a list of android.support.v4.media.session.MediaSessionCompat.QueueItem to a list of MediaItem. |
public static java.util.List<MediaSession.CommandButton> | convertToCustomLayout(android.support.v4.media.session.PlaybackStateCompat state)
Converts android.support.v4.media.session.PlaybackStateCompat.CustomAction in the android.support.v4.media.session.PlaybackStateCompat to the custom layout which
is the list of the MediaSession.CommandButton. |
public static MediaLibraryService.LibraryParams | convertToLibraryParams(Context context, Bundle legacyBundle)
Converts the rootHints, option, and extra to the MediaLibraryService.LibraryParams. |
public static MediaItem | convertToMediaItem(android.support.v4.media.MediaBrowserCompat.MediaItem item)
Creates a MediaItem from the . |
public static MediaItem | convertToMediaItem(android.support.v4.media.MediaDescriptionCompat descriptionCompat)
Convert a android.support.v4.media.MediaDescriptionCompat to a MediaItem. |
public static android.support.v4.media.MediaBrowserCompat.MediaItem | convertToMediaItem(MediaItem item2)
Creates a from the MediaItem. |
public static MediaItem | convertToMediaItem(android.support.v4.media.MediaMetadataCompat metadataCompat)
Convert a android.support.v4.media.MediaMetadataCompat from the getMetadata
to a MediaItem. |
public static MediaItem | convertToMediaItem(android.support.v4.media.session.MediaSessionCompat.QueueItem item)
Convert a android.support.v4.media.session.MediaSessionCompat.QueueItem to a MediaItem. |
public static java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem> | convertToMediaItemList(java.util.List<MediaItem> items)
Convert a list of MediaItem to a list of . |
public static MediaMetadata | convertToMediaMetadata(java.lang.CharSequence queueTitle)
Creates a MediaMetadata from the java.lang.CharSequence . |
public static android.support.v4.media.MediaMetadataCompat | convertToMediaMetadataCompat(MediaMetadata metadata)
Creates a android.support.v4.media.MediaMetadataCompat from the MediaMetadata. |
public static int | convertToPlaybackStateCompatState(int playerState, int bufferingState)
Convert a SessionPlayer.PlayerState and
SessionPlayer.BuffState into . |
public static int | convertToPlayerState(android.support.v4.media.session.PlaybackStateCompat state)
Convert a android.support.v4.media.session.PlaybackStateCompat into SessionPlayer.PlayerState. |
public static java.util.List<android.support.v4.media.session.MediaSessionCompat.QueueItem> | convertToQueueItemList(java.util.List<MediaItem> items)
Convert a list of MediaItem to a list of android.support.v4.media.session.MediaSessionCompat.QueueItem . |
public static Rating | convertToRating(android.support.v4.media.RatingCompat ratingCompat)
Creates a Rating from the android.support.v4.media.RatingCompat . |
public static android.support.v4.media.RatingCompat | convertToRatingCompat(Rating rating)
Creates a android.support.v4.media.RatingCompat from the Rating. |
public static Bundle | convertToRootHints(MediaLibraryService.LibraryParams params)
Converts MediaLibraryService.LibraryParams to the root hints. |
public static SessionCommandGroup | convertToSessionCommandGroup(long sessionFlags, android.support.v4.media.session.PlaybackStateCompat state)
Converts session flags and
android.support.v4.media.session.PlaybackStateCompat to the SessionCommandGroup. |
public static android.support.v4.media.MediaDescriptionCompat | createMediaDescriptionCompat(java.lang.String mediaId)
Creates android.support.v4.media.MediaDescriptionCompat with the id |
public static VersionedParcelable | fromParcelable(ParcelImpl p)
Media2 version of ParcelUtils.fromParcelable(Parcelable). |
public static boolean | isUnparcelableBundle(Bundle bundle)
Returns whether the bundle is not parcelable. |
public static void | keepUnparcelableBundlesOnly(java.util.List<Bundle> bundles)
Removes unparcelable bundles in the given list. |
public static java.util.List<java.lang.Object> | removeNullElements(java.util.List<java.lang.Object> list)
Removes all null elements from the list and returns it. |
public static int | toBufferingState(int playbackStateCompatState)
Convert a into SessionPlayer.BuffState. |
public static ParcelImpl | toParcelable(VersionedParcelable item)
Media2 version of ParcelUtils.toParcelable(VersionedParcelable). |
public static MediaController.PlaybackInfo | toPlaybackInfo2(android.support.v4.media.session.MediaControllerCompat.PlaybackInfo info)
Convert a into
MediaController.PlaybackInfo. |
public static java.util.List<Parcelable> | truncateListBySize(java.util.List<Parcelable> list, int sizeLimitInBytes)
Return a list which consists of first N items of the given list with the same order. |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Fields
public static final java.lang.String
TAGpublic static final int
TRANSACTION_SIZE_LIMIT_IN_BYTESpublic static final java.util.concurrent.Executor
DIRECT_EXECUTORpublic static final int
VERSION_0public static final int
CURRENT_VERSIONMethods
public static android.support.v4.media.MediaBrowserCompat.MediaItem
convertToMediaItem(
MediaItem item2)
Creates a from the MediaItem.
Parameters:
item2: an item.
Returns:
The newly created media item.
public static java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem>
convertToMediaItemList(java.util.List<MediaItem> items)
Convert a list of MediaItem to a list of .
public static
MediaItem convertToMediaItem(android.support.v4.media.MediaBrowserCompat.MediaItem item)
Creates a MediaItem from the .
Parameters:
item: an item.
Returns:
The newly created media item.
public static
MediaItem convertToMediaItem(android.support.v4.media.session.MediaSessionCompat.QueueItem item)
Convert a android.support.v4.media.session.MediaSessionCompat.QueueItem
to a MediaItem.
public static
MediaItem convertToMediaItem(android.support.v4.media.MediaMetadataCompat metadataCompat)
Convert a android.support.v4.media.MediaMetadataCompat
from the getMetadata
to a MediaItem.
public static
MediaItem convertToMediaItem(android.support.v4.media.MediaDescriptionCompat descriptionCompat)
Convert a android.support.v4.media.MediaDescriptionCompat
to a MediaItem.
public static java.util.List<MediaItem>
convertMediaItemListToMediaItemList(java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem> items)
Convert a list of to a list of MediaItem.
public static java.util.List<MediaItem>
convertQueueItemListToMediaItemList(java.util.List<android.support.v4.media.session.MediaSessionCompat.QueueItem> items)
Convert a list of android.support.v4.media.session.MediaSessionCompat.QueueItem
to a list of MediaItem.
public static android.support.v4.media.MediaDescriptionCompat
createMediaDescriptionCompat(java.lang.String mediaId)
Creates android.support.v4.media.MediaDescriptionCompat
with the id
public static java.util.List<android.support.v4.media.session.MediaSessionCompat.QueueItem>
convertToQueueItemList(java.util.List<MediaItem> items)
Convert a list of MediaItem to a list of android.support.v4.media.session.MediaSessionCompat.QueueItem
. The index of the item
would be used as the queue ID to match the behavior of MediaController.
public static java.util.List<MediaItem>
convertParcelImplListSliceToMediaItemList(
ParcelImplListSlice listSlice)
Convert a ParcelImplListSlice to a list of MediaItem.
public static java.util.List<Parcelable>
truncateListBySize(java.util.List<Parcelable> list, int sizeLimitInBytes)
Return a list which consists of first N items of the given list with the same order.
N is determined as the maximum number of items whose total parcelled size is less
than sizeLimitInBytes.
public static
MediaMetadata convertToMediaMetadata(java.lang.CharSequence queueTitle)
Creates a MediaMetadata from the java.lang.CharSequence
.
public static android.support.v4.media.MediaMetadataCompat
convertToMediaMetadataCompat(
MediaMetadata metadata)
Creates a android.support.v4.media.MediaMetadataCompat
from the MediaMetadata.
Parameters:
metadata: A MediaMetadata object.
Returns:
The newly created android.support.v4.media.MediaMetadataCompat
object.
public static
Rating convertToRating(android.support.v4.media.RatingCompat ratingCompat)
Creates a Rating from the android.support.v4.media.RatingCompat
.
Parameters:
ratingCompat: A android.support.v4.media.RatingCompat
object.
Returns:
The newly created Rating object.
public static android.support.v4.media.RatingCompat
convertToRatingCompat(
Rating rating)
Creates a android.support.v4.media.RatingCompat
from the Rating.
Parameters:
rating: A Rating object.
Returns:
The newly created android.support.v4.media.RatingCompat
object.
public static java.util.List<ParcelImpl>
convertCommandButtonListToParcelImplList(java.util.List<MediaSession.CommandButton> commandButtonList)
Convert a list of MediaSession.CommandButton to a list of ParcelImpl.
public static
ParcelImplListSlice convertMediaItemListToParcelImplListSlice(java.util.List<MediaItem> mediaItemList)
Convert a list of MediaItem to a list of ParcelImplListSlice.
public static int
convertToPlaybackStateCompatState(int playerState, int bufferingState)
Convert a SessionPlayer.PlayerState and
SessionPlayer.BuffState into .
public static int
convertToPlayerState(android.support.v4.media.session.PlaybackStateCompat state)
Convert a android.support.v4.media.session.PlaybackStateCompat
into SessionPlayer.PlayerState.
public static int
toBufferingState(int playbackStateCompatState)
Convert a into SessionPlayer.BuffState.
Convert a into
MediaController.PlaybackInfo.
public static boolean
isUnparcelableBundle(Bundle bundle)
Returns whether the bundle is not parcelable.
public static void
keepUnparcelableBundlesOnly(java.util.List<Bundle> bundles)
Removes unparcelable bundles in the given list.
Converts the rootHints, option, and extra to the MediaLibraryService.LibraryParams.
Parameters:
legacyBundle:
Returns:
new LibraryParams
Converts MediaLibraryService.LibraryParams to the root hints.
Parameters:
params:
Returns:
new root hints
public static java.util.List<java.lang.Object>
removeNullElements(java.util.List<java.lang.Object> list)
Removes all null elements from the list and returns it.
Parameters:
list:
Returns:
public static
SessionCommandGroup convertToSessionCommandGroup(long sessionFlags, android.support.v4.media.session.PlaybackStateCompat state)
Converts session flags
and
android.support.v4.media.session.PlaybackStateCompat
to the SessionCommandGroup.
This ignores actions
in the
android.support.v4.media.session.PlaybackStateCompat
to workaround media apps' issues that they don't set playback
state correctly.
Parameters:
sessionFlags: session flag
state: playback state
Returns:
the converted session command group
public static java.util.List<MediaSession.CommandButton>
convertToCustomLayout(android.support.v4.media.session.PlaybackStateCompat state)
Converts android.support.v4.media.session.PlaybackStateCompat.CustomAction
in the android.support.v4.media.session.PlaybackStateCompat
to the custom layout which
is the list of the MediaSession.CommandButton.
Parameters:
state: playback state
Returns:
custom layout. Always non-null.
Media2 version of ParcelUtils.toParcelable(VersionedParcelable).
This sanitizes MediaItem's subclass information.
Parameters:
item:
Returns:
Media2 version of ParcelUtils.fromParcelable(Parcelable).
Source
/*
* Copyright 2018 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.media2;
import static android.support.v4.media.MediaDescriptionCompat.EXTRA_BT_FOLDER_TYPE;
import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS;
import static androidx.media2.MediaMetadata.BROWSABLE_TYPE_MIXED;
import static androidx.media2.MediaMetadata.BROWSABLE_TYPE_NONE;
import static androidx.media2.MediaMetadata.METADATA_KEY_ADVERTISEMENT;
import static androidx.media2.MediaMetadata.METADATA_KEY_BROWSABLE;
import static androidx.media2.MediaMetadata.METADATA_KEY_DISPLAY_DESCRIPTION;
import static androidx.media2.MediaMetadata.METADATA_KEY_DISPLAY_ICON;
import static androidx.media2.MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI;
import static androidx.media2.MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE;
import static androidx.media2.MediaMetadata.METADATA_KEY_DISPLAY_TITLE;
import static androidx.media2.MediaMetadata.METADATA_KEY_DOWNLOAD_STATUS;
import static androidx.media2.MediaMetadata.METADATA_KEY_EXTRAS;
import static androidx.media2.MediaMetadata.METADATA_KEY_MEDIA_ID;
import static androidx.media2.MediaMetadata.METADATA_KEY_MEDIA_URI;
import static androidx.media2.MediaMetadata.METADATA_KEY_PLAYABLE;
import static androidx.media2.MediaMetadata.METADATA_KEY_TITLE;
import static androidx.media2.SessionCommand.COMMAND_CODE_PLAYER_SET_SPEED;
import static androidx.media2.SessionCommand.COMMAND_VERSION_CURRENT;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaDescriptionCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.RatingCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat.QueueItem;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v4.media.session.PlaybackStateCompat.CustomAction;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.media.AudioAttributesCompat;
import androidx.media.MediaBrowserServiceCompat.BrowserRoot;
import androidx.media2.MediaLibraryService.LibraryParams;
import androidx.media2.MediaSession.CommandButton;
import androidx.versionedparcelable.ParcelImpl;
import androidx.versionedparcelable.ParcelUtils;
import androidx.versionedparcelable.VersionedParcelable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public class MediaUtils {
public static final String TAG = "MediaUtils";
public static final int TRANSACTION_SIZE_LIMIT_IN_BYTES = 256 * 1024; // 256KB
// Stub BrowserRoot for accepting any connection here.
public static final BrowserRoot sDefaultBrowserRoot =
new BrowserRoot(MediaLibraryService.SERVICE_INTERFACE, null);
public static final Executor DIRECT_EXECUTOR = new Executor() {
@Override
public void execute(Runnable command) {
command.run();
}
};
// Initial version for all Media2 APIs.
public static final int VERSION_0 = 0;
// Current version for all Media2 APIs.
public static final int CURRENT_VERSION = VERSION_0;
private static final Map<String, String> METADATA_COMPAT_KEY_TO_METADATA_KEY = new HashMap<>();
private static final Map<String, String> METADATA_KEY_TO_METADATA_COMPAT_KEY = new HashMap<>();
static {
METADATA_COMPAT_KEY_TO_METADATA_KEY.put(
MediaMetadataCompat.METADATA_KEY_ADVERTISEMENT, METADATA_KEY_ADVERTISEMENT);
METADATA_COMPAT_KEY_TO_METADATA_KEY.put(MediaMetadataCompat.METADATA_KEY_BT_FOLDER_TYPE,
METADATA_KEY_BROWSABLE);
METADATA_COMPAT_KEY_TO_METADATA_KEY.put(MediaMetadataCompat.METADATA_KEY_DOWNLOAD_STATUS,
METADATA_KEY_DOWNLOAD_STATUS);
// Invert METADATA_COMPAT_KEY_TO_METADATA_KEY to create METADATA_KEY_TO_METADATA_COMPAT_KEY.
for (Map.Entry<String, String> entry : METADATA_COMPAT_KEY_TO_METADATA_KEY.entrySet()) {
// Sanity check..
if (METADATA_KEY_TO_METADATA_COMPAT_KEY.containsKey(entry.getValue())) {
throw new RuntimeException("Shouldn't map to the same value");
}
METADATA_KEY_TO_METADATA_COMPAT_KEY.put(entry.getValue(), entry.getKey());
}
}
private MediaUtils() {
}
/**
* Creates a {@link MediaBrowserCompat.MediaItem} from the {@link MediaItem}.
*
* @param item2 an item.
* @return The newly created media item.
*/
public static MediaBrowserCompat.MediaItem convertToMediaItem(MediaItem item2) {
if (item2 == null) {
return null;
}
int flags = 0;
MediaDescriptionCompat descCompat;
MediaMetadata metadata = item2.getMetadata();
if (metadata == null) {
descCompat = new MediaDescriptionCompat.Builder()
.setMediaId(item2.getMediaId())
.build();
} else {
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder()
.setMediaId(item2.getMediaId())
.setSubtitle(metadata.getText(METADATA_KEY_DISPLAY_SUBTITLE))
.setDescription(metadata.getText(METADATA_KEY_DISPLAY_DESCRIPTION))
.setIconBitmap(metadata.getBitmap(METADATA_KEY_DISPLAY_ICON))
.setExtras(metadata.getExtras());
String title = metadata.getString(METADATA_KEY_TITLE);
if (title != null) {
builder.setTitle(title);
} else {
builder.setTitle(metadata.getString(METADATA_KEY_DISPLAY_TITLE));
}
String displayIconUri = metadata.getString(METADATA_KEY_DISPLAY_ICON_URI);
if (displayIconUri != null) {
builder.setIconUri(Uri.parse(displayIconUri));
}
String mediaUri = metadata.getString(METADATA_KEY_MEDIA_URI);
if (mediaUri != null) {
builder.setMediaUri(Uri.parse(mediaUri));
}
descCompat = builder.build();
boolean browsable = metadata.containsKey(METADATA_KEY_BROWSABLE)
&& metadata.getLong(METADATA_KEY_BROWSABLE) != BROWSABLE_TYPE_NONE;
boolean playable = metadata.getLong(METADATA_KEY_PLAYABLE) != 0;
flags = (browsable ? MediaBrowserCompat.MediaItem.FLAG_BROWSABLE : 0)
| (playable ? MediaBrowserCompat.MediaItem.FLAG_PLAYABLE : 0);
}
return new MediaBrowserCompat.MediaItem(descCompat, flags);
}
/**
* Convert a list of {@link MediaItem} to a list of {@link MediaBrowserCompat.MediaItem}.
*/
public static List<MediaBrowserCompat.MediaItem> convertToMediaItemList(List<MediaItem> items) {
if (items == null) {
return null;
}
List<MediaBrowserCompat.MediaItem> result = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
result.add(convertToMediaItem(items.get(i)));
}
return result;
}
/**
* Creates a {@link MediaItem} from the {@link MediaBrowserCompat.MediaItem}.
*
* @param item an item.
* @return The newly created media item.
*/
public static MediaItem convertToMediaItem(MediaBrowserCompat.MediaItem item) {
if (item == null) {
return null;
}
MediaMetadata metadata = convertToMediaMetadata(item.getDescription(),
item.isBrowsable(), item.isPlayable());
return new MediaItem.Builder()
.setMetadata(metadata)
.build();
}
/**
* Convert a {@link QueueItem} to a {@link MediaItem}.
*/
public static MediaItem convertToMediaItem(QueueItem item) {
if (item == null) {
return null;
}
// descriptionCompat cannot be null
MediaDescriptionCompat descriptionCompat = item.getDescription();
MediaMetadata metadata = convertToMediaMetadata(descriptionCompat, false, true);
return new MediaItem.Builder()
.setMetadata(metadata)
.build();
}
/**
* Convert a {@link MediaMetadataCompat} from the {@link MediaControllerCompat#getMetadata()}
* to a {@link MediaItem}.
*/
public static MediaItem convertToMediaItem(MediaMetadataCompat metadataCompat) {
if (metadataCompat == null) {
return null;
}
// Item is from the MediaControllerCompat, so forcefully set the playable.
MediaMetadata.Builder builder = new MediaMetadata.Builder()
.putLong(METADATA_KEY_PLAYABLE, 1);
for (String key : metadataCompat.keySet()) {
Object value = metadataCompat.getBundle().get(key);
String metadataKey = METADATA_COMPAT_KEY_TO_METADATA_KEY.containsKey(key)
? METADATA_COMPAT_KEY_TO_METADATA_KEY.get(key) : key;
if (value instanceof CharSequence) {
builder.putText(metadataKey, (CharSequence) value);
} else if (value instanceof Bitmap) {
builder.putBitmap(metadataKey, (Bitmap) value);
} else if (value instanceof Long) {
builder.putLong(metadataKey, (Long) value);
} else if ((value instanceof RatingCompat)
|| (Build.VERSION.SDK_INT >= 19 && value instanceof android.media.Rating)) {
// Must be fwk Rating or RatingCompat according to SDK versions.
// Use MediaMetadataCompat#getRating(key) to get a RatingCompat object.
try {
RatingCompat rating = metadataCompat.getRating(key);
builder.putRating(metadataKey, MediaUtils.convertToRating(rating));
} catch (Exception e) {
// Prevent from CastException in the getRating() due to the future changes.
}
}
}
return new MediaItem.Builder().setMetadata(builder.build()).build();
}
/**
* Convert a {@link MediaDescriptionCompat} to a {@link MediaItem}.
*/
public static MediaItem convertToMediaItem(MediaDescriptionCompat descriptionCompat) {
MediaMetadata metadata = convertToMediaMetadata(descriptionCompat, false, true);
if (metadata == null) {
return null;
}
return new MediaItem.Builder().setMetadata(metadata).build();
}
/**
* Convert a list of {@link MediaBrowserCompat.MediaItem} to a list of {@link MediaItem}.
*/
public static List<MediaItem> convertMediaItemListToMediaItemList(
List<MediaBrowserCompat.MediaItem> items) {
if (items == null) {
return null;
}
List<MediaItem> result = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
result.add(convertToMediaItem(items.get(i)));
}
return result;
}
/**
* Convert a list of {@link QueueItem} to a list of {@link MediaItem}.
*/
public static List<MediaItem> convertQueueItemListToMediaItemList(List<QueueItem> items) {
if (items == null) {
return null;
}
List<MediaItem> result = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
MediaItem item = convertToMediaItem(items.get(i));
if (item != null) {
result.add(item);
}
}
return result;
}
/**
* Creates {@link MediaDescriptionCompat} with the id
*/
public static MediaDescriptionCompat createMediaDescriptionCompat(String mediaId) {
if (TextUtils.isEmpty(mediaId)) {
return null;
}
return new MediaDescriptionCompat.Builder().setMediaId(mediaId).build();
}
/**
* Convert a list of {@link MediaItem} to a list of {@link QueueItem}. The index of the item
* would be used as the queue ID to match the behavior of {@link MediaController}.
*/
public static List<QueueItem> convertToQueueItemList(List<MediaItem> items) {
if (items == null) {
return null;
}
List<QueueItem> result = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
MediaItem item = items.get(i);
MediaDescriptionCompat description = (item.getMetadata() == null)
? new MediaDescriptionCompat.Builder().setMediaId(item.getMediaId()).build()
: convertToMediaMetadataCompat(item.getMetadata()).getDescription();
result.add(new QueueItem(description, i));
}
return result;
}
/**
* Convert a {@link ParcelImplListSlice} to a list of {@link MediaItem}.
*/
public static List<MediaItem> convertParcelImplListSliceToMediaItemList(
ParcelImplListSlice listSlice) {
if (listSlice == null) {
return null;
}
List<ParcelImpl> parcelImplList = listSlice.getList();
List<MediaItem> mediaItemList = new ArrayList<>();
for (int i = 0; i < parcelImplList.size(); i++) {
final ParcelImpl itemParcelImpl = parcelImplList.get(i);
if (itemParcelImpl != null) {
mediaItemList.add((MediaItem) fromParcelable(itemParcelImpl));
}
}
return mediaItemList;
}
/**
* Return a list which consists of first {@code N} items of the given list with the same order.
* {@code N} is determined as the maximum number of items whose total parcelled size is less
* than {@param sizeLimitInBytes}.
*/
public static <T extends Parcelable> List<T> truncateListBySize(final List<T> list,
final int sizeLimitInBytes) {
if (list == null) {
return null;
}
List<T> result = new ArrayList<>();
Parcel parcel = Parcel.obtain();
for (int i = 0; i < list.size(); i++) {
// Calculate the size.
T item = list.get(i);
parcel.writeParcelable(item, 0);
if (parcel.dataSize() < sizeLimitInBytes) {
result.add(item);
} else {
break;
}
}
parcel.recycle();
return result;
}
/**
* Creates a {@link MediaMetadata} from the {@link MediaDescriptionCompat}.
*
* @param descCompat A {@link MediaDescriptionCompat} object.
* @param browsable {@code true} if it's from {@link MediaBrowserCompat.MediaItem} with
* browsable flag.
* @param playable {@code true} if it's from {@link MediaBrowserCompat.MediaItem} with
* playable flag, or from {@link QueueItem}.
* @return
*/
private static MediaMetadata convertToMediaMetadata(MediaDescriptionCompat descCompat,
boolean browsable, boolean playable) {
if (descCompat == null) {
return null;
}
MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder();
metadataBuilder.putString(METADATA_KEY_MEDIA_ID, descCompat.getMediaId());
CharSequence title = descCompat.getTitle();
if (title != null) {
metadataBuilder.putText(METADATA_KEY_DISPLAY_TITLE, title);
}
CharSequence description = descCompat.getDescription();
if (description != null) {
metadataBuilder.putText(METADATA_KEY_DISPLAY_DESCRIPTION, descCompat.getDescription());
}
CharSequence subtitle = descCompat.getSubtitle();
if (subtitle != null) {
metadataBuilder.putText(METADATA_KEY_DISPLAY_SUBTITLE, subtitle);
}
Bitmap icon = descCompat.getIconBitmap();
if (icon != null) {
metadataBuilder.putBitmap(METADATA_KEY_DISPLAY_ICON, icon);
}
Uri iconUri = descCompat.getIconUri();
if (iconUri != null) {
metadataBuilder.putText(METADATA_KEY_DISPLAY_ICON_URI, iconUri.toString());
}
Bundle bundle = descCompat.getExtras();
if (bundle != null) {
metadataBuilder.setExtras(bundle);
}
Uri mediaUri = descCompat.getMediaUri();
if (mediaUri != null) {
metadataBuilder.putText(METADATA_KEY_MEDIA_URI, mediaUri.toString());
}
if (bundle != null && bundle.containsKey(EXTRA_BT_FOLDER_TYPE)) {
metadataBuilder.putLong(METADATA_KEY_BROWSABLE,
bundle.getLong(EXTRA_BT_FOLDER_TYPE));
} else if (browsable) {
metadataBuilder.putLong(METADATA_KEY_BROWSABLE, BROWSABLE_TYPE_MIXED);
} else {
metadataBuilder.putLong(METADATA_KEY_BROWSABLE, BROWSABLE_TYPE_NONE);
}
metadataBuilder.putLong(METADATA_KEY_PLAYABLE, playable ? 1 : 0);
return metadataBuilder.build();
}
/**
* Creates a {@link MediaMetadata} from the {@link CharSequence}.
*/
public static MediaMetadata convertToMediaMetadata(CharSequence queueTitle) {
if (queueTitle == null) {
return null;
}
return new MediaMetadata.Builder()
.putString(METADATA_KEY_TITLE, queueTitle.toString())
.putLong(METADATA_KEY_BROWSABLE, BROWSABLE_TYPE_MIXED)
.putLong(METADATA_KEY_PLAYABLE, 1)
.build();
}
/**
* Creates a {@link MediaMetadataCompat} from the {@link MediaMetadata}.
*
* @param metadata A {@link MediaMetadata} object.
* @return The newly created {@link MediaMetadataCompat} object.
*/
public static MediaMetadataCompat convertToMediaMetadataCompat(MediaMetadata metadata) {
if (metadata == null) {
return null;
}
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
for (String key : metadata.keySet()) {
String compatKey = METADATA_KEY_TO_METADATA_COMPAT_KEY.containsKey(key)
? METADATA_KEY_TO_METADATA_COMPAT_KEY.get(key) : key;
Object value = metadata.getObject(key);
if (value instanceof CharSequence) {
builder.putText(compatKey, (CharSequence) value);
} else if (value instanceof Bitmap) {
builder.putBitmap(compatKey, (Bitmap) value);
} else if (value instanceof Long) {
builder.putLong(compatKey, (Long) value);
} else if (value instanceof Bundle && !TextUtils.equals(key, METADATA_KEY_EXTRAS)) {
// Must be Bundle which contains a Rating.
// Use MediaMetadata#getRating(key) to get a Rating object.
try {
Rating rating = metadata.getRating(key);
builder.putRating(compatKey, MediaUtils.convertToRatingCompat(rating));
} catch (Exception e) {
// Prevent from CastException in the getRating() due to the future changes.
}
}
}
return builder.build();
}
/**
* Creates a {@link Rating} from the {@link RatingCompat}.
*
* @param ratingCompat A {@link RatingCompat} object.
* @return The newly created {@link Rating} object.
*/
public static Rating convertToRating(RatingCompat ratingCompat) {
if (ratingCompat == null) {
return null;
}
switch (ratingCompat.getRatingStyle()) {
case RatingCompat.RATING_3_STARS:
return ratingCompat.isRated()
? new StarRating(3, ratingCompat.getStarRating()) : new StarRating(3);
case RatingCompat.RATING_4_STARS:
return ratingCompat.isRated()
? new StarRating(4, ratingCompat.getStarRating()) : new StarRating(4);
case RatingCompat.RATING_5_STARS:
return ratingCompat.isRated()
? new StarRating(5, ratingCompat.getStarRating()) : new StarRating(5);
case RatingCompat.RATING_HEART:
return ratingCompat.isRated()
? new HeartRating(ratingCompat.hasHeart()) : new HeartRating();
case RatingCompat.RATING_THUMB_UP_DOWN:
return ratingCompat.isRated()
? new ThumbRating(ratingCompat.isThumbUp()) : new ThumbRating();
case RatingCompat.RATING_PERCENTAGE:
return ratingCompat.isRated()
? new PercentageRating(ratingCompat.getPercentRating())
: new PercentageRating();
default:
return null;
}
}
/**
* Creates a {@link RatingCompat} from the {@link Rating}.
*
* @param rating A {@link Rating} object.
* @return The newly created {@link RatingCompat} object.
*/
@SuppressLint("WrongConstant") // for @StarStyle
public static RatingCompat convertToRatingCompat(Rating rating) {
if (rating == null) {
return null;
}
int ratingCompatStyle = getRatingCompatStyle(rating);
if (!rating.isRated()) {
return RatingCompat.newUnratedRating(ratingCompatStyle);
}
switch (ratingCompatStyle) {
case RatingCompat.RATING_3_STARS:
case RatingCompat.RATING_4_STARS:
case RatingCompat.RATING_5_STARS:
return RatingCompat.newStarRating(
ratingCompatStyle, ((StarRating) rating).getStarRating());
case RatingCompat.RATING_HEART:
return RatingCompat.newHeartRating(((HeartRating) rating).hasHeart());
case RatingCompat.RATING_THUMB_UP_DOWN:
return RatingCompat.newThumbRating(((ThumbRating) rating).isThumbUp());
case RatingCompat.RATING_PERCENTAGE:
return RatingCompat.newPercentageRating(
((PercentageRating) rating).getPercentRating());
default:
return null;
}
}
/**
* Convert a list of {@link CommandButton} to a list of {@link ParcelImpl}.
*/
public static List<ParcelImpl> convertCommandButtonListToParcelImplList(
List<CommandButton> commandButtonList) {
if (commandButtonList == null) {
return null;
}
List<ParcelImpl> parcelImplList = new ArrayList<>();
for (int i = 0; i < commandButtonList.size(); i++) {
final CommandButton commandButton = commandButtonList.get(i);
parcelImplList.add(toParcelable(commandButton));
}
return parcelImplList;
}
/**
* Convert a list of {@link MediaItem} to a list of {@link ParcelImplListSlice}.
*/
public static ParcelImplListSlice convertMediaItemListToParcelImplListSlice(
List<MediaItem> mediaItemList) {
if (mediaItemList == null) {
return null;
}
List<ParcelImpl> itemParcelableList = new ArrayList<>();
for (int i = 0; i < mediaItemList.size(); i++) {
final MediaItem item = mediaItemList.get(i);
if (item != null) {
final ParcelImpl itemParcelImpl = toParcelable(item);
itemParcelableList.add(itemParcelImpl);
}
}
return new ParcelImplListSlice(itemParcelableList);
}
/**
* Convert a {@link SessionPlayer.PlayerState} and
* {@link SessionPlayer.BuffState} into {@link PlaybackStateCompat.State}.
*/
public static int convertToPlaybackStateCompatState(int playerState, int bufferingState) {
switch (playerState) {
case SessionPlayer.PLAYER_STATE_PLAYING:
switch (bufferingState) {
case SessionPlayer.BUFFERING_STATE_BUFFERING_AND_STARVED:
return PlaybackStateCompat.STATE_BUFFERING;
}
return PlaybackStateCompat.STATE_PLAYING;
case SessionPlayer.PLAYER_STATE_PAUSED:
return PlaybackStateCompat.STATE_PAUSED;
case SessionPlayer.PLAYER_STATE_IDLE:
return PlaybackStateCompat.STATE_NONE;
case SessionPlayer.PLAYER_STATE_ERROR:
return PlaybackStateCompat.STATE_ERROR;
}
// For unknown value
return PlaybackStateCompat.STATE_ERROR;
}
/**
* Convert a {@link PlaybackStateCompat} into {@link SessionPlayer.PlayerState}.
*/
public static int convertToPlayerState(PlaybackStateCompat state) {
if (state == null) {
return SessionPlayer.PLAYER_STATE_IDLE;
}
switch (state.getState()) {
case PlaybackStateCompat.STATE_ERROR:
return SessionPlayer.PLAYER_STATE_ERROR;
case PlaybackStateCompat.STATE_NONE:
return SessionPlayer.PLAYER_STATE_IDLE;
case PlaybackStateCompat.STATE_PAUSED:
case PlaybackStateCompat.STATE_STOPPED:
case PlaybackStateCompat.STATE_BUFFERING: // means paused for buffering.
return SessionPlayer.PLAYER_STATE_PAUSED;
case PlaybackStateCompat.STATE_FAST_FORWARDING:
case PlaybackStateCompat.STATE_PLAYING:
case PlaybackStateCompat.STATE_REWINDING:
case PlaybackStateCompat.STATE_SKIPPING_TO_NEXT:
case PlaybackStateCompat.STATE_SKIPPING_TO_PREVIOUS:
case PlaybackStateCompat.STATE_SKIPPING_TO_QUEUE_ITEM:
case PlaybackStateCompat.STATE_CONNECTING: // Note: there's no perfect match for this.
return SessionPlayer.PLAYER_STATE_PLAYING;
}
return SessionPlayer.PLAYER_STATE_ERROR;
}
/**
* Convert a {@link PlaybackStateCompat.State} into {@link SessionPlayer.BuffState}.
*/
// Note: there's no perfect match for this.
public static int toBufferingState(int playbackStateCompatState) {
switch (playbackStateCompatState) {
case PlaybackStateCompat.STATE_BUFFERING:
return SessionPlayer.BUFFERING_STATE_BUFFERING_AND_STARVED;
case PlaybackStateCompat.STATE_PLAYING:
return SessionPlayer.BUFFERING_STATE_COMPLETE;
default:
return SessionPlayer.BUFFERING_STATE_UNKNOWN;
}
}
/**
* Convert a {@link MediaControllerCompat.PlaybackInfo} into
* {@link MediaController.PlaybackInfo}.
*/
public static MediaController.PlaybackInfo toPlaybackInfo2(
MediaControllerCompat.PlaybackInfo info) {
return MediaController.PlaybackInfo.createPlaybackInfo(info.getPlaybackType(),
new AudioAttributesCompat.Builder()
.setLegacyStreamType(info.getAudioStream()).build(),
info.getVolumeControl(), info.getMaxVolume(), info.getCurrentVolume());
}
/**
* Returns whether the bundle is not parcelable.
*/
public static boolean isUnparcelableBundle(Bundle bundle) {
if (bundle == null) {
return false;
}
bundle.setClassLoader(MediaUtils.class.getClassLoader());
try {
bundle.size();
} catch (Exception e) {
return true;
}
return false;
}
/**
* Removes unparcelable bundles in the given list.
*/
public static void keepUnparcelableBundlesOnly(final List<Bundle> bundles) {
if (bundles == null) {
return;
}
for (int i = bundles.size() - 1; i >= 0; --i) {
Bundle bundle = bundles.get(i);
if (isUnparcelableBundle(bundle)) {
bundles.remove(i);
}
}
}
private static @RatingCompat.Style int getRatingCompatStyle(Rating rating) {
if (rating instanceof HeartRating) {
return RatingCompat.RATING_HEART;
} else if (rating instanceof ThumbRating) {
return RatingCompat.RATING_THUMB_UP_DOWN;
} else if (rating instanceof StarRating) {
switch (((StarRating) rating).getMaxStars()) {
case 3:
return RatingCompat.RATING_3_STARS;
case 4:
return RatingCompat.RATING_4_STARS;
case 5:
return RatingCompat.RATING_5_STARS;
}
} else if (rating instanceof PercentageRating) {
return RatingCompat.RATING_PERCENTAGE;
}
return RatingCompat.RATING_NONE;
}
/**
* Converts the rootHints, option, and extra to the {@link LibraryParams}.
*
* @param legacyBundle
* @return new LibraryParams
*/
public static LibraryParams convertToLibraryParams(Context context, Bundle legacyBundle) {
if (legacyBundle == null) {
return null;
}
try {
legacyBundle.setClassLoader(context.getClassLoader());
return new LibraryParams.Builder().setExtras(legacyBundle)
.setRecent(legacyBundle.getBoolean(BrowserRoot.EXTRA_RECENT))
.setOffline(legacyBundle.getBoolean(BrowserRoot.EXTRA_OFFLINE))
.setSuggested(legacyBundle.getBoolean(BrowserRoot.EXTRA_SUGGESTED))
.build();
} catch (Exception e) {
// Failure when unpacking the legacy bundle.
return new LibraryParams.Builder().setExtras(legacyBundle).build();
}
}
/**
* Converts {@link LibraryParams} to the root hints.
*
* @param params
* @return new root hints
*/
public static Bundle convertToRootHints(LibraryParams params) {
if (params == null) {
return null;
}
Bundle rootHints = (params.getExtras() == null)
? new Bundle() : new Bundle(params.getExtras());
rootHints.putBoolean(BrowserRoot.EXTRA_RECENT, params.isRecent());
rootHints.putBoolean(BrowserRoot.EXTRA_OFFLINE, params.isOffline());
rootHints.putBoolean(BrowserRoot.EXTRA_SUGGESTED, params.isSuggested());
return rootHints;
}
/**
* Removes all null elements from the list and returns it.
*
* @param list
* @return
*/
public static <T> List<T> removeNullElements(@Nullable List<T> list) {
if (list == null) {
return null;
}
List<T> newList = new ArrayList<>();
for (T item : list) {
if (item != null) {
newList.add(item);
}
}
return newList;
}
/**
* Converts {@link MediaControllerCompat#getFlags() session flags} and
* {@link PlaybackStateCompat} to the {@link SessionCommandGroup}.
* <p>
* This ignores {@link PlaybackStateCompat#getActions() actions} in the
* {@link PlaybackStateCompat} to workaround media apps' issues that they don't set playback
* state correctly.
*
* @param sessionFlags session flag
* @param state playback state
* @return the converted session command group
*/
@NonNull
public static SessionCommandGroup convertToSessionCommandGroup(long sessionFlags,
PlaybackStateCompat state) {
SessionCommandGroup.Builder commandsBuilder = new SessionCommandGroup.Builder();
boolean includePlaylistCommands = (sessionFlags & FLAG_HANDLES_QUEUE_COMMANDS) != 0;
commandsBuilder.addAllPlayerCommands(COMMAND_VERSION_CURRENT, includePlaylistCommands);
commandsBuilder.addAllVolumeCommands(COMMAND_VERSION_CURRENT);
commandsBuilder.addAllSessionCommands(COMMAND_VERSION_CURRENT);
commandsBuilder.removeCommand(COMMAND_CODE_PLAYER_SET_SPEED);
if (state != null && state.getCustomActions() != null) {
for (CustomAction customAction : state.getCustomActions()) {
commandsBuilder.addCommand(
new SessionCommand(customAction.getAction(), customAction.getExtras()));
}
}
return commandsBuilder.build();
}
/**
* Converts {@link CustomAction} in the {@link PlaybackStateCompat} to the custom layout which
* is the list of the {@link CommandButton}.
*
* @param state playback state
* @return custom layout. Always non-null.
*/
@NonNull
public static List<CommandButton> convertToCustomLayout(PlaybackStateCompat state) {
List<CommandButton> layout = new ArrayList<>();
if (state == null) {
return layout;
}
for (CustomAction action : state.getCustomActions()) {
CommandButton button = new CommandButton.Builder()
.setCommand(new SessionCommand(action.getAction(), action.getExtras()))
.setDisplayName(action.getName())
.setEnabled(true)
.setIconResId(action.getIcon()).build();
layout.add(button);
}
return layout;
}
/**
* Media2 version of {@link ParcelUtils#toParcelable(VersionedParcelable)}.
* <p>
* This sanitizes {@link MediaItem}'s subclass information.
*
* @param item
* @return
*/
@SuppressLint("RestrictedApi")
public static ParcelImpl toParcelable(VersionedParcelable item) {
if (item instanceof MediaItem) {
return new MediaItemParcelImpl((MediaItem) item);
}
return (ParcelImpl) ParcelUtils.toParcelable(item);
}
/**
* Media2 version of {@link ParcelUtils#fromParcelable(Parcelable)}.
*/
@SuppressWarnings("TypeParameterUnusedInFormals")
@SuppressLint("RestrictedApi")
public static <T extends VersionedParcelable> T fromParcelable(ParcelImpl p) {
return ParcelUtils.<T>fromParcelable(p);
}
private static class MediaItemParcelImpl extends ParcelImpl {
private final MediaItem mItem;
@SuppressLint("RestrictedApi")
MediaItemParcelImpl(MediaItem item) {
// Up-cast (possibly MediaItem's subclass object) item to MediaItem for the
// writeToParcel(). The copied media item will be only used when it's sent across the
// process.
super(new MediaItem(item));
// Keeps the original copy for local binder to send the original item.
// When local binder is used (i.e. binder call happens in a single process),
// writeToParcel() wouldn't happen for the Parcelable object and the same object will
// be sent through the binder call.
mItem = item;
}
@Override
public MediaItem getVersionedParcel() {
return mItem;
}
}
}