Update Exoplayer all the way to 2.18.1

technical/upgrade-exoplayer
Ryan Harg 2022-12-05 14:11:45 +01:00
rodzic ef01386f16
commit c27d2d0d55
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 89106F3A84E6958C
12 zmienionych plików z 68 dodań i 57 usunięć

Wyświetl plik

@ -52,7 +52,7 @@ android {
disable += listOf("MissingTranslation", "ExtraTranslation") disable += listOf("MissingTranslation", "ExtraTranslation")
} }
compileSdk = 31 compileSdk = 33
defaultConfig { defaultConfig {
@ -62,7 +62,7 @@ android {
versionName = androidGitVersion.name() versionName = androidGitVersion.name()
minSdk = 24 minSdk = 24
targetSdk = 30 targetSdk = 33
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@ -167,21 +167,14 @@ dependencies {
implementation("com.google.android.material:material:1.6.1") implementation("com.google.android.material:material:1.6.1")
implementation("com.android.support.constraint:constraint-layout:2.0.4") implementation("com.android.support.constraint:constraint-layout:2.0.4")
implementation("com.google.android.exoplayer:exoplayer-core:2.14.2") implementation("com.google.android.exoplayer:exoplayer-core:2.18.1")
implementation("com.google.android.exoplayer:exoplayer-ui:2.14.2") implementation("com.google.android.exoplayer:exoplayer-ui:2.18.1")
implementation("com.google.android.exoplayer:extension-mediasession:2.14.2") implementation("com.google.android.exoplayer:extension-mediasession:2.18.1")
implementation("io.insert-koin:koin-core:3.1.2") implementation("io.insert-koin:koin-core:3.1.2")
implementation("io.insert-koin:koin-android:3.1.2") implementation("io.insert-koin:koin-android:3.1.2")
testImplementation("io.insert-koin:koin-test:3.1.2") testImplementation("io.insert-koin:koin-test:3.1.2")
implementation("com.github.PaulWoitaschek.ExoPlayer-Extensions:extension-opus:2.14.0") {
isTransitive = false
}
implementation("com.github.PaulWoitaschek.ExoPlayer-Extensions:extension-flac:2.14.0") {
isTransitive = false
}
implementation("com.aliassadi:power-preference-lib:2.0.0") implementation("com.aliassadi:power-preference-lib:2.0.0")
implementation("com.github.kittinunf.fuel:fuel:2.3.1") implementation("com.github.kittinunf.fuel:fuel:2.3.1")
implementation("com.github.kittinunf.fuel:fuel-coroutines:2.3.1") implementation("com.github.kittinunf.fuel:fuel-coroutines:2.3.1")

Wyświetl plik

@ -22,7 +22,8 @@
android:name=".activities.SplashActivity" android:name=".activities.SplashActivity"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:noHistory="true" android:noHistory="true"
android:screenOrientation="portrait"> android:screenOrientation="portrait"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -61,7 +62,8 @@
<service <service
android:name=".playback.PlayerService" android:name=".playback.PlayerService"
android:foregroundServiceType="mediaPlayback"> android:foregroundServiceType="mediaPlayback"
android:exported="false">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" /> <action android:name="android.intent.action.MEDIA_BUTTON" />
@ -80,7 +82,8 @@
</service> </service>
<receiver android:name="androidx.media.session.MediaButtonReceiver"> <receiver android:name="androidx.media.session.MediaButtonReceiver"
android:exported="false">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" /> <action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter> </intent-filter>

Wyświetl plik

@ -228,8 +228,8 @@ class MainActivity : AppCompatActivity() {
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW)
item.actionView = View(this) item.actionView = View(this)
item.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { item.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem?) = false override fun onMenuItemActionExpand(item: MenuItem) = false
override fun onMenuItemActionCollapse(item: MenuItem?) = false override fun onMenuItemActionCollapse(item: MenuItem) = false
}) })
item.isChecked = !item.isChecked item.isChecked = !item.isChecked
@ -359,7 +359,7 @@ class MainActivity : AppCompatActivity() {
.alpha(0.0f) .alpha(0.0f)
.setDuration(400) .setDuration(400)
.setListener(object : AnimatorListenerAdapter() { .setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animator: Animator?) { override fun onAnimationEnd(animator: Animator) {
binding.nowPlaying.visibility = View.GONE binding.nowPlaying.visibility = View.GONE
} }
}) })

Wyświetl plik

