android auto
parent
6d84ad1028
commit
e8cb0f5274
|
@ -13,7 +13,7 @@ android {
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
applicationId "code.name.monkey.retromusic"
|
applicationId "code.name.monkey.retromusic"
|
||||||
versionCode 352
|
versionCode 353
|
||||||
versionName '3.3.100'
|
versionName '3.3.100'
|
||||||
|
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
|
@ -2,6 +2,18 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="code.name.monkey.retromusic">
|
package="code.name.monkey.retromusic">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||||
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="com.android.vending.BILLING" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -125,25 +137,7 @@
|
||||||
android:name=".activities.saf.SAFGuideActivity"
|
android:name=".activities.saf.SAFGuideActivity"
|
||||||
android:theme="@style/Theme.Intro" />
|
android:theme="@style/Theme.Intro" />
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.max_aspect"
|
|
||||||
android:value="2.1" />
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="com.lge.support.SPLIT_WINDOW"
|
|
||||||
android:value="true" />
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="code.name.monkey.retromusic.glide.RetroMusicGlideModule"
|
|
||||||
android:value="GlideModule" />
|
|
||||||
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="com.bumptech.glide.integration.okhttp3.OkHttpGlideModule"
|
|
||||||
android:value="GlideModule" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
|
|
||||||
android:value="code.name.monkey.retromusic.cast.CastOptionsProvider" />
|
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".misc.GenericFileProvider"
|
android:name=".misc.GenericFileProvider"
|
||||||
|
@ -171,6 +165,7 @@
|
||||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".appwidgets.BootReceiver">
|
<receiver android:name=".appwidgets.BootReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
@ -260,22 +255,22 @@
|
||||||
android:name="com.google.android.gms.car.notification.SmallIcon"
|
android:name="com.google.android.gms.car.notification.SmallIcon"
|
||||||
android:resource="@drawable/ic_notification"/>
|
android:resource="@drawable/ic_notification"/>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.max_aspect"
|
||||||
|
android:value="2.1" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.lge.support.SPLIT_WINDOW"
|
||||||
|
android:value="true" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="code.name.monkey.retromusic.glide.RetroMusicGlideModule"
|
||||||
|
android:value="GlideModule" />
|
||||||
|
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.bumptech.glide.integration.okhttp3.OkHttpGlideModule"
|
||||||
|
android:value="GlideModule" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
||||||
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
|
||||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
||||||
<uses-permission android:name="com.android.vending.BILLING" />
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
||||||
|
|
||||||
<uses-feature
|
|
||||||
android:name="android.hardware.type.automotive"
|
|
||||||
android:required="true" />
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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_PLAYLIST = "__BY_PLAYLIST__";
|
||||||
public static final String MEDIA_ID_MUSICS_BY_ALBUM = "__BY_ALBUM__";
|
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_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_SHUFFLE = "__BY_SHUFFLE__";
|
||||||
public static final String MEDIA_ID_MUSICS_BY_QUEUE = "__BY_QUEUE__";
|
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.ConcurrentMap;
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
import java.util.concurrent.ConcurrentSkipListMap;
|
||||||
|
|
||||||
import code.name.monkey.appthemehelper.ThemeStore;
|
|
||||||
import code.name.monkey.retromusic.R;
|
import code.name.monkey.retromusic.R;
|
||||||
import code.name.monkey.retromusic.loaders.AlbumLoader;
|
import code.name.monkey.retromusic.loaders.AlbumLoader;
|
||||||
import code.name.monkey.retromusic.loaders.ArtistLoader;
|
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.PlaylistLoader;
|
||||||
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader;
|
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader;
|
||||||
import code.name.monkey.retromusic.model.Album;
|
import code.name.monkey.retromusic.model.Album;
|
||||||
import code.name.monkey.retromusic.model.Artist;
|
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.Playlist;
|
||||||
import code.name.monkey.retromusic.model.Song;
|
import code.name.monkey.retromusic.model.Song;
|
||||||
import code.name.monkey.retromusic.providers.MusicPlaybackQueueStore;
|
import code.name.monkey.retromusic.providers.MusicPlaybackQueueStore;
|
||||||
import code.name.monkey.retromusic.service.MusicService;
|
import code.name.monkey.retromusic.service.MusicService;
|
||||||
import code.name.monkey.retromusic.util.ImageUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Beesham Sarendranauth (Beesham)
|
* 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_ID = 0;
|
||||||
private static final int PATH_SEGMENT_TITLE = 1;
|
private static final int PATH_SEGMENT_TITLE = 1;
|
||||||
private static final int PATH_SEGMENT_ARTIST = 2;
|
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
|
// Categorized caches for music data
|
||||||
private ConcurrentMap<Integer, Uri> mMusicListByHistory;
|
private ConcurrentMap<Integer, Uri> mMusicListByHistory;
|
||||||
|
@ -65,6 +68,7 @@ public class AutoMusicProvider {
|
||||||
private ConcurrentMap<Integer, Uri> mMusicListByPlaylist;
|
private ConcurrentMap<Integer, Uri> mMusicListByPlaylist;
|
||||||
private ConcurrentMap<Integer, Uri> mMusicListByAlbum;
|
private ConcurrentMap<Integer, Uri> mMusicListByAlbum;
|
||||||
private ConcurrentMap<Integer, Uri> mMusicListByArtist;
|
private ConcurrentMap<Integer, Uri> mMusicListByArtist;
|
||||||
|
private ConcurrentMap<Integer, Uri> mMusicListByGenre;
|
||||||
|
|
||||||
private Uri defaultAlbumArtUri;
|
private Uri defaultAlbumArtUri;
|
||||||
|
|
||||||
|
@ -79,12 +83,17 @@ public class AutoMusicProvider {
|
||||||
mMusicListByPlaylist = new ConcurrentSkipListMap<>();
|
mMusicListByPlaylist = new ConcurrentSkipListMap<>();
|
||||||
mMusicListByAlbum = new ConcurrentSkipListMap<>();
|
mMusicListByAlbum = new ConcurrentSkipListMap<>();
|
||||||
mMusicListByArtist = new ConcurrentSkipListMap<>();
|
mMusicListByArtist = new ConcurrentSkipListMap<>();
|
||||||
|
mMusicListByGenre = new ConcurrentSkipListMap<>();
|
||||||
|
|
||||||
defaultAlbumArtUri = Uri.parse("android.resource://" +
|
defaultAlbumArtUri = Uri.parse("android.resource://" +
|
||||||
mContext.getPackageName() + "/drawable/" +
|
mContext.getPackageName() + "/drawable/" +
|
||||||
mContext.getResources().getResourceEntryName(R.drawable.default_album_art));
|
mContext.getResources().getResourceEntryName(R.drawable.default_album_art));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMusicService(MusicService service) {
|
||||||
|
mMusicService = new WeakReference<>(service);
|
||||||
|
}
|
||||||
|
|
||||||
public Iterable<Uri> getHistory() {
|
public Iterable<Uri> getHistory() {
|
||||||
if (mCurrentState != State.INITIALIZED) {
|
if (mCurrentState != State.INITIALIZED) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -120,6 +129,13 @@ public class AutoMusicProvider {
|
||||||
return mMusicListByArtist.values();
|
return mMusicListByArtist.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterable<Uri> getGenres() {
|
||||||
|
if (mCurrentState != State.INITIALIZED) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return mMusicListByGenre.values();
|
||||||
|
}
|
||||||
|
|
||||||
public Iterable<Uri> getQueue() {
|
public Iterable<Uri> getQueue() {
|
||||||
if (mCurrentState != State.INITIALIZED) {
|
if (mCurrentState != State.INITIALIZED) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -128,8 +144,9 @@ public class AutoMusicProvider {
|
||||||
// Re-built every time since the queue updates often
|
// Re-built every time since the queue updates often
|
||||||
ConcurrentMap<Integer, Uri> queueList = new ConcurrentSkipListMap<>();
|
ConcurrentMap<Integer, Uri> queueList = new ConcurrentSkipListMap<>();
|
||||||
|
|
||||||
if (mContext != null) {
|
final MusicService service = mMusicService.get();
|
||||||
final List<Song> songs = MusicPlaybackQueueStore.getInstance(mContext).getSavedOriginalPlayingQueue();
|
if (service != null) {
|
||||||
|
final List<Song> songs = MusicPlaybackQueueStore.getInstance(service).getSavedOriginalPlayingQueue();
|
||||||
for (int i = 0; i < songs.size(); i++) {
|
for (int i = 0; i < songs.size(); i++) {
|
||||||
final Song s = songs.get(i);
|
final Song s = songs.get(i);
|
||||||
Uri.Builder topTracksData = Uri.parse(BASE_URI).buildUpon();
|
Uri.Builder topTracksData = Uri.parse(BASE_URI).buildUpon();
|
||||||
|
@ -260,6 +277,21 @@ public class AutoMusicProvider {
|
||||||
mMusicListByArtist = newMusicListByArtist;
|
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() {
|
private synchronized void retrieveMedia() {
|
||||||
try {
|
try {
|
||||||
if (mCurrentState == State.NON_INITIALIZED) {
|
if (mCurrentState == State.NON_INITIALIZED) {
|
||||||
|
@ -270,6 +302,7 @@ public class AutoMusicProvider {
|
||||||
buildListsByPlaylist();
|
buildListsByPlaylist();
|
||||||
buildListsByAlbum();
|
buildListsByAlbum();
|
||||||
buildListsByArtist();
|
buildListsByArtist();
|
||||||
|
buildListsByGenre();
|
||||||
mCurrentState = State.INITIALIZED;
|
mCurrentState = State.INITIALIZED;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -290,13 +323,31 @@ public class AutoMusicProvider {
|
||||||
|
|
||||||
switch (mediaId) {
|
switch (mediaId) {
|
||||||
case AutoMediaIDHelper.MEDIA_ID_ROOT:
|
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_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_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_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(
|
||||||
mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST, resources.getString(R.string.artists_label), R.drawable.ic_artist_white_24dp));
|
createBrowsableMediaItem(
|
||||||
mediaItems.add(createPlayableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_SHUFFLE, resources.getString(R.string.action_shuffle_all), R.drawable.ic_shuffle_white_24dp, null));
|
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM,
|
||||||
mediaItems.add(createBrowsableMediaItem(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE, resources.getString(R.string.queue_label), R.drawable.ic_playlist_play_white_24dp));
|
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;
|
break;
|
||||||
|
|
||||||
case AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_HISTORY:
|
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));
|
mediaItems.add(createPlayableMediaItem(mediaId, uri, uri.getPathSegments().get(PATH_SEGMENT_ARTIST), null));
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE:
|
||||||
// TODO: auto scroll to current track, indicate that it's playing
|
// 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) {
|
private MediaBrowserCompat.MediaItem createBrowsableMediaItem(String mediaId, String title, int iconDrawableId) {
|
||||||
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder();
|
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder();
|
||||||
builder.setMediaId(mediaId)
|
builder.setMediaId(mediaId)
|
||||||
.setTitle(title)
|
.setTitle(title);
|
||||||
.setIconBitmap(ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(mContext, iconDrawableId, ThemeStore.Companion.textColorSecondary(mContext))));
|
|
||||||
|
|
||||||
return new MediaBrowserCompat.MediaItem(builder.build(),
|
return new MediaBrowserCompat.MediaItem(builder.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId, Uri musicSelection,
|
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId,
|
||||||
String title, @Nullable String subtitle) {
|
Uri musicSelection,
|
||||||
|
String title,
|
||||||
|
@Nullable String subtitle) {
|
||||||
return createPlayableMediaItem(mediaId, musicSelection, title, subtitle, null, null);
|
return createPlayableMediaItem(mediaId, musicSelection, title, subtitle, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId, Uri musicSelection,
|
private MediaBrowserCompat.MediaItem createPlayableMediaItem(String mediaId,
|
||||||
String title, @Nullable String subtitle,
|
Uri musicSelection,
|
||||||
@Nullable Bitmap albumArt, @Nullable Resources resources) {
|
String title,
|
||||||
|
@Nullable String subtitle,
|
||||||
|
@Nullable Bitmap albumArt,
|
||||||
|
@Nullable Resources resources) {
|
||||||
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder();
|
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder();
|
||||||
builder.setMediaId(AutoMediaIDHelper.createMediaID(musicSelection.getPathSegments().get(PATH_SEGMENT_ID), mediaId))
|
builder.setMediaId(AutoMediaIDHelper.createMediaID(musicSelection.getPathSegments().get(PATH_SEGMENT_ID), mediaId))
|
||||||
.setTitle(title);
|
.setTitle(title);
|
||||||
|
@ -378,12 +438,13 @@ public class AutoMusicProvider {
|
||||||
MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
|
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) {
|
@Nullable String subtitle) {
|
||||||
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder()
|
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder()
|
||||||
.setMediaId(mediaId)
|
.setMediaId(mediaId)
|
||||||
.setTitle(title)
|
.setTitle(title);
|
||||||
.setIconBitmap(ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(mContext, iconDrawableId, ThemeStore.Companion.textColorSecondary(mContext))));
|
|
||||||
|
|
||||||
if (subtitle != null) {
|
if (subtitle != null) {
|
||||||
builder.setSubtitle(subtitle);
|
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))
|
songs.addAll(playlist.getSongs(context))
|
||||||
openQueue(songs, 0, true)
|
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_HISTORY,
|
||||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_TOP_TRACKS,
|
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_TOP_TRACKS,
|
||||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE -> {
|
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE -> {
|
||||||
|
|
|
@ -337,8 +337,10 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
||||||
PreferenceUtil.getInstance().registerOnSharedPreferenceChangedListener(this);
|
PreferenceUtil.getInstance().registerOnSharedPreferenceChangedListener(this);
|
||||||
|
|
||||||
restoreState();
|
restoreState();
|
||||||
|
|
||||||
mPackageValidator = new PackageValidator(this, R.xml.allowed_media_browser_callers);
|
mPackageValidator = new PackageValidator(this, R.xml.allowed_media_browser_callers);
|
||||||
mMusicProvider = new AutoMusicProvider(this);
|
mMusicProvider = new AutoMusicProvider(this);
|
||||||
|
|
||||||
sendBroadcast(new Intent("code.name.monkey.retromusic.RETRO_MUSIC_SERVICE_CREATED"));
|
sendBroadcast(new Intent("code.name.monkey.retromusic.RETRO_MUSIC_SERVICE_CREATED"));
|
||||||
|
|
||||||
registerHeadsetEvents();
|
registerHeadsetEvents();
|
||||||
|
@ -352,19 +354,26 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupMediaSession() {
|
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);
|
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||||
mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
|
mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
|
||||||
|
|
||||||
|
|
||||||
PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
|
PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(
|
||||||
|
getApplicationContext(),
|
||||||
|
0,
|
||||||
|
mediaButtonIntent,
|
||||||
|
0);
|
||||||
|
|
||||||
mediaSession = new MediaSessionCompat(this,
|
mediaSession = new MediaSessionCompat(this,
|
||||||
"RetroMusicPlayer",
|
"RetroMusicPlayer",
|
||||||
mediaButtonReceiverComponentName,
|
mediaButtonReceiverComponentName,
|
||||||
mediaButtonReceiverPendingIntent);
|
mediaButtonReceiverPendingIntent);
|
||||||
MediaSessionCallback mediasessionCallback = new MediaSessionCallback(getApplicationContext(), this);
|
MediaSessionCallback mediasessionCallback = new MediaSessionCallback(
|
||||||
|
getApplicationContext(), this);
|
||||||
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
|
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
|
||||||
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
|
| 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) {
|
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
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
unregisterReceiver(widgetIntentReceiver);
|
unregisterReceiver(widgetIntentReceiver);
|
||||||
|
@ -478,20 +472,28 @@ public class MusicService extends MediaBrowserServiceCompat implements SharedPre
|
||||||
PreferenceUtil.getInstance().unregisterOnSharedPreferenceChangedListener(this);
|
PreferenceUtil.getInstance().unregisterOnSharedPreferenceChangedListener(this);
|
||||||
wakeLock.release();
|
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
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
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;
|
return musicBind;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
|
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)) {
|
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_EMPTY_ROOT, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BrowserRoot(AutoMediaIDHelper.MEDIA_ID_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,
|
.setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
||||||
getSongProgressMillis(), 1);
|
getSongProgressMillis(), 1);
|
||||||
|
|
||||||
|
setCustomAction(stateBuilder);
|
||||||
|
|
||||||
mediaSession.setPlaybackState(stateBuilder.build());
|
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() {
|
private void updateMediaSessionMetaData() {
|
||||||
final Song song = getCurrentSong();
|
final Song song = getCurrentSong();
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,10 @@
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
* See the GNU General Public License for more details.
|
* See the GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package code.name.monkey.retromusic.util
|
package code.name.monkey.retromusic.util
|
||||||
|
|
||||||
|
|
||||||
import android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE
|
import android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE
|
||||||
import android.Manifest.permission.MEDIA_CONTENT_CONTROL
|
import android.Manifest.permission.MEDIA_CONTENT_CONTROL
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
@ -45,7 +47,10 @@ import java.security.NoSuchAlgorithmException
|
||||||
*
|
*
|
||||||
* For more information, see res/xml/allowed_media_browser_callers.xml.
|
* 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 context: Context
|
||||||
private val packageManager: PackageManager
|
private val packageManager: PackageManager
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,7 @@
|
||||||
<string name="genre">Genre</string>
|
<string name="genre">Genre</string>
|
||||||
|
|
||||||
<string name="genres">Genres</string>
|
<string name="genres">Genres</string>
|
||||||
|
<string name="genres_label">Genres</string>
|
||||||
|
|
||||||
<string name="git_hub_summary">Fork the project on GitHub</string>
|
<string name="git_hub_summary">Fork the project on GitHub</string>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
Copyright (C) 2014 The Android Open Source Project
|
Copyright (C) 2017 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -18,7 +15,6 @@ limitations under the License.
|
||||||
PackageValidator by default will print to logcat (INFO level) a message with the proper base64
|
PackageValidator by default will print to logcat (INFO level) a message with the proper base64
|
||||||
version of the caller's certificate that has not been validated. You can copy from logcat and
|
version of the caller's certificate that has not been validated. You can copy from logcat and
|
||||||
paste it here.
|
paste it here.
|
||||||
|
|
||||||
Spaces and newlines are ignored.
|
Spaces and newlines are ignored.
|
||||||
-->
|
-->
|
||||||
<allowed_callers>
|
<allowed_callers>
|
||||||
|
@ -164,32 +160,6 @@ limitations under the License.
|
||||||
BKZCvlzboOEAZfx8aBKc7SezqATXpM3ZDNPsywWoyIpgmtBWoE60ih4Flf05XB+n
|
BKZCvlzboOEAZfx8aBKc7SezqATXpM3ZDNPsywWoyIpgmtBWoE60ih4Flf05XB+n
|
||||||
e7MdpSQ0Xgq9TgG1BoJP6rpC0y3Ukmc+z8AXnYYdJunNXEbv0A==
|
e7MdpSQ0Xgq9TgG1BoJP6rpC0y3Ukmc+z8AXnYYdJunNXEbv0A==
|
||||||
</signing_certificate>
|
</signing_certificate>
|
||||||
<signing_certificate
|
|
||||||
name="Media Browser Service Simulator"
|
|
||||||
package="com.google.android.mediasimulator"
|
|
||||||
release="true">
|
|
||||||
MIIDvTCCAqWgAwIBAgIJAMePnkuTQTAGMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
|
|
||||||
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
|
|
||||||
aWV3MRQwEgYDVQQKDAtHb29nbGUgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDERMA8G
|
|
||||||
A1UEAwwIZ2VhcmhlYWQwHhcNMTQwNTI3MjMwNTM0WhcNNDExMDEyMjMwNTM0WjB1
|
|
||||||
MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
|
|
||||||
bnRhaW4gVmlldzEUMBIGA1UECgwLR29vZ2xlIEluYy4xEDAOBgNVBAsMB0FuZHJv
|
|
||||||
aWQxETAPBgNVBAMMCGdlYXJoZWFkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
|
||||||
CgKCAQEA050XDkNIsVRMX2wTvVplpCu4OtnyNK2v5B7PS+DggmH2yuZiwpTurdKD
|
|
||||||
Q9R9UzxH9U4lsC+mIxXkiBYKIWNVgMtiTgxkEy7cgWvdYHgNYpFu8IxZKYDyXes+
|
|
||||||
02pfvpu63MIBD/PnvVFipo1oUrbfetj+mroEpjnA71gUS0Ok+H6XWWsmb8xFHQVM
|
|
||||||
oZWEIzsUJ2nhm8EcnPkAPfNZAG++XLPROoRQCaswyYsd42JuYAP3CwZuhDcUbMWm
|
|
||||||
k7rBi9BVQ8gmkrbwqo94A7qStLUp3NyCmlKSWHaZ05SspEPwsfctka0oXG5bhgT6
|
|
||||||
67EMCzQ+YsFN1oJRL7Qq+mMQjFJs3wIDAQABo1AwTjAdBgNVHQ4EFgQUGvBfYNeu
|
|
||||||
6JSJUnJZCiaBGsnXztswHwYDVR0jBBgwFoAUGvBfYNeu6JSJUnJZCiaBGsnXztsw
|
|
||||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAlGsDY0EPu3NBSH5k6iw/
|
|
||||||
wJh9e3xMwS17ErKGlhyWogxJMzLjAN6g0aCPHxB40IQC+8qAl+RL7VQx6oxttf0m
|
|
||||||
31yUGQPcNYbt2CxBTCAr885oLK5t2TAi5tQzhd6ZEYihWSUWUd/X8BQRouxboss9
|
|
||||||
QbBA/iIx0OpDaxiAcq7Cb67TheXZDxGuQ8fmHYbLx84pEvm3DQOB/LIMkkpQSfEC
|
|
||||||
1f+oP1zB3urPU/dSvED/LCgOdrpxZ5di7SwSyue+Vq/TZQy34tPygEzD2d8hFlh/
|
|
||||||
yfhWkMizOeIXcayVAQdNn5zpBkuay1skGOjQQ5kTbDcDzigO2R2rqn6HCd9l5Z0W
|
|
||||||
IQ==
|
|
||||||
</signing_certificate>
|
|
||||||
<signing_certificate
|
<signing_certificate
|
||||||
name="Android Auto Simulator"
|
name="Android Auto Simulator"
|
||||||
package="com.google.android.autosimulator"
|
package="com.google.android.autosimulator"
|
||||||
|
@ -220,36 +190,6 @@ limitations under the License.
|
||||||
ayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUW
|
ayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUW
|
||||||
Ev9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
|
Ev9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
|
||||||
</signing_certificate>
|
</signing_certificate>
|
||||||
<signing_certificate
|
|
||||||
name="Media Browser Simulator"
|
|
||||||
package="com.google.android.mediasimulator"
|
|
||||||
release="true">
|
|
||||||
MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYD
|
|
||||||
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
|
|
||||||
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
|
|
||||||
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
|
|
||||||
Fw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzET
|
|
||||||
MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
|
|
||||||
A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
|
|
||||||
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
|
|
||||||
hvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR
|
|
||||||
24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVy
|
|
||||||
xW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8X
|
|
||||||
W8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC
|
|
||||||
69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexA
|
|
||||||
cKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkw
|
|
||||||
HQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0c
|
|
||||||
xb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
|
|
||||||
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
|
|
||||||
QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
|
|
||||||
CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1Ud
|
|
||||||
EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrP
|
|
||||||
zgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXcla
|
|
||||||
XjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05a
|
|
||||||
IskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+a
|
|
||||||
ayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUW
|
|
||||||
Ev9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
|
|
||||||
</signing_certificate>
|
|
||||||
<signing_certificate
|
<signing_certificate
|
||||||
name="Google"
|
name="Google"
|
||||||
package="com.google.android.googlequicksearchbox"
|
package="com.google.android.googlequicksearchbox"
|
||||||
|
@ -284,26 +224,28 @@ limitations under the License.
|
||||||
name="Google"
|
name="Google"
|
||||||
package="com.google.android.googlequicksearchbox"
|
package="com.google.android.googlequicksearchbox"
|
||||||
release="true">
|
release="true">
|
||||||
MIIDvTCCAqWgAwIBAgIJAMePnkuTQTAGMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
|
MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNV
|
||||||
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
|
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBW
|
||||||
aWV3MRQwEgYDVQQKDAtHb29nbGUgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDERMA8G
|
aWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4G
|
||||||
A1UEAwwIZ2VhcmhlYWQwHhcNMTQwNTI3MjMwNTM0WhcNNDExMDEyMjMwNTM0WjB1
|
A1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQx
|
||||||
MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
|
CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3Vu
|
||||||
bnRhaW4gVmlldzEUMBIGA1UECgwLR29vZ2xlIEluYy4xEDAOBgNVBAsMB0FuZHJv
|
dGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9p
|
||||||
aWQxETAPBgNVBAMMCGdlYXJoZWFkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
ZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC
|
||||||
CgKCAQEA050XDkNIsVRMX2wTvVplpCu4OtnyNK2v5B7PS+DggmH2yuZiwpTurdKD
|
ggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JO
|
||||||
Q9R9UzxH9U4lsC+mIxXkiBYKIWNVgMtiTgxkEy7cgWvdYHgNYpFu8IxZKYDyXes+
|
Rland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/
|
||||||
02pfvpu63MIBD/PnvVFipo1oUrbfetj+mroEpjnA71gUS0Ok+H6XWWsmb8xFHQVM
|
8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfY
|
||||||
oZWEIzsUJ2nhm8EcnPkAPfNZAG++XLPROoRQCaswyYsd42JuYAP3CwZuhDcUbMWm
|
wXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LW
|
||||||
k7rBi9BVQ8gmkrbwqo94A7qStLUp3NyCmlKSWHaZ05SspEPwsfctka0oXG5bhgT6
|
uT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0z
|
||||||
67EMCzQ+YsFN1oJRL7Qq+mMQjFJs3wIDAQABo1AwTjAdBgNVHQ4EFgQUGvBfYNeu
|
OHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Yl
|
||||||
6JSJUnJZCiaBGsnXztswHwYDVR0jBBgwFoAUGvBfYNeu6JSJUnJZCiaBGsnXztsw
|
mn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14al
|
||||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAlGsDY0EPu3NBSH5k6iw/
|
oXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE
|
||||||
wJh9e3xMwS17ErKGlhyWogxJMzLjAN6g0aCPHxB40IQC+8qAl+RL7VQx6oxttf0m
|
BxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsT
|
||||||
31yUGQPcNYbt2CxBTCAr885oLK5t2TAi5tQzhd6ZEYihWSUWUd/X8BQRouxboss9
|
B0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTAD
|
||||||
QbBA/iIx0OpDaxiAcq7Cb67TheXZDxGuQ8fmHYbLx84pEvm3DQOB/LIMkkpQSfEC
|
AQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4
|
||||||
1f+oP1zB3urPU/dSvED/LCgOdrpxZ5di7SwSyue+Vq/TZQy34tPygEzD2d8hFlh/
|
rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCE
|
||||||
yfhWkMizOeIXcayVAQdNn5zpBkuay1skGOjQQ5kTbDcDzigO2R2rqn6HCd9l5Z0W
|
yj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh
|
||||||
IQ==
|
5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTb
|
||||||
|
Qe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZM
|
||||||
|
cUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK
|
||||||
</signing_certificate>
|
</signing_certificate>
|
||||||
</allowed_callers>
|
</allowed_callers>
|
Loading…
Reference in New Issue