android auto
This commit is contained in:
parent
6d84ad1028
commit
e8cb0f5274
11 changed files with 196 additions and 190 deletions
|
@ -30,6 +30,7 @@ public class AutoMediaIDHelper {
|
|||
public static final String MEDIA_ID_MUSICS_BY_PLAYLIST = "__BY_PLAYLIST__";
|
||||
public static final String MEDIA_ID_MUSICS_BY_ALBUM = "__BY_ALBUM__";
|
||||
public static final String MEDIA_ID_MUSICS_BY_ARTIST = "__BY_ARTIST__";
|
||||
public static final String MEDIA_ID_MUSICS_BY_GENRE = "__BY_GENRE__";
|
||||
public static final String MEDIA_ID_MUSICS_BY_SHUFFLE = "__BY_SHUFFLE__";
|
||||
public static final String MEDIA_ID_MUSICS_BY_QUEUE = "__BY_QUEUE__";
|
||||
|
||||
|
|
|
@ -32,19 +32,19 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
|
||||
import code.name.monkey.appthemehelper.ThemeStore;
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.AlbumLoader;
|
||||
import code.name.monkey.retromusic.loaders.ArtistLoader;
|
||||
import code.name.monkey.retromusic.loaders.GenreLoader;
|
||||
import code.name.monkey.retromusic.loaders.PlaylistLoader;
|
||||
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader;
|
||||
import code.name.monkey.retromusic.model.Album;
|
||||
import code.name.monkey.retromusic.model.Artist;
|
||||
import code.name.monkey.retromusic.model.Genre;
|
||||
import code.name.monkey.retromusic.model.Playlist;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.providers.MusicPlaybackQueueStore;
|
||||
import code.name.monkey.retromusic.service.MusicService;
|
||||
import code.name.monkey.retromusic.util.ImageUtil;
|
||||
|
||||
/**
|
||||
* Created by Beesham Sarendranauth (Beesham)
|
||||
|
@ -57,7 +57,10 @@ public class AutoMusicProvider {
|
|||
private static final int PATH_SEGMENT_ID = 0;
|
||||
private static final int PATH_SEGMENT_TITLE = 1;
|
||||
private static final int PATH_SEGMENT_ARTIST = 2;
|
||||
private static final int PATH_SEGMENT_GENRE = 4;
|
||||
private static final int PATH_SEGMENT_ALBUM_ID = 5;
|
||||
|
||||
private WeakReference<MusicService> mMusicService;
|
||||
|
||||
// Categorized caches for music data
|
||||
private ConcurrentMap<Integer, Uri> mMusicListByHistory;
|
||||
|
@ -65,6 +68,7 @@ public class AutoMusicProvider {
|
|||
private ConcurrentMap<Integer, Uri> mMusicListByPlaylist;
|
||||
private ConcurrentMap<Integer, Uri> mMusicListByAlbum;
|
||||
private ConcurrentMap<Integer, Uri> mMusicListByArtist;
|
||||
private ConcurrentMap<Integer, Uri> mMusicListByGenre;
|
||||
|
||||
private Uri defaultAlbumArtUri;
|
||||
|
||||
|
@ -79,12 +83,17 @@ public class AutoMusicProvider {
|
|||
mMusicListByPlaylist = new ConcurrentSkipListMap<>();
|
||||
mMusicListByAlbum = new ConcurrentSkipListMap<>();
|
||||
mMusicListByArtist = new ConcurrentSkipListMap<>();
|
||||
mMusicListByGenre = new ConcurrentSkipListMap<>();
|
||||
|
||||
defaultAlbumArtUri = Uri.parse("android.resource://" +
|
||||
mContext.getPackageName() + "/drawable/" +
|
||||
mContext.getResources().getResourceEntryName(R.drawable.default_album_art));
|
||||
}
|
||||
|
||||
public void setMusicService(MusicService service) {
|
||||
mMusicService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
public Iterable<Uri> getHistory() {
|
||||
if (mCurrentState != State.INITIALIZED) {
|
||||
return Collections.emptyList();
|
||||
|
@ -120,6 +129,13 @@ public class AutoMusicProvider {
|
|||
return mMusicListByArtist.values();
|
||||
}
|
||||
|
||||
public Iterable<Uri> getGenres() {
|
||||
if (mCurrentState != State.INITIALIZED) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return mMusicListByGenre.values();
|
||||
}
|
||||
|
||||
public Iterable<Uri> getQueue() {
|
||||
if (mCurrentState != State.INITIALIZED) {
|
||||
return Collections.emptyList();
|
||||
|
@ -128,8 +144,9 @@ public class AutoMusicProvider {
|
|||
// Re-built every time since the queue updates often
|
||||
ConcurrentMap<Integer, Uri> queueList = new ConcurrentSkipListMap<>();
|
||||
|
||||
if (mContext != null) {
|
||||
final List<Song> songs = MusicPlaybackQueueStore.getInstance(mContext).getSavedOriginalPlayingQueue();
|
||||
final MusicService service = mMusicService.get();
|
||||
if (service != null) {
|
||||
final List<Song> songs = MusicPlaybackQueueStore.getInstance(service).getSavedOriginalPlayingQueue();
|
||||
for (int i = 0; i < songs.size(); i++) {
|
||||
final Song s = songs.get(i);
|
||||
Uri.Builder topTracksData = Uri.parse(BASE_URI).buildUpon();
|
||||
|
@ -260,6 +277,21 @@ public class AutoMusicProvider {
|
|||
mMusicListByArtist = newMusicListByArtist;
|
||||
}
|
||||
|
||||
private synchronized void buildListsByGenre() {
|
||||
ConcurrentMap<Integer, Uri> newMusicListByGenre = new ConcurrentSkipListMap<>();
|
||||
|
||||
final List<Genre> genres = GenreLoader.INSTANCE.getAllGenres(mContext);
|
||||
for (int i = 0; i < genres.size(); i++) {
|
||||
final Genre p = genres.get(i);
|
||||
Uri.Builder playlistData = Uri.parse(BASE_URI).buildUpon();
|
||||
playlistData.appendPath(String.valueOf(p.getId()))
|
||||
.appendPath(p.getName());
|
||||
newMusicListByGenre.putIfAbsent(i, playlistData.build());
|
||||
}
|
||||
|
||||
mMusicListByGenre = newMusicListByGenre;
|
||||
}
|
||||
|
||||
private synchronized void retrieveMedia() {
|
||||
try {
|
||||
if (mCurrentState == State.NON_INITIALIZED) {
|
||||
|
@ -270,6 +302,7 @@ public class AutoMusicProvider {
|
|||
buildListsByPlaylist();
|
||||
buildListsByAlbum();
|
||||
buildListsByArtist();
|
||||
buildListsByGenre();
|
||||
mCurrentState = State.INITIALIZED;
|
||||
}
|
||||
} finally {
|
||||
|
@ -290,13 +323,31 @@ public class AutoMusicProvider {
|
|||
|
||||
switch (mediaId) {
|
||||
case AutoMediaIDHelper.MEDIA_ID_ROOT:
|
||||
mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_HISTORY, resources.getString(R.string.history_label), R.drawable.ic_access_time_white_24dp));
|
||||
mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_TOP_TRACKS, resources.getString(R.string.top_tracks_label), R.drawable.ic_trending_up_white_24dp));
|
||||
mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_PLAYLIST, resources.getString(R.string.playlists_label), R.drawable.ic_queue_music_white_24dp));
|
||||
mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM, resources.getString(R.string.albums_label), R.drawable.ic_album_white_24dp));
|
||||
mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST, resources.getString(R.string.artists_label), R.drawable.ic_artist_white_24dp));
|
||||
mediaItems.add(createPlayableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_SHUFFLE, resources.getString(R.string.action_shuffle_all), R.drawable.ic_shuffle_white_24dp, null));
|
||||
mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE, resources.getString(R.string.queue_label), R.drawable.ic_playlist_play_white_24dp));
|
||||
//mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_HISTORY, resources.getString(R.string.history_label), R.drawable.ic_access_time_white_24dp));
|
||||
//mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_TOP_TRACKS, resources.getString(R.string.top_tracks_label), R.drawable.ic_trending_up_white_24dp));
|
||||
//mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_PLAYLIST, resources.getString(R.string.playlists_label), R.drawable.ic_queue_music_white_24dp));
|
||||
mediaItems.add(
|
||||
createBrowsableMediaItem(
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM,
|
||||
resources.getString(R.string.albums_label),
|
||||
R.drawable.ic_album_white_24dp));
|
||||
mediaItems.add(
|
||||
createBrowsableMediaItem(
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST,
|
||||
resources.getString(R.string.artists_label),
|
||||
R.drawable.ic_artist_white_24dp));
|
||||
mediaItems.add(
|
||||
createBrowsableMediaItem(
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_GENRE,
|
||||
resources.getString(R.string.genres_label),
|
||||
R.drawable.ic_guitar_acoustic_white_24dp));
|
||||
mediaItems.add(
|
||||
createPlayableMediaItem(
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_SHUFFLE,
|
||||
resources.getString(R.string.action_shuffle_all),
|
||||
R.drawable.ic_shuffle_white_24dp,
|
||||
""));
|
||||
//mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE, resources.getString(R.string.queue_label), R.drawable.ic_playlist_play_white_24dp));
|
||||
break;
|
||||
|
||||
case AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_HISTORY:
|
||||
|
@ -328,6 +379,11 @@ public class AutoMusicProvider {
|
|||
mediaItems.add(createPlayableMediaItem(mediaId, uri, uri.getPathSegments().get(PATH_SEGMENT_ARTIST), null));
|
||||
}
|
||||
break;
|
||||
case AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_GENRE:
|
||||
for (final Uri uri : getGenres()) {
|
||||
mediaItems.add(createPlayableMediaItem(mediaId, uri, uri.getPathSegments().get(PATH_SEGMENT_TITLE), null));
|
||||
}
|
||||
break;
|
||||
|
||||
case AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE:
|
||||
// TODO: auto scroll to current track, indicate that it's playing
|
||||
|
@ -343,21 +399,25 @@ public class AutoMusicProvider {
|
|||
private MediaBrowserCompat.MediaItem createBrowsableMediaItem(String mediaId, String title, int iconDrawableId) {
|
||||
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder();
|
||||
builder.setMediaId(mediaId)
|
||||
.setTitle(title)
|
||||
.setIconBitmap(ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(mContext, iconDrawableId, ThemeStore.Companion.textColorSecondary(mContext))));
|
||||
.setTitle(title);
|
||||
|
||||
return new MediaBrowserCompat.MediaItem(builder.build(),
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);
|
||||
}
|
||||
|
||||
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId, Uri musicSelection,
|
||||
String title, @Nullable String subtitle) {
|
||||
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId,
|
||||
Uri musicSelection,
|
||||
String title,
|
||||
@Nullable String subtitle) {
|
||||
return createPlayableMediaItem(mediaId, musicSelection, title, subtitle, null, null);
|
||||
}
|
||||
|
||||
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId, Uri musicSelection,
|
||||
String title, @Nullable String subtitle,
|
||||
@Nullable Bitmap albumArt, @Nullable Resources resources) {
|
||||
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId,
|
||||
Uri musicSelection,
|
||||
String title,
|
||||
@Nullable String subtitle,
|
||||
@Nullable Bitmap albumArt,
|
||||
@Nullable Resources resources) {
|
||||
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder();
|
||||
builder.setMediaId(AutoMediaIDHelper.createMediaID(musicSelection.getPathSegments().get(PATH_SEGMENT_ID), mediaId))
|
||||
.setTitle(title);
|
||||
|
@ -378,12 +438,13 @@ public class AutoMusicProvider {
|
|||
MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
|
||||
}
|
||||
|
||||
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId, String title, int iconDrawableId,
|
||||
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId,
|
||||
String title,
|
||||
int iconDrawableId,
|
||||
@Nullable String subtitle) {
|
||||
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder()
|
||||
.setMediaId(mediaId)
|
||||
.setTitle(title)
|
||||
.setIconBitmap(ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(mContext, iconDrawableId, ThemeStore.Companion.textColorSecondary(mContext))));
|
||||
.setTitle(title);
|
||||
|
||||
if (subtitle != null) {
|
||||
builder.setSubtitle(subtitle);
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
package code.name.monkey.retromusic.auto;
|
||||
|
||||
import android.app.UiModeManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
|
||||
public class CarHelper {
|
||||
|
||||
private static final String TAG = "CarHelper";
|
||||
|
||||
public static boolean isCarUiMode(Context c) {
|
||||
UiModeManager uiModeManager = (UiModeManager) c.getSystemService(Context.UI_MODE_SERVICE);
|
||||
return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR;
|
||||
}
|
||||
}
|
|
@ -92,6 +92,10 @@ class MediaSessionCallback(private val context: Context,
|
|||
songs.addAll(playlist.getSongs(context))
|
||||
openQueue(songs, 0, true)
|
||||
}
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_GENRE -> {
|
||||
songs.addAll(GenreLoader.getSongs(context, itemId))
|
||||
openQueue(songs, 0, true)
|
||||
}
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_HISTORY,
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_TOP_TRACKS,
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE -> {
|
||||
|
|
|
@ -337,8 +337,10 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
|||
PreferenceUtil.getInstance().registerOnSharedPreferenceChangedListener(this);
|
||||
|
||||
restoreState();
|
||||
|
||||
mPackageValidator = new PackageValidator(this, R.xml.allowed_media_browser_callers);
|
||||
mMusicProvider = new AutoMusicProvider(this);
|
||||
|
||||
sendBroadcast(new Intent("code.name.monkey.retromusic.RETRO_MUSIC_SERVICE_CREATED"));
|
||||
|
||||
registerHeadsetEvents();
|
||||
|
@ -352,19 +354,26 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
|||
}
|
||||
|
||||
private void setupMediaSession() {
|
||||
ComponentName mediaButtonReceiverComponentName = new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class);
|
||||
ComponentName mediaButtonReceiverComponentName = new ComponentName(
|
||||
getApplicationContext(),
|
||||
MediaButtonIntentReceiver.class);
|
||||
|
||||
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||
mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
|
||||
|
||||
|
||||
PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
|
||||
PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(
|
||||
getApplicationContext(),
|
||||
0,
|
||||
mediaButtonIntent,
|
||||
0);
|
||||
|
||||
mediaSession = new MediaSessionCompat(this,
|
||||
"RetroMusicPlayer",
|
||||
mediaButtonReceiverComponentName,
|
||||
mediaButtonReceiverPendingIntent);
|
||||
MediaSessionCallback mediasessionCallback = new MediaSessionCallback(getApplicationContext(), this);
|
||||
MediaSessionCallback mediasessionCallback = new MediaSessionCallback(
|
||||
getApplicationContext(), this);
|
||||
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
|
||||
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
|
||||
);
|
||||
|
@ -418,7 +427,7 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
|||
}
|
||||
}
|
||||
|
||||
return START_STICKY;
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
private void playFromPlaylist(Intent intent) {
|
||||
|
@ -445,21 +454,6 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
|||
}
|
||||
}
|
||||
|
||||
private void playSongs(int shuffleMode, ArrayList<Song> playlistSongs) {
|
||||
if (!playlistSongs.isEmpty()) {
|
||||
if (shuffleMode == SHUFFLE_MODE_SHUFFLE) {
|
||||
int startPosition;
|
||||
startPosition = new Random().nextInt(playlistSongs.size());
|
||||
openQueue(playlistSongs, startPosition, true);
|
||||
setShuffleMode(shuffleMode);
|
||||
} else {
|
||||
openQueue(playlistSongs, 0, true);
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
unregisterReceiver(widgetIntentReceiver);
|
||||
|
@ -478,20 +472,28 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
|||
PreferenceUtil.getInstance().unregisterOnSharedPreferenceChangedListener(this);
|
||||
wakeLock.release();
|
||||
|
||||
sendBroadcast(new Intent("code.name.monkey.retromusic.RETRO_MUSIC_MUSIC_SERVICE_DESTROYED"));
|
||||
sendBroadcast(new Intent("code.name.monkey.retromusic.RETRO_MUSIC_SERVICE_DESTROYED"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// For Android auto, need to call super, or onGetRoot won't be called.
|
||||
if (intent != null && "android.media.browse.MediaBrowserService".equals(intent.getAction())) {
|
||||
return super.onBind(intent);
|
||||
}
|
||||
return musicBind;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
|
||||
|
||||
// Check origin to ensure we're not allowing any arbitrary app to browse app contents
|
||||
if (!mPackageValidator.isKnownCaller(clientPackageName, clientUid)) {
|
||||
// Request from an untrusted package: return an empty browser root
|
||||
return new BrowserRoot(AutoMediaIDHelper.MEDIA_ID_EMPTY_ROOT, null);
|
||||
}
|
||||
|
||||
return new BrowserRoot(AutoMediaIDHelper.MEDIA_ID_ROOT, null);
|
||||
}
|
||||
|
||||
|
@ -686,10 +688,33 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
|||
.setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
||||
getSongProgressMillis(), 1);
|
||||
|
||||
setCustomAction(stateBuilder);
|
||||
|
||||
mediaSession.setPlaybackState(stateBuilder.build());
|
||||
}
|
||||
|
||||
private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) {
|
||||
int repeatIcon = R.drawable.ic_repeat_white_24dp; // REPEAT_MODE_NONE
|
||||
if (getRepeatMode() == REPEAT_MODE_THIS) {
|
||||
repeatIcon = R.drawable.ic_repeat_one_white_24dp;
|
||||
} else if (getRepeatMode() == REPEAT_MODE_ALL) {
|
||||
repeatIcon = R.drawable.ic_repeat_white_24dp;
|
||||
}
|
||||
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
|
||||
CYCLE_REPEAT, getString(R.string.action_cycle_repeat), repeatIcon)
|
||||
.build());
|
||||
|
||||
final int shuffleIcon = getShuffleMode() == SHUFFLE_MODE_NONE ? R.drawable.ic_shuffle_white_24dp : R.drawable.ic_shuffle_white_24dp;
|
||||
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
|
||||
TOGGLE_SHUFFLE, getString(R.string.action_toggle_shuffle), shuffleIcon)
|
||||
.build());
|
||||
|
||||
final int favoriteIcon = MusicUtil.isFavorite(getApplicationContext(), getCurrentSong()) ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_border_white_24dp;
|
||||
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
|
||||
TOGGLE_FAVORITE, getString(R.string.action_toggle_favorite), favoriteIcon)
|
||||
.build());
|
||||
}
|
||||
|
||||
private void updateMediaSessionMetaData() {
|
||||
final Song song = getCurrentSong();
|
||||
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.util
|
||||
|
||||
|
||||
import android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE
|
||||
import android.Manifest.permission.MEDIA_CONTENT_CONTROL
|
||||
import android.annotation.SuppressLint
|
||||
|
@ -45,7 +47,10 @@ import java.security.NoSuchAlgorithmException
|
|||
*
|
||||
* For more information, see res/xml/allowed_media_browser_callers.xml.
|
||||
*/
|
||||
class PackageValidator(context: Context, @XmlRes xmlResId: Int) {
|
||||
class PackageValidator(
|
||||
context: Context,
|
||||
@XmlRes xmlResId: Int
|
||||
) {
|
||||
private val context: Context
|
||||
private val packageManager: PackageManager
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue