迁移到Androidx Media3

This commit is contained in:
ag2s20150909
2023-05-11 19:53:56 +08:00
parent 81f5340047
commit 134d62cba7
7 changed files with 122 additions and 46 deletions
+9 -2
View File
@@ -179,8 +179,15 @@ dependencies {
//media //media
implementation("androidx.media:media:1.6.0") implementation("androidx.media:media:1.6.0")
implementation("com.google.android.exoplayer:exoplayer-core:$exoplayer_version") // For media playback using ExoPlayer
implementation("com.google.android.exoplayer:extension-okhttp:$exoplayer_version") implementation "androidx.media3:media3-exoplayer:$media3_version"
// For loading data using the OkHttp network stack
implementation "androidx.media3:media3-datasource-okhttp:$media3_version"
// For exposing and controlling media sessions
//implementation "androidx.media3:media3-session:$media3_version"
// implementation("com.google.android.exoplayer:exoplayer-core:$exoplayer_version")
// implementation("com.google.android.exoplayer:extension-okhttp:$exoplayer_version")
//Splitties //Splitties
implementation("com.louiscad.splitties:splitties-appctx:$splitties_version") implementation("com.louiscad.splitties:splitties-appctx:$splitties_version")
+1 -1
View File
@@ -239,7 +239,7 @@
} }
## ExoPlayer 反射设置ua 保证该私有变量不被混淆 ## ExoPlayer 反射设置ua 保证该私有变量不被混淆
-keepclassmembers class com.google.android.exoplayer2.upstream.cache.CacheDataSource$Factory { -keepclassmembers class androidx.media3.datasource.cache.CacheDataSource$Factory {
*** upstreamDataSourceFactory; *** upstreamDataSourceFactory;
} }
## ExoPlayer 如果还不能播放就取消注释这个 ## ExoPlayer 如果还不能播放就取消注释这个
@@ -1,9 +1,9 @@
package io.legado.app.lib.cronet package io.legado.app.lib.cronet
import android.annotation.SuppressLint
import android.os.Build import android.os.Build
import androidx.annotation.Keep import androidx.annotation.Keep
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import io.legado.app.utils.DebugLog
import okhttp3.Call import okhttp3.Call
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@@ -12,6 +12,7 @@ import java.io.IOException
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@SuppressLint("ObsoleteSdkInt")
@Keep @Keep
@RequiresApi(api = Build.VERSION_CODES.N) @RequiresApi(api = Build.VERSION_CODES.N)
class NewCallBack(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) { class NewCallBack(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) {
@@ -1,35 +1,79 @@
package io.legado.app.help.exoplayer package io.legado.app.help.exoplayer
import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri import android.net.Uri
import com.google.android.exoplayer2.MediaItem import androidx.media3.common.MediaItem
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider import androidx.media3.database.StandaloneDatabaseProvider
import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource import androidx.media3.datasource.DataSource
import com.google.android.exoplayer2.offline.DefaultDownloaderFactory import androidx.media3.datasource.FileDataSource
import com.google.android.exoplayer2.offline.DownloadRequest import androidx.media3.datasource.ResolvingDataSource
import com.google.android.exoplayer2.offline.DownloaderFactory import androidx.media3.datasource.cache.Cache
import com.google.android.exoplayer2.source.MediaSource import androidx.media3.datasource.cache.CacheDataSink
import com.google.android.exoplayer2.source.ProgressiveMediaSource import androidx.media3.datasource.cache.CacheDataSource
import com.google.android.exoplayer2.upstream.DataSource import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
import com.google.android.exoplayer2.upstream.FileDataSource import androidx.media3.datasource.cache.SimpleCache
import com.google.android.exoplayer2.upstream.cache.* import androidx.media3.datasource.okhttp.OkHttpDataSource
import androidx.media3.exoplayer.DefaultLoadControl
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.offline.DefaultDownloaderFactory
import androidx.media3.exoplayer.offline.DownloadRequest
import androidx.media3.exoplayer.offline.DownloaderFactory
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.okHttpClient
import okhttp3.CacheControl import okhttp3.CacheControl
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
import java.lang.reflect.Type
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@SuppressLint("UnsafeOptInUsageError")
object ExoPlayerHelper { object ExoPlayerHelper {
fun createMediaSource( private const val SPLIT_TAG = "\uD83D\uDEA7"
uri: Uri,
defaultRequestProperties: Map<String, String> private val gson by lazy {
): MediaSource { GsonBuilder().create()
val mediaItem = MediaItem.fromUri(uri) }
val mediaSourceFactory = ProgressiveMediaSource.Factory( private val mapType by lazy {
cacheDataSourceFactory.setDefaultRequestProperties(defaultRequestProperties) val type: Type = object : TypeToken<Map<String?, String?>?>() {}.type
type
}
// fun createMediaSource(
// uri: Uri,
// defaultRequestProperties: Map<String, String>
// ): MediaSource {
// val mediaItem = MediaItem.fromUri(uri)
// val mediaSourceFactory = ProgressiveMediaSource.Factory(
// cacheDataSourceFactory.setDefaultRequestProperties(defaultRequestProperties)
// )
// return mediaSourceFactory.createMediaSource(mediaItem)
// }
fun createMediaItem(url: String, headers: Map<String, String>): MediaItem {
val formatUrl = url + SPLIT_TAG + gson.toJson(headers, mapType)
return MediaItem.Builder().setUri(formatUrl).build()
}
fun createExoPlayer(context: Context): ExoPlayer {
return ExoPlayer.Builder(context).setLoadControl(
DefaultLoadControl.Builder().setBufferDurationsMs(
DefaultLoadControl.DEFAULT_MIN_BUFFER_MS,
DefaultLoadControl.DEFAULT_MAX_BUFFER_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS / 10,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS / 10
).build()
) )
return mediaSourceFactory.createMediaSource(mediaItem) .setMediaSourceFactory(
DefaultMediaSourceFactory(context)
.setDataSourceFactory(resolvingDataSource)
.setLiveTargetOffsetMs(5000)
).build()
} }
/** /**
@@ -62,6 +106,31 @@ object ExoPlayerHelper {
} }
private val resolvingDataSource: ResolvingDataSource.Factory by lazy {
ResolvingDataSource.Factory(
cacheDataSourceFactory
) {
var res = it
if (it.uri.toString().contains(SPLIT_TAG)) {
val urls = it.uri.toString().split(SPLIT_TAG)
val url = urls[0]
res = res.withUri(Uri.parse(url))
try {
val headers: Map<String, String> = gson.fromJson(urls[1], mapType)
res = res.withAdditionalHeaders(headers)
} catch (_: Exception) {
}
}
res
}
}
/** /**
* 支持缓存的DataSource.Factory * 支持缓存的DataSource.Factory
*/ */
@@ -7,7 +7,6 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.media.AudioManager import android.media.AudioManager
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.PowerManager import android.os.PowerManager
import android.support.v4.media.MediaMetadataCompat import android.support.v4.media.MediaMetadataCompat
@@ -15,10 +14,10 @@ import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat import android.support.v4.media.session.PlaybackStateCompat
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.media.AudioFocusRequestCompat import androidx.media.AudioFocusRequestCompat
import com.google.android.exoplayer2.DefaultLoadControl import androidx.media3.common.PlaybackException
import com.google.android.exoplayer2.ExoPlayer import androidx.media3.common.Player
import com.google.android.exoplayer2.PlaybackException import androidx.media3.common.util.UnstableApi
import com.google.android.exoplayer2.Player import androidx.media3.exoplayer.ExoPlayer
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseService import io.legado.app.base.BaseService
import io.legado.app.constant.* import io.legado.app.constant.*
@@ -40,6 +39,7 @@ import kotlinx.coroutines.Dispatchers.Main
import splitties.systemservices.audioManager import splitties.systemservices.audioManager
import splitties.systemservices.powerManager import splitties.systemservices.powerManager
@UnstableApi
/** /**
* 音频播放服务 * 音频播放服务
*/ */
@@ -74,14 +74,7 @@ class AudioPlayService : BaseService(),
MediaHelp.buildAudioFocusRequestCompat(this) MediaHelp.buildAudioFocusRequestCompat(this)
} }
private val exoPlayer: ExoPlayer by lazy { private val exoPlayer: ExoPlayer by lazy {
ExoPlayer.Builder(this).setLoadControl( ExoPlayerHelper.createExoPlayer(this)
DefaultLoadControl.Builder().setBufferDurationsMs(
DefaultLoadControl.DEFAULT_MIN_BUFFER_MS,
DefaultLoadControl.DEFAULT_MAX_BUFFER_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS / 10,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS / 10
).build()
).build()
} }
private var mediaSessionCompat: MediaSessionCompat? = null private var mediaSessionCompat: MediaSessionCompat? = null
private var broadcastReceiver: BroadcastReceiver? = null private var broadcastReceiver: BroadcastReceiver? = null
@@ -159,13 +152,14 @@ class AudioPlayService : BaseService(),
chapter = AudioPlay.durChapter, chapter = AudioPlay.durChapter,
headerMapF = AudioPlay.headers(true), headerMapF = AudioPlay.headers(true),
) )
val uri = Uri.parse(analyzeUrl.url) //val uri = Uri.parse(analyzeUrl.url)
//ExoPlayerHelper.preDownload(uri, analyzeUrl.headerMap) //ExoPlayerHelper.preDownload(uri, analyzeUrl.headerMap)
//休息1秒钟,防止403 //休息1秒钟,防止403
//delay(1000) //delay(1000)
val mediaSource = ExoPlayerHelper // val mediaSource = ExoPlayerHelper
.createMediaSource(uri, analyzeUrl.headerMap) // .createMediaSource(uri, analyzeUrl.headerMap)
exoPlayer.setMediaSource(mediaSource) //exoPlayer.setMediaSource(mediaSource)
exoPlayer.setMediaItem(ExoPlayerHelper.createMediaItem(analyzeUrl.url,analyzeUrl.headerMap))
exoPlayer.playWhenReady = true exoPlayer.playWhenReady = true
exoPlayer.prepare() exoPlayer.prepare()
}.onError { }.onError {
@@ -234,8 +228,10 @@ class AudioPlayService : BaseService(),
/** /**
* 调节速度 * 调节速度
*/ */
private fun upSpeed(adjust: Float) { private fun upSpeed(adjust: Float) {
kotlin.runCatching { kotlin.runCatching {
@SuppressLint("ObsoleteSdkInt")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
playSpeed += adjust playSpeed += adjust
exoPlayer.setPlaybackSpeed(playSpeed) exoPlayer.setPlaybackSpeed(playSpeed)
@@ -2,10 +2,10 @@ package io.legado.app.service
import android.app.PendingIntent import android.app.PendingIntent
import android.net.Uri import android.net.Uri
import com.google.android.exoplayer2.ExoPlayer import androidx.media3.common.MediaItem
import com.google.android.exoplayer2.MediaItem import androidx.media3.common.PlaybackException
import com.google.android.exoplayer2.PlaybackException import androidx.media3.common.Player
import com.google.android.exoplayer2.Player import androidx.media3.exoplayer.ExoPlayer
import com.script.ScriptException import com.script.ScriptException
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.AppLog import io.legado.app.constant.AppLog
@@ -16,6 +16,7 @@ import io.legado.app.exception.ConcurrentException
import io.legado.app.exception.NoStackTraceException import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.exoplayer.ExoPlayerHelper
import io.legado.app.model.ReadAloud import io.legado.app.model.ReadAloud
import io.legado.app.model.ReadBook import io.legado.app.model.ReadBook
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
@@ -38,7 +39,8 @@ class HttpReadAloudService : BaseReadAloudService(),
Player.Listener { Player.Listener {
private val exoPlayer: ExoPlayer by lazy { private val exoPlayer: ExoPlayer by lazy {
ExoPlayer.Builder(this).build() //ExoPlayer.Builder(this).build()
ExoPlayerHelper.createExoPlayer(this)
} }
private val ttsFolderPath: String by lazy { private val ttsFolderPath: String by lazy {
cacheDir.absolutePath + File.separator + "httpTTS" + File.separator cacheDir.absolutePath + File.separator + "httpTTS" + File.separator
+2 -1
View File
@@ -6,7 +6,8 @@ buildscript {
build_tool_version = '33.0.1' build_tool_version = '33.0.1'
kotlin_version = '1.8.21' kotlin_version = '1.8.21'
agp_version = '8.0.1' agp_version = '8.0.1'
exoplayer_version = '2.18.6' //exoplayer_version = '2.18.6'
media3_version = "1.0.1"
splitties_version = '3.0.0' splitties_version = '3.0.0'
room_version = '2.5.1' room_version = '2.5.1'
} }