Merge 8878cdc7a7
into 18e981fba5
This commit is contained in:
commit
19843bf351
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.github.apognu.otter">
|
package="com.github.apognu.otter">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
@ -17,6 +18,13 @@
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
android:usesCleartextTraffic="true">
|
android:usesCleartextTraffic="true">
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.car.notification.SmallIcon"
|
||||||
|
android:resource="@drawable/ottershape" />
|
||||||
|
<meta-data android:name="com.google.android.gms.car.application"
|
||||||
|
android:resource="@xml/automotive_app_desc"/>
|
||||||
|
|
||||||
|
|
||||||
<!-- <meta-data
|
<!-- <meta-data
|
||||||
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
|
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
|
||||||
android:value="com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider"/> -->
|
android:value="com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider"/> -->
|
||||||
|
@ -45,7 +53,14 @@
|
||||||
<activity android:name="com.github.apognu.otter.activities.SettingsActivity" />
|
<activity android:name="com.github.apognu.otter.activities.SettingsActivity" />
|
||||||
<activity android:name="com.github.apognu.otter.activities.LicencesActivity" />
|
<activity android:name="com.github.apognu.otter.activities.LicencesActivity" />
|
||||||
|
|
||||||
<service android:name="com.github.apognu.otter.playback.PlayerService" />
|
<service
|
||||||
|
android:name="com.github.apognu.otter.playback.PlayerService"
|
||||||
|
android:exported="true"
|
||||||
|
tools:ignore="ExportedService">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.media.browse.MediaBrowserService"/>
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".playback.PinService"
|
android:name=".playback.PinService"
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
package com.github.apognu.otter.playback
|
package com.github.apognu.otter.playback
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Service
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.media.AudioAttributes
|
import android.media.AudioAttributes
|
||||||
import android.media.AudioFocusRequest
|
import android.media.AudioFocusRequest
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.IBinder
|
import android.os.Bundle
|
||||||
|
import android.support.v4.media.MediaBrowserCompat
|
||||||
|
import android.support.v4.media.MediaDescriptionCompat
|
||||||
import android.support.v4.media.session.MediaSessionCompat
|
import android.support.v4.media.session.MediaSessionCompat
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import com.github.apognu.otter.Otter
|
import com.github.apognu.otter.Otter
|
||||||
|
import androidx.media.MediaBrowserServiceCompat
|
||||||
import com.github.apognu.otter.R
|
import com.github.apognu.otter.R
|
||||||
import com.github.apognu.otter.utils.*
|
import com.github.apognu.otter.utils.*
|
||||||
import com.google.android.exoplayer2.C
|
import com.google.android.exoplayer2.C
|
||||||
|
@ -20,6 +23,7 @@ import com.google.android.exoplayer2.ExoPlaybackException
|
||||||
import com.google.android.exoplayer2.Player
|
import com.google.android.exoplayer2.Player
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||||
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
|
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
|
||||||
|
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray
|
import com.google.android.exoplayer2.source.TrackGroupArray
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
|
@ -30,7 +34,7 @@ import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class PlayerService : Service() {
|
class PlayerService : MediaBrowserServiceCompat() {
|
||||||
private lateinit var queue: QueueManager
|
private lateinit var queue: QueueManager
|
||||||
private val jobs = mutableListOf<Job>()
|
private val jobs = mutableListOf<Job>()
|
||||||
|
|
||||||
|
@ -84,8 +88,21 @@ class PlayerService : Service() {
|
||||||
isActive = true
|
isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionToken = mediaSession.sessionToken
|
||||||
|
|
||||||
mediaControlsManager = MediaControlsManager(this, mediaSession)
|
mediaControlsManager = MediaControlsManager(this, mediaSession)
|
||||||
|
|
||||||
|
val queueNavigator: TimelineQueueNavigator = object : TimelineQueueNavigator(mediaSession) {
|
||||||
|
override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
|
||||||
|
val track = queue.get(windowIndex)
|
||||||
|
return MediaDescriptionCompat.Builder().apply {
|
||||||
|
setTitle(track.title)
|
||||||
|
setSubtitle(track.subtitle())
|
||||||
|
setIconUri(Uri.parse(maybeNormalizeUrl(track.cover())))
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
player = SimpleExoPlayer.Builder(this).build().apply {
|
player = SimpleExoPlayer.Builder(this).build().apply {
|
||||||
playWhenReady = false
|
playWhenReady = false
|
||||||
|
|
||||||
|
@ -95,6 +112,7 @@ class PlayerService : Service() {
|
||||||
|
|
||||||
MediaSessionConnector(mediaSession).also {
|
MediaSessionConnector(mediaSession).also {
|
||||||
it.setPlayer(this)
|
it.setPlayer(this)
|
||||||
|
it.setQueueNavigator(queueNavigator)
|
||||||
it.setMediaButtonEventHandler { player, _, mediaButtonEvent ->
|
it.setMediaButtonEventHandler { player, _, mediaButtonEvent ->
|
||||||
mediaButtonEvent.extras?.getParcelable<KeyEvent>(Intent.EXTRA_KEY_EVENT)?.let { key ->
|
mediaButtonEvent.extras?.getParcelable<KeyEvent>(Intent.EXTRA_KEY_EVENT)?.let { key ->
|
||||||
if (key.action == KeyEvent.ACTION_UP) {
|
if (key.action == KeyEvent.ACTION_UP) {
|
||||||
|
@ -219,8 +237,6 @@ class PlayerService : Service() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? = null
|
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
jobs.forEach { it.cancel() }
|
jobs.forEach { it.cancel() }
|
||||||
|
@ -430,4 +446,20 @@ class PlayerService : Service() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onGetRoot(
|
||||||
|
clientPackageName: String,
|
||||||
|
clientUid: Int,
|
||||||
|
rootHints: Bundle?
|
||||||
|
): BrowserRoot? {
|
||||||
|
return BrowserRoot("/", null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoadChildren(
|
||||||
|
parentId: String,
|
||||||
|
result: Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
|
) {
|
||||||
|
val list = mutableListOf<MediaBrowserCompat.MediaItem>()
|
||||||
|
result.sendResult(list)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<automotiveApp>
|
||||||
|
<uses name="media"/>
|
||||||
|
</automotiveApp>
|
Loading…
Reference in New Issue