@ -2,6 +2,7 @@ package audio.funkwhale.ffa.playback
import android.app.Notification import android.app.Notification
import android.app.PendingIntent import android.app.PendingIntent
import android.app.PendingIntent.FLAG_MUTABLE
import android.app.Service import android.app.Service
import android.content.Intent import android.content.Intent
import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.MediaSessionCompat
@ -42,7 +43,7 @@ class MediaControlsManager(val context: Service, private val scope: CoroutineSco
scope.launch(Default) { scope.launch(Default) {
val openIntent = Intent(context, MainActivity::class.java).apply { action = NOTIFICATION_ACTION_OPEN_QUEUE.toString() } val openIntent = Intent(context, MainActivity::class.java).apply { action = NOTIFICATION_ACTION_OPEN_QUEUE.toString() }
val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, 0) val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, FLAG_MUTABLE)
val coverUrl = maybeNormalizeUrl(track.album?.cover()) val coverUrl = maybeNormalizeUrl(track.album?.cover())

Wyświetl plik

@ -9,7 +9,6 @@ import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat import android.support.v4.media.session.PlaybackStateCompat
import audio.funkwhale.ffa.utils.Command import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus import audio.funkwhale.ffa.utils.CommandBus
import com.google.android.exoplayer2.ControlDispatcher
import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
@ -43,7 +42,7 @@ class MediaSession(private val context: Context) {
MediaSessionConnector(session).also { MediaSessionConnector(session).also {
it.setQueueNavigator(FFAQueueNavigator()) it.setQueueNavigator(FFAQueueNavigator())
it.setMediaButtonEventHandler { _, _, intent -> it.setMediaButtonEventHandler { _, intent ->
if (!active) { if (!active) {
Intent(context, PlayerService::class.java).let { player -> Intent(context, PlayerService::class.java).let { player ->
player.action = intent.action player.action = intent.action
@ -67,13 +66,14 @@ class MediaSession(private val context: Context) {
} }
class FFAQueueNavigator : MediaSessionConnector.QueueNavigator { class FFAQueueNavigator : MediaSessionConnector.QueueNavigator {
override fun onSkipToQueueItem(player: Player, controlDispatcher: ControlDispatcher, id: Long) { override fun onSkipToQueueItem(player: Player, id: Long) {
CommandBus.send(Command.PlayTrack(id.toInt())) CommandBus.send(Command.PlayTrack(id.toInt()))
} }
override fun onCurrentWindowIndexChanged(player: Player) {} override fun onCurrentMediaItemIndexChanged(player: Player) {}
override fun onCommand(player: Player, controlDispatcher: ControlDispatcher, command: String, extras: Bundle?, cb: ResultReceiver?) = true override fun onCommand(player: Player, command: String, extras: Bundle?, cb: ResultReceiver?) =
true
override fun getSupportedQueueNavigatorActions(player: Player): Long { override fun getSupportedQueueNavigatorActions(player: Player): Long {
return PlaybackStateCompat.ACTION_PLAY_PAUSE or return PlaybackStateCompat.ACTION_PLAY_PAUSE or
@ -82,13 +82,13 @@ class FFAQueueNavigator : MediaSessionConnector.QueueNavigator {
PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM
} }
override fun onSkipToNext(player: Player, controlDispatcher: ControlDispatcher) { override fun onSkipToNext(player: Player) {
CommandBus.send(Command.NextTrack) CommandBus.send(Command.NextTrack)
} }
override fun getActiveQueueItemId(player: Player?) = player?.currentWindowIndex?.toLong() ?: 0 override fun getActiveQueueItemId(player: Player?) = player?.currentWindowIndex?.toLong() ?: 0
override fun onSkipToPrevious(player: Player, controlDispatcher: ControlDispatcher) { override fun onSkipToPrevious(player: Player) {
CommandBus.send(Command.PreviousTrack) CommandBus.send(Command.PreviousTrack)
} }

Wyświetl plik

@ -80,7 +80,10 @@ class PinService : DownloadService(AppContext.NOTIFICATION_DOWNLOADS) {
override fun getScheduler(): Scheduler? = null override fun getScheduler(): Scheduler? = null
override fun getForegroundNotification(downloads: MutableList<Download>): Notification { override fun getForegroundNotification(
downloads: MutableList<Download>,
notMetRequirements: Int
): Notification {
val description = val description =
resources.getQuantityString(R.plurals.downloads_description, downloads.size, downloads.size) resources.getQuantityString(R.plurals.downloads_description, downloads.size, downloads.size)

Wyświetl plik

@ -31,11 +31,10 @@ import audio.funkwhale.ffa.utils.log
import audio.funkwhale.ffa.utils.maybeNormalizeUrl import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.onApi import audio.funkwhale.ffa.utils.onApi
import com.google.android.exoplayer2.C import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.ExoPlaybackException import com.google.android.exoplayer2.PlaybackException
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.source.TrackGroupArray import com.google.android.exoplayer2.Tracks
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
@ -43,7 +42,6 @@ import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.koin.java.KoinJavaComponent.inject import org.koin.java.KoinJavaComponent.inject
@ -136,6 +134,7 @@ class PlayerService : Service() {
playWhenReady = false playWhenReady = false
playerEventListener = PlayerEventListener().also { playerEventListener = PlayerEventListener().also {
addListener(it) addListener(it)
} }
} }
@ -419,9 +418,9 @@ class PlayerService : Service() {
} }
@SuppressLint("NewApi") @SuppressLint("NewApi")
inner class PlayerEventListener : Player.EventListener { inner class PlayerEventListener : Player.Listener {
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) { override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
super.onPlayerStateChanged(playWhenReady, playbackState) super.onPlayWhenReadyChanged(playWhenReady, playbackState)
EventBus.send(Event.StateChanged(playWhenReady)) EventBus.send(Event.StateChanged(playWhenReady))
@ -469,14 +468,11 @@ class PlayerService : Service() {
} }
} }
override fun onTracksChanged( override fun onTracksChanged(tracks: Tracks) {
trackGroups: TrackGroupArray, super.onTracksChanged(tracks)
trackSelections: TrackSelectionArray
) {
super.onTracksChanged(trackGroups, trackSelections)
if (queue.current != player.currentWindowIndex) { if (queue.current != player.currentMediaItemIndex) {
queue.current = player.currentWindowIndex queue.current = player.currentMediaItemIndex
mediaControlsManager.updateNotification(queue.current(), player.playWhenReady) mediaControlsManager.updateNotification(queue.current(), player.playWhenReady)
} }
@ -510,7 +506,7 @@ class PlayerService : Service() {
} }
} }
override fun onPlayerError(error: ExoPlaybackException) { override fun onPlayerError(error: PlaybackException) {
EventBus.send(Event.PlaybackError(getString(R.string.error_playback))) EventBus.send(Event.PlaybackError(getString(R.string.error_playback)))
if (player.playWhenReady) { if (player.playWhenReady) {

Wyświetl plik

@ -12,6 +12,7 @@ import audio.funkwhale.ffa.utils.FFACache
import audio.funkwhale.ffa.utils.log import audio.funkwhale.ffa.utils.log
import audio.funkwhale.ffa.utils.mustNormalizeUrl import audio.funkwhale.ffa.utils.mustNormalizeUrl
import com.github.kittinunf.fuel.gson.gsonDeserializerOf import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.source.ConcatenatingMediaSource import com.google.android.exoplayer2.source.ConcatenatingMediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.gson.Gson import com.google.gson.Gson
@ -37,9 +38,12 @@ class QueueManager(val context: Context) {
dataSources.addMediaSources( dataSources.addMediaSources(
metadata.map { track -> metadata.map { track ->
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "") val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
ProgressiveMediaSource.Factory(factory).createMediaSource(
ProgressiveMediaSource.Factory(factory).setTag(track.title) MediaItem.Builder()
.createMediaSource(Uri.parse(url)) .setTag(track.title)
.setUri(Uri.parse(url))
.build()
)
} }
) )
} }
@ -63,8 +67,12 @@ class QueueManager(val context: Context) {
val factory = cacheDataSourceFactoryProvider.create(context) val factory = cacheDataSourceFactoryProvider.create(context)
val sources = tracks.map { track -> val sources = tracks.map { track ->
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "") val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
ProgressiveMediaSource.Factory(factory).createMediaSource(
ProgressiveMediaSource.Factory(factory).setTag(track.title).createMediaSource(Uri.parse(url)) MediaItem.Builder()
.setTag(track.title)
.setUri(Uri.parse(url))
.build()
)
} }
metadata = tracks.toMutableList() metadata = tracks.toMutableList()
@ -84,7 +92,12 @@ class QueueManager(val context: Context) {
val sources = missingTracks.map { track -> val sources = missingTracks.map { track ->
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "") val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
ProgressiveMediaSource.Factory(factory).createMediaSource(Uri.parse(url)) ProgressiveMediaSource.Factory(factory).createMediaSource(
MediaItem.Builder()
.setTag(track.title) // was this missing on purpose?!
.setUri(Uri.parse(url))
.build()
)
} }
metadata.addAll(tracks) metadata.addAll(tracks)
@ -101,7 +114,12 @@ class QueueManager(val context: Context) {
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "") val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
if (metadata.indexOf(track) == -1) { if (metadata.indexOf(track) == -1) {
ProgressiveMediaSource.Factory(factory).createMediaSource(Uri.parse(url)).let { ProgressiveMediaSource.Factory(factory).createMediaSource(
MediaItem.Builder()
.setTag(track.title) // was this missing on purpose?!
.setUri(Uri.parse(url))
.build()
).let {
dataSources.addMediaSource(current + 1, it) dataSources.addMediaSource(current + 1, it)
metadata.add(current + 1, track) metadata.add(current + 1, track)
} }

Wyświetl plik

@ -11,8 +11,8 @@ import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.model.TracksCache import audio.funkwhale.ffa.model.TracksCache
import audio.funkwhale.ffa.model.TracksResponse import audio.funkwhale.ffa.model.TracksResponse
import audio.funkwhale.ffa.utils.OAuth import audio.funkwhale.ffa.utils.OAuth
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import audio.funkwhale.ffa.utils.mustNormalizeUrl import audio.funkwhale.ffa.utils.mustNormalizeUrl
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.android.exoplayer2.offline.DownloadManager import com.google.android.exoplayer2.offline.DownloadManager
import com.google.android.exoplayer2.upstream.cache.Cache import com.google.android.exoplayer2.upstream.cache.Cache
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken

Wyświetl plik

@ -7,8 +7,8 @@ import audio.funkwhale.ffa.model.TracksCache
import audio.funkwhale.ffa.model.TracksResponse import audio.funkwhale.ffa.model.TracksResponse
import audio.funkwhale.ffa.utils.OAuth import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.getMetadata import audio.funkwhale.ffa.utils.getMetadata
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import audio.funkwhale.ffa.utils.mustNormalizeUrl import audio.funkwhale.ffa.utils.mustNormalizeUrl
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.android.exoplayer2.offline.Download import com.google.android.exoplayer2.offline.Download
import com.google.android.exoplayer2.offline.DownloadManager import com.google.android.exoplayer2.offline.DownloadManager
import com.google.android.exoplayer2.upstream.cache.Cache import com.google.android.exoplayer2.upstream.cache.Cache

Wyświetl plik

@ -10,10 +10,8 @@ import audio.funkwhale.ffa.model.DownloadInfo
import audio.funkwhale.ffa.repositories.Repository import audio.funkwhale.ffa.repositories.Repository
import com.github.kittinunf.fuel.core.FuelError import com.github.kittinunf.fuel.core.FuelError
import com.github.kittinunf.fuel.core.Request import com.github.kittinunf.fuel.core.Request
import com.github.kittinunf.fuel.core.ResponseDeserializable
import com.google.android.exoplayer2.offline.Download import com.google.android.exoplayer2.offline.Download
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import com.squareup.picasso.RequestCreator import com.squareup.picasso.RequestCreator
import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableDeferred
@ -23,7 +21,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.openid.appauth.ClientSecretPost import net.openid.appauth.ClientSecretPost
import java.io.Reader
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext

Wyświetl plik

@ -52,7 +52,7 @@ class NowPlayingView : MaterialCardView {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() { override fun onGlobalLayout() {
gestureDetectorCallback = OnGestureDetection() gestureDetectorCallback = OnGestureDetection()
gestureDetector = GestureDetector(context, gestureDetectorCallback) gestureDetector = GestureDetector(context, gestureDetectorCallback!!)
setOnTouchListener { _, motionEvent -> setOnTouchListener { _, motionEvent ->
val ret = gestureDetector?.onTouchEvent(motionEvent) ?: false val ret = gestureDetector?.onTouchEvent(motionEvent) ?: false
@ -128,8 +128,8 @@ class NowPlayingView : MaterialCardView {
} }
override fun onFling( override fun onFling(
firstMotionEvent: MotionEvent?, firstMotionEvent: MotionEvent,
secondMotionEvent: MotionEvent?, secondMotionEvent: MotionEvent,
velocityX: Float, velocityX: Float,
velocityY: Float velocityY: Float
): Boolean { ): Boolean {
@ -195,7 +195,7 @@ class NowPlayingView : MaterialCardView {
return true return true
} }
override fun onSingleTapUp(e: MotionEvent?): Boolean { override fun onSingleTapUp(e: MotionEvent): Boolean {
layoutParams.let { layoutParams.let {
if (height != minHeight) return true if (height != minHeight) return true