ag2s20150909 3 лет назад
Родитель
Сommit
ab1d08dadf

+ 9 - 2
app/build.gradle

@@ -179,8 +179,15 @@ dependencies {
 
     //media
     implementation("androidx.media:media:1.6.0")
-    implementation("com.google.android.exoplayer:exoplayer-core:$exoplayer_version")
-    implementation("com.google.android.exoplayer:extension-okhttp:$exoplayer_version")
+    // For media playback using ExoPlayer
+    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
     implementation("com.louiscad.splitties:splitties-appctx:$splitties_version")

+ 1 - 1
app/proguard-rules.pro

@@ -239,7 +239,7 @@
 }
 
 ## ExoPlayer 反射设置ua 保证该私有变量不被混淆
--keepclassmembers class com.google.android.exoplayer2.upstream.cache.CacheDataSource$Factory {
+-keepclassmembers class androidx.media3.datasource.cache.CacheDataSource$Factory {
     *** upstreamDataSourceFactory;
 }
 ## ExoPlayer 如果还不能播放就取消注释这个

+ 2 - 1
app/src/app/java/io/legado/app/lib/cronet/NewCallBack.kt

@@ -1,9 +1,9 @@
 package io.legado.app.lib.cronet
 
+import android.annotation.SuppressLint
 import android.os.Build
 import androidx.annotation.Keep
 import androidx.annotation.RequiresApi
-import io.legado.app.utils.DebugLog
 import okhttp3.Call
 import okhttp3.Request
 import okhttp3.Response
@@ -12,6 +12,7 @@ import java.io.IOException
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.TimeUnit
 
+@SuppressLint("ObsoleteSdkInt")
 @Keep
 @RequiresApi(api = Build.VERSION_CODES.N)
 class NewCallBack(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) {

+ 88 - 19
app/src/main/java/io/legado/app/help/exoplayer/ExoPlayerHelper.kt

@@ -1,35 +1,79 @@
 package io.legado.app.help.exoplayer
 
+import android.annotation.SuppressLint
+import android.content.Context
 import android.net.Uri
-import com.google.android.exoplayer2.MediaItem
-import com.google.android.exoplayer2.database.StandaloneDatabaseProvider
-import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource
-import com.google.android.exoplayer2.offline.DefaultDownloaderFactory
-import com.google.android.exoplayer2.offline.DownloadRequest
-import com.google.android.exoplayer2.offline.DownloaderFactory
-import com.google.android.exoplayer2.source.MediaSource
-import com.google.android.exoplayer2.source.ProgressiveMediaSource
-import com.google.android.exoplayer2.upstream.DataSource
-import com.google.android.exoplayer2.upstream.FileDataSource
-import com.google.android.exoplayer2.upstream.cache.*
+import androidx.media3.common.MediaItem
+import androidx.media3.database.StandaloneDatabaseProvider
+import androidx.media3.datasource.DataSource
+import androidx.media3.datasource.FileDataSource
+import androidx.media3.datasource.ResolvingDataSource
+import androidx.media3.datasource.cache.Cache
+import androidx.media3.datasource.cache.CacheDataSink
+import androidx.media3.datasource.cache.CacheDataSource
+import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
+import androidx.media3.datasource.cache.SimpleCache
+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 okhttp3.CacheControl
 import splitties.init.appCtx
 import java.io.File
+import java.lang.reflect.Type
 import java.util.concurrent.TimeUnit
 
 
+@SuppressLint("UnsafeOptInUsageError")
 object ExoPlayerHelper {
 
-    fun createMediaSource(
-        uri: Uri,
-        defaultRequestProperties: Map<String, String>
-    ): MediaSource {
-        val mediaItem = MediaItem.fromUri(uri)
-        val mediaSourceFactory = ProgressiveMediaSource.Factory(
-            cacheDataSourceFactory.setDefaultRequestProperties(defaultRequestProperties)
+    private const val SPLIT_TAG = "\uD83D\uDEA7"
+
+    private val gson by lazy {
+        GsonBuilder().create()
+    }
+    private val mapType by lazy {
+        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
      */

+ 13 - 17
app/src/main/java/io/legado/app/service/AudioPlayService.kt

@@ -7,7 +7,6 @@ import android.content.Intent
 import android.content.IntentFilter
 import android.graphics.BitmapFactory
 import android.media.AudioManager
-import android.net.Uri
 import android.os.Build
 import android.os.PowerManager
 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 androidx.core.app.NotificationCompat
 import androidx.media.AudioFocusRequestCompat
-import com.google.android.exoplayer2.DefaultLoadControl
-import com.google.android.exoplayer2.ExoPlayer
-import com.google.android.exoplayer2.PlaybackException
-import com.google.android.exoplayer2.Player
+import androidx.media3.common.PlaybackException
+import androidx.media3.common.Player
+import androidx.media3.common.util.UnstableApi
+import androidx.media3.exoplayer.ExoPlayer
 import io.legado.app.R
 import io.legado.app.base.BaseService
 import io.legado.app.constant.*
@@ -40,6 +39,7 @@ import kotlinx.coroutines.Dispatchers.Main
 import splitties.systemservices.audioManager
 import splitties.systemservices.powerManager
 
+@UnstableApi
 /**
  * 音频播放服务
  */
@@ -74,14 +74,7 @@ class AudioPlayService : BaseService(),
         MediaHelp.buildAudioFocusRequestCompat(this)
     }
     private val exoPlayer: ExoPlayer by lazy {
-        ExoPlayer.Builder(this).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()
-        ).build()
+       ExoPlayerHelper.createExoPlayer(this)
     }
     private var mediaSessionCompat: MediaSessionCompat? = null
     private var broadcastReceiver: BroadcastReceiver? = null
@@ -159,13 +152,14 @@ class AudioPlayService : BaseService(),
                     chapter = AudioPlay.durChapter,
                     headerMapF = AudioPlay.headers(true),
                 )
-                val uri = Uri.parse(analyzeUrl.url)
+                //val uri = Uri.parse(analyzeUrl.url)
                 //ExoPlayerHelper.preDownload(uri, analyzeUrl.headerMap)
                 //休息1秒钟,防止403
                 //delay(1000)
-                val mediaSource = ExoPlayerHelper
-                    .createMediaSource(uri, analyzeUrl.headerMap)
-                exoPlayer.setMediaSource(mediaSource)
+//                val mediaSource = ExoPlayerHelper
+//                    .createMediaSource(uri, analyzeUrl.headerMap)
+                //exoPlayer.setMediaSource(mediaSource)
+                exoPlayer.setMediaItem(ExoPlayerHelper.createMediaItem(analyzeUrl.url,analyzeUrl.headerMap))
                 exoPlayer.playWhenReady = true
                 exoPlayer.prepare()
             }.onError {
@@ -234,8 +228,10 @@ class AudioPlayService : BaseService(),
     /**
      * 调节速度
      */
+
     private fun upSpeed(adjust: Float) {
         kotlin.runCatching {
+            @SuppressLint("ObsoleteSdkInt")
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                 playSpeed += adjust
                 exoPlayer.setPlaybackSpeed(playSpeed)

+ 7 - 5
app/src/main/java/io/legado/app/service/HttpReadAloudService.kt

@@ -2,10 +2,10 @@ package io.legado.app.service
 
 import android.app.PendingIntent
 import android.net.Uri
-import com.google.android.exoplayer2.ExoPlayer
-import com.google.android.exoplayer2.MediaItem
-import com.google.android.exoplayer2.PlaybackException
-import com.google.android.exoplayer2.Player
+import androidx.media3.common.MediaItem
+import androidx.media3.common.PlaybackException
+import androidx.media3.common.Player
+import androidx.media3.exoplayer.ExoPlayer
 import com.script.ScriptException
 import io.legado.app.R
 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.help.config.AppConfig
 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.ReadBook
 import io.legado.app.model.analyzeRule.AnalyzeUrl
@@ -38,7 +39,8 @@ class HttpReadAloudService : BaseReadAloudService(),
     Player.Listener {
 
     private val exoPlayer: ExoPlayer by lazy {
-        ExoPlayer.Builder(this).build()
+        //ExoPlayer.Builder(this).build()
+        ExoPlayerHelper.createExoPlayer(this)
     }
     private val ttsFolderPath: String by lazy {
         cacheDir.absolutePath + File.separator + "httpTTS" + File.separator

+ 2 - 1
build.gradle

@@ -6,7 +6,8 @@ buildscript {
         build_tool_version = '33.0.1'
         kotlin_version = '1.8.21'
         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'
         room_version = '2.5.1'
     }