mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-07-29 15:49:30 +00:00
ref: playbackDataSourceFactory to be in parity with Nuvio TV
This commit is contained in:
parent
3625a72ee7
commit
73c29ccab8
3 changed files with 108 additions and 26 deletions
|
|
@ -3,18 +3,9 @@ package com.nuvio.app.features.player
|
|||
import android.content.Context
|
||||
import androidx.media3.datasource.DataSource
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
import androidx.media3.datasource.DefaultHttpDataSource
|
||||
import com.nuvio.app.features.trailer.YoutubeChunkedDataSourceFactory
|
||||
|
||||
internal object PlatformPlaybackDataSourceFactory {
|
||||
|
||||
private val DEFAULT_STREAM_HEADERS = mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/120.0.0.0 Safari/537.36",
|
||||
"Referer" to "https://www.strem.io/"
|
||||
)
|
||||
|
||||
fun create(
|
||||
context: Context,
|
||||
defaultRequestHeaders: Map<String, String>,
|
||||
|
|
@ -24,9 +15,7 @@ internal object PlatformPlaybackDataSourceFactory {
|
|||
val networkFactory: DataSource.Factory = if (useYoutubeChunkedPlayback) {
|
||||
YoutubeChunkedDataSourceFactory(defaultRequestHeaders = defaultRequestHeaders)
|
||||
} else {
|
||||
DefaultHttpDataSource.Factory()
|
||||
.setAllowCrossProtocolRedirects(true)
|
||||
.setDefaultRequestProperties(DEFAULT_STREAM_HEADERS + defaultRequestHeaders)
|
||||
PlayerPlaybackNetworking.createHttpDataSourceFactory(defaultRequestHeaders)
|
||||
}
|
||||
val baseFactory: DataSource.Factory = DefaultDataSource.Factory(context, networkFactory)
|
||||
return if (defaultResponseHeaders.isEmpty()) {
|
||||
|
|
@ -38,4 +27,4 @@ internal object PlatformPlaybackDataSourceFactory {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package com.nuvio.app.features.player
|
||||
|
||||
import android.content.Context
|
||||
import androidx.media3.datasource.DataSource
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
import androidx.media3.datasource.okhttp.OkHttpDataSource
|
||||
import com.nuvio.app.core.network.IPv4FirstDns
|
||||
import okhttp3.OkHttpClient
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.security.SecureRandom
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.net.ssl.HostnameVerifier
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
internal object PlayerPlaybackNetworking {
|
||||
private val DEFAULT_STREAM_HEADERS = mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/120.0.0.0 Safari/537.36",
|
||||
|
||||
)
|
||||
|
||||
internal const val DEFAULT_USER_AGENT =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " +
|
||||
"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
|
||||
private val trustAllManager = object : X509TrustManager {
|
||||
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unit
|
||||
|
||||
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unit
|
||||
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
|
||||
}
|
||||
|
||||
private val playbackHostnameVerifier = HostnameVerifier { _, _ -> true }
|
||||
|
||||
private val sslContext: SSLContext by lazy {
|
||||
SSLContext.getInstance("TLS").apply {
|
||||
init(null, arrayOf<TrustManager>(trustAllManager), SecureRandom())
|
||||
}
|
||||
}
|
||||
|
||||
private val playbackHttpClient: OkHttpClient by lazy {
|
||||
OkHttpClient.Builder()
|
||||
.dns(IPv4FirstDns())
|
||||
.sslSocketFactory(sslContext.socketFactory, trustAllManager)
|
||||
.hostnameVerifier(playbackHostnameVerifier)
|
||||
.connectTimeout(15, TimeUnit.SECONDS)
|
||||
.readTimeout(15, TimeUnit.SECONDS)
|
||||
.writeTimeout(15, TimeUnit.SECONDS)
|
||||
.followRedirects(true)
|
||||
.followSslRedirects(true)
|
||||
.retryOnConnectionFailure(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun createHttpDataSourceFactory(defaultHeaders: Map<String, String> = emptyMap()): DataSource.Factory {
|
||||
val mergedHeaders = DEFAULT_STREAM_HEADERS + defaultHeaders
|
||||
return OkHttpDataSource.Factory(playbackHttpClient).apply {
|
||||
setDefaultRequestProperties(mergedHeaders)
|
||||
setUserAgent(DEFAULT_USER_AGENT)
|
||||
}
|
||||
}
|
||||
|
||||
fun createDataSourceFactory(
|
||||
context: Context,
|
||||
defaultHeaders: Map<String, String> = emptyMap(),
|
||||
): DataSource.Factory {
|
||||
return DefaultDataSource.Factory(context, createHttpDataSourceFactory(defaultHeaders))
|
||||
}
|
||||
|
||||
fun openConnection(
|
||||
url: String,
|
||||
headers: Map<String, String>,
|
||||
method: String,
|
||||
connectTimeoutMs: Int,
|
||||
readTimeoutMs: Int,
|
||||
range: String? = null,
|
||||
): HttpURLConnection {
|
||||
val mergedHeaders = DEFAULT_STREAM_HEADERS + headers
|
||||
return (URL(url).openConnection() as HttpURLConnection).apply {
|
||||
if (this is HttpsURLConnection) {
|
||||
sslSocketFactory = sslContext.socketFactory
|
||||
hostnameVerifier = playbackHostnameVerifier
|
||||
}
|
||||
instanceFollowRedirects = true
|
||||
connectTimeout = connectTimeoutMs
|
||||
readTimeout = readTimeoutMs
|
||||
requestMethod = method
|
||||
setRequestProperty("User-Agent", mergedHeaders["User-Agent"] ?: DEFAULT_USER_AGENT)
|
||||
mergedHeaders.forEach { (key, value) ->
|
||||
if (key.equals("Range", ignoreCase = true)) return@forEach
|
||||
if (key.equals("User-Agent", ignoreCase = true)) return@forEach
|
||||
setRequestProperty(key, value)
|
||||
}
|
||||
range?.let { setRequestProperty("Range", it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,26 +3,15 @@ package com.nuvio.app.features.player
|
|||
import android.content.Context
|
||||
import androidx.media3.datasource.DataSource
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
import androidx.media3.datasource.DefaultHttpDataSource
|
||||
|
||||
internal object PlatformPlaybackDataSourceFactory {
|
||||
|
||||
private val DEFAULT_STREAM_HEADERS = mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/120.0.0.0 Safari/537.36",
|
||||
"Referer" to "https://www.strem.io/"
|
||||
)
|
||||
|
||||
fun create(
|
||||
context: Context,
|
||||
defaultRequestHeaders: Map<String, String>,
|
||||
defaultResponseHeaders: Map<String, String>,
|
||||
useYoutubeChunkedPlayback: Boolean,
|
||||
): DataSource.Factory {
|
||||
val httpFactory = DefaultHttpDataSource.Factory()
|
||||
.setAllowCrossProtocolRedirects(true)
|
||||
.setDefaultRequestProperties(DEFAULT_STREAM_HEADERS + defaultRequestHeaders)
|
||||
val httpFactory = PlayerPlaybackNetworking.createHttpDataSourceFactory(defaultRequestHeaders)
|
||||
val baseFactory: DataSource.Factory = DefaultDataSource.Factory(context, httpFactory)
|
||||
return if (defaultResponseHeaders.isEmpty()) {
|
||||
baseFactory
|
||||
|
|
@ -33,4 +22,4 @@ internal object PlatformPlaybackDataSourceFactory {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue