Add demos/session-automotive module
This change also enables Android Auto support for the session demo. PiperOrigin-RevId: 569448376
@ -16,6 +16,8 @@
|
|||||||
* Muxers:
|
* Muxers:
|
||||||
* IMA extension:
|
* IMA extension:
|
||||||
* Session:
|
* Session:
|
||||||
|
* Add session demo module for Automotive OS and enable session demo for
|
||||||
|
Android Auto.
|
||||||
* UI:
|
* UI:
|
||||||
* Downloads:
|
* Downloads:
|
||||||
* OkHttp Extension:
|
* OkHttp Extension:
|
||||||
@ -111,7 +113,7 @@ This release includes the following changes since the
|
|||||||
* Add `MediaLibrarySession.getSubscribedControllers(mediaId)` for
|
* Add `MediaLibrarySession.getSubscribedControllers(mediaId)` for
|
||||||
convenience.
|
convenience.
|
||||||
* Override `MediaLibrarySession.Callback.onSubscribe()` to assert the
|
* Override `MediaLibrarySession.Callback.onSubscribe()` to assert the
|
||||||
availability of the parent Id for which the controller subscribes. If
|
availability of the parent ID for which the controller subscribes. If
|
||||||
successful, the subscription is accepted and `notifyChildrenChanged()`
|
successful, the subscription is accepted and `notifyChildrenChanged()`
|
||||||
is called immediately to inform the browser
|
is called immediately to inform the browser
|
||||||
([#561](https://github.com/androidx/media/issues/561)).
|
([#561](https://github.com/androidx/media/issues/561)).
|
||||||
|
@ -15,6 +15,8 @@ project.ext {
|
|||||||
releaseVersion = '1.2.0-alpha02'
|
releaseVersion = '1.2.0-alpha02'
|
||||||
releaseVersionCode = 1_002_000_0_02
|
releaseVersionCode = 1_002_000_0_02
|
||||||
minSdkVersion = 16
|
minSdkVersion = 16
|
||||||
|
// See https://developer.android.com/training/cars/media/automotive-os#automotive-module
|
||||||
|
automotiveMinSdkVersion = 28
|
||||||
appTargetSdkVersion = 34
|
appTargetSdkVersion = 34
|
||||||
// Upgrading this requires [Internal ref: b/193254928] to be fixed, or some
|
// Upgrading this requires [Internal ref: b/193254928] to be fixed, or some
|
||||||
// additional robolectric config.
|
// additional robolectric config.
|
||||||
|
@ -30,6 +30,11 @@
|
|||||||
android:theme="@style/Theme.Media3Demo"
|
android:theme="@style/Theme.Media3Demo"
|
||||||
tools:replace="android:name">
|
tools:replace="android:name">
|
||||||
|
|
||||||
|
<!-- Declare that this session demo supports Android Auto. -->
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.car.application"
|
||||||
|
android:resource="@xml/auto_app_desc" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
18
demos/session/src/main/res/xml/auto_app_desc.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright 2023 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.
|
||||||
|
-->
|
||||||
|
<automotiveApp>
|
||||||
|
<uses name="media" />
|
||||||
|
</automotiveApp>
|
7
demos/session_automotive/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Media3 Automotive session demo
|
||||||
|
|
||||||
|
This app demonstrates use of the `MediaLibraryService` for
|
||||||
|
[Android Automotive](https://developer.android.com/training/cars/media/automotive-os).
|
||||||
|
|
||||||
|
See the [demos README](../README.md) for instructions on how to build and run
|
||||||
|
this demo.
|
67
demos/session_automotive/build.gradle
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
apply from: '../../constants.gradle'
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace 'androidx.media3.demo.session.automotive'
|
||||||
|
|
||||||
|
compileSdkVersion project.ext.compileSdkVersion
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
versionName project.ext.releaseVersion
|
||||||
|
versionCode project.ext.releaseVersionCode
|
||||||
|
minSdkVersion project.ext.automotiveMinSdkVersion
|
||||||
|
targetSdkVersion project.ext.appTargetSdkVersion
|
||||||
|
multiDexEnabled true
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
shrinkResources true
|
||||||
|
minifyEnabled true
|
||||||
|
proguardFiles = [
|
||||||
|
getDefaultProguardFile('proguard-android-optimize.txt')
|
||||||
|
]
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
jniDebuggable = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
// The demo app isn't indexed, and doesn't have translations.
|
||||||
|
disable 'GoogleAppIndexingWarning','MissingTranslation'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'androidx.core:core-ktx:' + androidxCoreVersion
|
||||||
|
implementation 'androidx.appcompat:appcompat:' + androidxAppCompatVersion
|
||||||
|
implementation 'androidx.multidex:multidex:' + androidxMultidexVersion
|
||||||
|
implementation 'com.google.android.material:material:' + androidxMaterialVersion
|
||||||
|
implementation project(modulePrefix + 'lib-session')
|
||||||
|
implementation project(modulePrefix + 'demo-session-service')
|
||||||
|
}
|
72
demos/session_automotive/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright 2023 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.
|
||||||
|
-->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="androidx.media3.demo.session.automotive">
|
||||||
|
|
||||||
|
<uses-sdk/>
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||||
|
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.type.automotive"
|
||||||
|
android:required="true" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.wifi"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.screen.portrait"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.screen.landscape"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
|
<meta-data android:name="com.android.automotive"
|
||||||
|
android:resource="@xml/automotive_app_desc"/>
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name="androidx.multidex.MultiDexApplication"
|
||||||
|
android:allowBackup="false"
|
||||||
|
android:taskAffinity=""
|
||||||
|
android:appCategory="audio"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
tools:replace="android:name">
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="androidx.car.app.TintableAttributionIcon"
|
||||||
|
android:resource="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".AutomotiveService"
|
||||||
|
android:foregroundServiceType="mediaPlayback"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="androidx.media3.session.MediaLibraryService"/>
|
||||||
|
<action android:name="android.media.browse.MediaBrowserService"/>
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<!-- Artwork provider for content:// URIs -->
|
||||||
|
<provider
|
||||||
|
android:name="BitmapContentProvider"
|
||||||
|
android:authorities="androidx.media3"
|
||||||
|
android:exported="true" />
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
After Width: | Height: | Size: 353 KiB |
After Width: | Height: | Size: 215 KiB |
After Width: | Height: | Size: 41 KiB |
BIN
demos/session_automotive/src/main/assets/artwork/album_road.png
Normal file
After Width: | Height: | Size: 278 KiB |
BIN
demos/session_automotive/src/main/assets/artwork/album_sea.png
Normal file
After Width: | Height: | Size: 240 KiB |
After Width: | Height: | Size: 425 KiB |
472
demos/session_automotive/src/main/assets/catalog.json
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
{
|
||||||
|
"media": [
|
||||||
|
{
|
||||||
|
"id": "wake_up_01",
|
||||||
|
"title": "Intro - The Way Of Waking Up (feat. Alan Watts)",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/01_-_Intro_-_The_Way_Of_Waking_Up_feat_Alan_Watts.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 1,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 90,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_02",
|
||||||
|
"title": "Geisha",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/02_-_Geisha.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 2,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 267,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_03",
|
||||||
|
"title": "Voyage I - Waterfall",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/03_-_Voyage_I_-_Waterfall.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 3,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 264,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_04",
|
||||||
|
"title": "The Music In You",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/04_-_The_Music_In_You.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 4,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 223,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_05",
|
||||||
|
"title": "The Calm Before The Storm",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/05_-_The_Calm_Before_The_Storm.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 5,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 229,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_06",
|
||||||
|
"title": "No Pain, No Gain",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/06_-_No_Pain_No_Gain.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 6,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 304,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_07",
|
||||||
|
"title": "Voyage II - Satori",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/07_-_Voyage_II_-_Satori.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 7,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 256,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_08",
|
||||||
|
"title": "Reveal the Magic",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/08_-_Reveal_the_Magic.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 8,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 293,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_09",
|
||||||
|
"title": "Hachiko (The Faithtful Dog)",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/09_-_Hachiko_The_Faithtful_Dog.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 9,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 185,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_10",
|
||||||
|
"title": "Wake Up",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/10_-_Wake_Up.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 10,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 251,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_11",
|
||||||
|
"title": "Voyage III - The Space Between Us",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/11_-_Voyage_III_-_The_Space_Between_Us.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 11,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 290,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_12",
|
||||||
|
"title": "Ume No Kaori (feat. Sunawai)",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/12_-_Ume_No_Kaori_feat_Sunawai.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 12,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 334,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wake_up_13",
|
||||||
|
"title": "Outro - Totally Here and Now (feat. Alan Watts)",
|
||||||
|
"album": "Wake Up",
|
||||||
|
"artist": "The Kyoto Connection",
|
||||||
|
"genre": "Electronic",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/13_-_Outro_-_Totally_Here_and_Now_feat_Alan_Watts.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kyoto_connection.png",
|
||||||
|
"trackNumber": 13,
|
||||||
|
"totalTrackCount": 13,
|
||||||
|
"duration": 242,
|
||||||
|
"site": "http://freemusicarchive.org/music/The_Kyoto_Connection/Wake_Up_1957/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_01",
|
||||||
|
"title": "Intro (.udonthear)",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/01_-_Intro_udonthear.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 1,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 63,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_02",
|
||||||
|
"title": "Leaving",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/02_-_Leaving.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 2,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 170,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_03",
|
||||||
|
"title": "Irsen's Tale",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/03_-_Irsens_Tale.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 3,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 164,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_04",
|
||||||
|
"title": "Moonlight Reprise",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/04_-_Moonlight_Reprise.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 4,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 181,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_05",
|
||||||
|
"title": "Nothing Lasts Forever",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/05_-_Nothing_Lasts_Forever.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 5,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 132,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_06",
|
||||||
|
"title": "The Moments of Our Mornings",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/06_-_The_Moments_of_Our_Mornings.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 6,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 104,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_07",
|
||||||
|
"title": "Laceration",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/07_-_Laceration.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 7,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 173,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_08",
|
||||||
|
"title": "Memories",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/08_-_Memories.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 8,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 213,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "irsens_tale_09",
|
||||||
|
"title": "Outro",
|
||||||
|
"album": "Irsen's Tale",
|
||||||
|
"artist": "Kai Engel",
|
||||||
|
"genre": "Ambient",
|
||||||
|
"source": "https://storage.googleapis.com/uamp/Kai_Engel_-_Irsens_Tale/09_-_Outro.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_kai_engel.png",
|
||||||
|
"trackNumber": 9,
|
||||||
|
"totalTrackCount": 9,
|
||||||
|
"duration": 65,
|
||||||
|
"site": "http://freemusicarchive.org/music/Kai_Engel/Irsens_Tale/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "jazz_in_paris",
|
||||||
|
"title": "Jazz in Paris",
|
||||||
|
"album": "Jazz & Blues",
|
||||||
|
"artist": "Media Right Productions",
|
||||||
|
"genre": "Jazz & Blues",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_sea.png",
|
||||||
|
"trackNumber": 1,
|
||||||
|
"totalTrackCount": 6,
|
||||||
|
"duration": 103,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "the_messenger",
|
||||||
|
"title": "The Messenger",
|
||||||
|
"album": "Jazz & Blues",
|
||||||
|
"artist": "Silent Partner",
|
||||||
|
"genre": "Jazz & Blues",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/The_Messenger.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_sea.png",
|
||||||
|
"trackNumber": 2,
|
||||||
|
"totalTrackCount": 6,
|
||||||
|
"duration": 132,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "talkies",
|
||||||
|
"title": "Talkies",
|
||||||
|
"album": "Jazz & Blues",
|
||||||
|
"artist": "Huma-Huma",
|
||||||
|
"genre": "Jazz & Blues",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Talkies.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_sea.png",
|
||||||
|
"trackNumber": 3,
|
||||||
|
"totalTrackCount": 6,
|
||||||
|
"duration": 162,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "on_the_bach",
|
||||||
|
"title": "On the Bach",
|
||||||
|
"album": "Cinematic",
|
||||||
|
"artist": "Jingle Punks",
|
||||||
|
"genre": "Cinematic",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/On_the_Bach.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_drinks.png",
|
||||||
|
"trackNumber": 4,
|
||||||
|
"totalTrackCount": 6,
|
||||||
|
"duration": 66,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "the_story_unfolds",
|
||||||
|
"title": "The Story Unfolds",
|
||||||
|
"album": "Cinematic",
|
||||||
|
"artist": "Jingle Punks",
|
||||||
|
"genre": "Cinematic",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/The_Story_Unfolds.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_drinks.png",
|
||||||
|
"trackNumber": 5,
|
||||||
|
"totalTrackCount": 6,
|
||||||
|
"duration": 91,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "drop_and_roll",
|
||||||
|
"title": "Drop and Roll",
|
||||||
|
"album": "Youtube Audio Library Rock",
|
||||||
|
"artist": "Silent Partner",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Drop_and_Roll.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_road.png",
|
||||||
|
"trackNumber": 1,
|
||||||
|
"totalTrackCount": 7,
|
||||||
|
"duration": 121,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "motocross",
|
||||||
|
"title": "Motocross",
|
||||||
|
"album": "Youtube Audio Library Rock",
|
||||||
|
"artist": "Topher Mohr and Alex Elena",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Motocross.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_road.png",
|
||||||
|
"trackNumber": 2,
|
||||||
|
"totalTrackCount": 7,
|
||||||
|
"duration": 182,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wish_youd_come_true",
|
||||||
|
"title": "Wish You'd Come True",
|
||||||
|
"album": "Youtube Audio Library Rock",
|
||||||
|
"artist": "The 126ers",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Wish_You_d_Come_True.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_road.png",
|
||||||
|
"trackNumber": 3,
|
||||||
|
"totalTrackCount": 7,
|
||||||
|
"duration": 169,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "awakening",
|
||||||
|
"title": "Awakening",
|
||||||
|
"album": "Youtube Audio Library Rock",
|
||||||
|
"artist": "Silent Partner",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Awakening.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_road.png",
|
||||||
|
"trackNumber": 4,
|
||||||
|
"totalTrackCount": 7,
|
||||||
|
"duration": 220,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "home",
|
||||||
|
"title": "Home",
|
||||||
|
"album": "Youtube Audio Library Rock",
|
||||||
|
"artist": "Letter Box",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Home.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_road.png",
|
||||||
|
"trackNumber": 5,
|
||||||
|
"totalTrackCount": 7,
|
||||||
|
"duration": 213,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tell_the_angels",
|
||||||
|
"title": "Tell The Angels",
|
||||||
|
"album": "Youtube Audio Library Rock 2",
|
||||||
|
"artist": "Letter Box",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Tell_The_Angels.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_skyline.png",
|
||||||
|
"trackNumber": 6,
|
||||||
|
"totalTrackCount": 7,
|
||||||
|
"duration": 208,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hey_sailor",
|
||||||
|
"title": "Hey Sailor",
|
||||||
|
"album": "Youtube Audio Library Rock 2",
|
||||||
|
"artist": "Letter Box",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Hey_Sailor.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_skyline.png",
|
||||||
|
"trackNumber": 7,
|
||||||
|
"totalTrackCount": 7,
|
||||||
|
"duration": 193,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "keys_to_the_kingdom",
|
||||||
|
"title": "Keys To The Kingdom",
|
||||||
|
"album": "Youtube Audio Library Rock 2",
|
||||||
|
"artist": "The 126ers",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/Keys_To_The_Kingdom.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_skyline.png",
|
||||||
|
"trackNumber": 1,
|
||||||
|
"totalTrackCount": 2,
|
||||||
|
"duration": 221,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "the_coldest_shoulder",
|
||||||
|
"title": "The Coldest Shoulder",
|
||||||
|
"album": "Youtube Audio Library Rock 2",
|
||||||
|
"artist": "The 126ers",
|
||||||
|
"genre": "Rock",
|
||||||
|
"source": "https://storage.googleapis.com/automotive-media/The_Coldest_Shoulder.mp3",
|
||||||
|
"image": "content://androidx.media3/artwork/album_skyline.png",
|
||||||
|
"trackNumber": 2,
|
||||||
|
"totalTrackCount": 2,
|
||||||
|
"duration": 160,
|
||||||
|
"site": "https://www.youtube.com/audiolibrary/music"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package androidx.media3.demo.session.automotive
|
||||||
|
|
||||||
|
import androidx.annotation.OptIn
|
||||||
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import androidx.media3.demo.session.DemoMediaLibrarySessionCallback
|
||||||
|
import androidx.media3.demo.session.DemoPlaybackService
|
||||||
|
import androidx.media3.session.LibraryResult
|
||||||
|
import androidx.media3.session.MediaConstants
|
||||||
|
import androidx.media3.session.MediaSession.ControllerInfo
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
|
|
||||||
|
class AutomotiveService : DemoPlaybackService() {
|
||||||
|
|
||||||
|
override fun createLibrarySessionCallback(): MediaLibrarySession.Callback {
|
||||||
|
return object : DemoMediaLibrarySessionCallback(this@AutomotiveService) {
|
||||||
|
|
||||||
|
@OptIn(UnstableApi::class)
|
||||||
|
override fun onGetLibraryRoot(
|
||||||
|
session: MediaLibrarySession,
|
||||||
|
browser: ControllerInfo,
|
||||||
|
params: LibraryParams?
|
||||||
|
): ListenableFuture<LibraryResult<MediaItem>> {
|
||||||
|
var responseParams = params
|
||||||
|
if (session.isAutomotiveController(browser)) {
|
||||||
|
// See https://developer.android.com/training/cars/media#apply_content_style
|
||||||
|
val rootHintParams = params ?: LibraryParams.Builder().build()
|
||||||
|
rootHintParams.extras.putInt(
|
||||||
|
MediaConstants.EXTRAS_KEY_CONTENT_STYLE_BROWSABLE,
|
||||||
|
MediaConstants.EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM
|
||||||
|
)
|
||||||
|
rootHintParams.extras.putInt(
|
||||||
|
MediaConstants.EXTRAS_KEY_CONTENT_STYLE_PLAYABLE,
|
||||||
|
MediaConstants.EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM
|
||||||
|
)
|
||||||
|
// Tweaked params are propagated to Automotive browsers as root hints.
|
||||||
|
responseParams = rootHintParams
|
||||||
|
}
|
||||||
|
// Use super to return the common library root with the tweaked params sent to the browser.
|
||||||
|
return super.onGetLibraryRoot(session, browser, responseParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package androidx.media3.demo.session.automotive
|
||||||
|
|
||||||
|
import android.content.ContentProvider
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.content.Context
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.ParcelFileDescriptor
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides artwork for content URIs.
|
||||||
|
*
|
||||||
|
* <p>A bitmap file in the asset folder with path 'artwork/album1.png' can be referenced as artwork
|
||||||
|
* URI with 'content://androidx.media3/artwork/album1.png'. 'androidx.media3' is the authority
|
||||||
|
* declared for the content provider in 'AndroidManifest.xml'.
|
||||||
|
*
|
||||||
|
* <p>For demo use only.
|
||||||
|
*/
|
||||||
|
class BitmapContentProvider : ContentProvider() {
|
||||||
|
|
||||||
|
override fun onCreate() = true
|
||||||
|
|
||||||
|
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {
|
||||||
|
context?.let { ctx ->
|
||||||
|
getAssetPath(uri)?.let {
|
||||||
|
return ParcelFileDescriptor.open(
|
||||||
|
copyAssetFileToCacheDirectory(ctx, it),
|
||||||
|
ParcelFileDescriptor.MODE_READ_ONLY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.openFile(uri, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAssetPath(contentUri: Uri): String? {
|
||||||
|
contentUri.path?.let {
|
||||||
|
return it.substring(1)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyAssetFileToCacheDirectory(context: Context, assetPath: String): File {
|
||||||
|
val publicFile = File(context.cacheDir, assetPath.replace("/", "_"))
|
||||||
|
if (!publicFile.exists()) {
|
||||||
|
context.assets.open(assetPath).copyTo(publicFile.outputStream())
|
||||||
|
}
|
||||||
|
return publicFile
|
||||||
|
}
|
||||||
|
|
||||||
|
// No-op implementations of abstract ContentProvider methods.
|
||||||
|
|
||||||
|
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
|
||||||
|
|
||||||
|
override fun query(
|
||||||
|
uri: Uri,
|
||||||
|
projection: Array<String>?,
|
||||||
|
selection: String?,
|
||||||
|
selectionArgs: Array<String>?,
|
||||||
|
sortOrder: String?
|
||||||
|
): Cursor? = null
|
||||||
|
|
||||||
|
override fun update(
|
||||||
|
uri: Uri,
|
||||||
|
values: ContentValues?,
|
||||||
|
selection: String?,
|
||||||
|
selectionArgs: Array<String>?
|
||||||
|
) = 0
|
||||||
|
|
||||||
|
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?) = 0
|
||||||
|
|
||||||
|
override fun getType(uri: Uri): String? = null
|
||||||
|
}
|
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 10 KiB |
18
demos/session_automotive/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright 2023 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.
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Media3 Automotive Demo</string>
|
||||||
|
</resources>
|
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright 2023 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.
|
||||||
|
-->
|
||||||
|
<automotiveApp>
|
||||||
|
<uses name="media"/>
|
||||||
|
</automotiveApp>
|
@ -44,12 +44,12 @@ open class DemoMediaLibrarySessionCallback(private val context: Context) :
|
|||||||
CommandButton.Builder()
|
CommandButton.Builder()
|
||||||
.setDisplayName(context.getString(R.string.exo_controls_shuffle_on_description))
|
.setDisplayName(context.getString(R.string.exo_controls_shuffle_on_description))
|
||||||
.setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON, Bundle.EMPTY))
|
.setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON, Bundle.EMPTY))
|
||||||
.setIconResId(R.drawable.exo_icon_shuffle_on)
|
.setIconResId(R.drawable.exo_icon_shuffle_off)
|
||||||
.build(),
|
.build(),
|
||||||
CommandButton.Builder()
|
CommandButton.Builder()
|
||||||
.setDisplayName(context.getString(R.string.exo_controls_shuffle_off_description))
|
.setDisplayName(context.getString(R.string.exo_controls_shuffle_off_description))
|
||||||
.setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF, Bundle.EMPTY))
|
.setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF, Bundle.EMPTY))
|
||||||
.setIconResId(R.drawable.exo_icon_shuffle_off)
|
.setIconResId(R.drawable.exo_icon_shuffle_on)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -71,7 +71,11 @@ open class DemoMediaLibrarySessionCallback(private val context: Context) :
|
|||||||
session: MediaSession,
|
session: MediaSession,
|
||||||
controller: MediaSession.ControllerInfo
|
controller: MediaSession.ControllerInfo
|
||||||
): MediaSession.ConnectionResult {
|
): MediaSession.ConnectionResult {
|
||||||
if (session.isMediaNotificationController(controller)) {
|
if (
|
||||||
|
session.isMediaNotificationController(controller) ||
|
||||||
|
session.isAutomotiveController(controller) ||
|
||||||
|
session.isAutoCompanionController(controller)
|
||||||
|
) {
|
||||||
// Select the button to display.
|
// Select the button to display.
|
||||||
val customLayout = customLayoutCommandButtons[if (session.player.shuffleModeEnabled) 1 else 0]
|
val customLayout = customLayoutCommandButtons[if (session.player.shuffleModeEnabled) 1 else 0]
|
||||||
return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
|
return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
|
||||||
@ -90,21 +94,26 @@ open class DemoMediaLibrarySessionCallback(private val context: Context) :
|
|||||||
customCommand: SessionCommand,
|
customCommand: SessionCommand,
|
||||||
args: Bundle
|
args: Bundle
|
||||||
): ListenableFuture<SessionResult> {
|
): ListenableFuture<SessionResult> {
|
||||||
if (!session.isMediaNotificationController(controller)) {
|
|
||||||
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED))
|
|
||||||
}
|
|
||||||
if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON == customCommand.customAction) {
|
if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON == customCommand.customAction) {
|
||||||
// Enable shuffling.
|
// Enable shuffling.
|
||||||
session.player.shuffleModeEnabled = true
|
session.player.shuffleModeEnabled = true
|
||||||
// Change the custom layout to contain the `Disable shuffling` command.
|
// Change the custom layout to contain the `Disable shuffling` command.
|
||||||
session.setCustomLayout(controller, ImmutableList.of(customLayoutCommandButtons[1]))
|
session.setCustomLayout(
|
||||||
|
session.mediaNotificationControllerInfo!!,
|
||||||
|
ImmutableList.of(customLayoutCommandButtons[1])
|
||||||
|
)
|
||||||
|
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
|
||||||
} else if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF == customCommand.customAction) {
|
} else if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF == customCommand.customAction) {
|
||||||
// Disable shuffling.
|
// Disable shuffling.
|
||||||
session.player.shuffleModeEnabled = false
|
session.player.shuffleModeEnabled = false
|
||||||
// Change the custom layout to contain the `Enable shuffling` command.
|
// Change the custom layout to contain the `Enable shuffling` command.
|
||||||
session.setCustomLayout(controller, ImmutableList.of(customLayoutCommandButtons[0]))
|
session.setCustomLayout(
|
||||||
|
session.mediaNotificationControllerInfo!!,
|
||||||
|
ImmutableList.of(customLayoutCommandButtons[0])
|
||||||
|
)
|
||||||
|
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
|
||||||
}
|
}
|
||||||
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
|
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onGetLibraryRoot(
|
override fun onGetLibraryRoot(
|
||||||
|
@ -224,7 +224,12 @@ object MediaItemTree {
|
|||||||
isPlayable = true,
|
isPlayable = true,
|
||||||
isBrowsable = true,
|
isBrowsable = true,
|
||||||
mediaType = MediaMetadata.MEDIA_TYPE_ALBUM,
|
mediaType = MediaMetadata.MEDIA_TYPE_ALBUM,
|
||||||
subtitleConfigurations
|
subtitleConfigurations,
|
||||||
|
album = null,
|
||||||
|
artist = null,
|
||||||
|
genre = null,
|
||||||
|
sourceUri = null,
|
||||||
|
imageUri
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
treeNodes[ALBUM_ID]!!.addChild(albumFolderIdInTree)
|
treeNodes[ALBUM_ID]!!.addChild(albumFolderIdInTree)
|
||||||
|
@ -31,6 +31,8 @@ include modulePrefix + 'demo-session'
|
|||||||
project(modulePrefix + 'demo-session').projectDir = new File(rootDir, 'demos/session')
|
project(modulePrefix + 'demo-session').projectDir = new File(rootDir, 'demos/session')
|
||||||
include modulePrefix + 'demo-session-service'
|
include modulePrefix + 'demo-session-service'
|
||||||
project(modulePrefix + 'demo-session-service').projectDir = new File(rootDir, 'demos/session_service')
|
project(modulePrefix + 'demo-session-service').projectDir = new File(rootDir, 'demos/session_service')
|
||||||
|
include modulePrefix + 'demo-session-automotive'
|
||||||
|
project(modulePrefix + 'demo-session-automotive').projectDir = new File(rootDir, 'demos/session_automotive')
|
||||||
include modulePrefix + 'demo-surface'
|
include modulePrefix + 'demo-surface'
|
||||||
project(modulePrefix + 'demo-surface').projectDir = new File(rootDir, 'demos/surface')
|
project(modulePrefix + 'demo-surface').projectDir = new File(rootDir, 'demos/surface')
|
||||||
include modulePrefix + 'demo-transformer'
|
include modulePrefix + 'demo-transformer'
|
||||||
|