|
|
@@ -9,11 +9,18 @@ import android.os.Message
|
|
|
import android.util.AttributeSet
|
|
|
import android.view.MotionEvent
|
|
|
import android.webkit.*
|
|
|
+import androidx.webkit.WebViewAssetLoader
|
|
|
+import com.adealink.frame.base.fastLazy
|
|
|
import com.adealink.frame.log.Log
|
|
|
import com.adealink.frame.util.ONE_SECOND
|
|
|
import com.adealink.weparty.webview.BaseWebView
|
|
|
import com.adealink.weparty.webview.CommonWebViewClient
|
|
|
import com.adealink.weparty.webview.jsbridge.JSBridge
|
|
|
+import com.adealink.weparty.module.profile.ProfileModule
|
|
|
+import com.adealink.weparty.youtube.config.YoutubePlayerConfigManager
|
|
|
+import com.adealink.weparty.youtube.data.PlayerLoadType
|
|
|
+import com.adealink.weparty.youtube.data.TAG_YOUTUBE
|
|
|
+import com.adealink.weparty.youtube.util.isLoginYoutube
|
|
|
|
|
|
/**
|
|
|
* WebView implementation of YouTube Player based on IFrame Player API.
|
|
|
@@ -39,7 +46,6 @@ class YouTubePlayerWebView @JvmOverloads constructor(
|
|
|
private var hasInitialized = false
|
|
|
private var playerListener: IYoutubePlayerListener? = null
|
|
|
private var defVideoThumb: Bitmap? = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565)
|
|
|
- private var showErrorToast = true
|
|
|
|
|
|
private val mainThreadHandler: Handler = object : Handler(Looper.getMainLooper()) {
|
|
|
override fun handleMessage(msg: Message) {
|
|
|
@@ -59,23 +65,36 @@ class YouTubePlayerWebView @JvmOverloads constructor(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fun setShowErrorToast(showToast: Boolean) {
|
|
|
- showErrorToast = showToast
|
|
|
+ /**
|
|
|
+ * 获取当前播放器加载类型
|
|
|
+ */
|
|
|
+ fun getCurrentLoadType(): PlayerLoadType {
|
|
|
+ return getCurrentPlayerConfig().loadType
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 重新初始化播放器(使用最新的配置)
|
|
|
+ */
|
|
|
+ fun reinitialize() {
|
|
|
+ hasInitialized = false
|
|
|
+ initializePlayer(getCurrentPlayerConfig().loadType)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前播放器配置
|
|
|
+ */
|
|
|
+ private fun getCurrentPlayerConfig() = YoutubePlayerConfigManager.resolveConfig(
|
|
|
+ userId = ProfileModule.getMyUserInfo()?.uid,
|
|
|
+ countryCode = ProfileModule.getMyUserInfo()?.country
|
|
|
+ )
|
|
|
+
|
|
|
/**
|
|
|
* If player not call back onReady for a time, then auto retry
|
|
|
*/
|
|
|
private val tryReloadPlayerTask = Runnable {
|
|
|
if (hasInitialized.not()) {
|
|
|
Log.w(TAG, "player not initialize yet")
|
|
|
- loadDataWithBaseURL(
|
|
|
- playerOptions.getOrigin(),
|
|
|
- videoHTMLBuilder(),
|
|
|
- "text/html",
|
|
|
- "utf-8",
|
|
|
- null
|
|
|
- )
|
|
|
+ initializePlayer(getCurrentPlayerConfig().loadType)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -121,11 +140,35 @@ class YouTubePlayerWebView @JvmOverloads constructor(
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ private val assetLoader by fastLazy {
|
|
|
+ WebViewAssetLoader.Builder()
|
|
|
+ .addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(context))
|
|
|
+ .build()
|
|
|
+ }
|
|
|
+
|
|
|
override fun initWebViewClient() {
|
|
|
webViewClient = object : CommonWebViewClient(this) {
|
|
|
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
|
|
|
return false
|
|
|
}
|
|
|
+
|
|
|
+ override fun shouldInterceptRequest(
|
|
|
+ view: WebView,
|
|
|
+ request: WebResourceRequest
|
|
|
+ ): WebResourceResponse? {
|
|
|
+ if (request.url.host == WebViewAssetLoader.DEFAULT_DOMAIN) {
|
|
|
+ if (request.url.path == "/favicon.ico") {
|
|
|
+ Log.d(TAG_YOUTUBE, "ignore load favicon.ico")
|
|
|
+ return WebResourceResponse(
|
|
|
+ "text/html",
|
|
|
+ "UTF-8",
|
|
|
+ ByteArray(0).inputStream()
|
|
|
+ )
|
|
|
+ }
|
|
|
+ return assetLoader.shouldInterceptRequest(request.url)
|
|
|
+ }
|
|
|
+ return super.shouldInterceptRequest(view, request)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -139,14 +182,21 @@ class YouTubePlayerWebView @JvmOverloads constructor(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fun initialize(options: YoutubePlayerOptions? = null, autoRetry: Boolean = true) {
|
|
|
+ fun initialize(
|
|
|
+ options: YoutubePlayerOptions? = null,
|
|
|
+ loadType: PlayerLoadType? = null,
|
|
|
+ autoRetry: Boolean = true
|
|
|
+ ) {
|
|
|
if (options != null) {
|
|
|
playerOptions = options
|
|
|
}
|
|
|
- loadDataWithBaseURL(
|
|
|
- playerOptions.getOrigin(),
|
|
|
- videoHTMLBuilder(), "text/html", "utf-8", null
|
|
|
- )
|
|
|
+
|
|
|
+ // 如果指定了loadType则使用指定的,否则通过配置管理器解析
|
|
|
+ val actualLoadType = loadType ?: getCurrentPlayerConfig().loadType
|
|
|
+
|
|
|
+ Log.d(TAG, "Initialize with loadType: $actualLoadType, userId: ${ProfileModule.getMyUserInfo()?.uid}, country: ${ProfileModule.getMyUserInfo()?.country}")
|
|
|
+
|
|
|
+ initializePlayer(actualLoadType)
|
|
|
if (autoRetry) {
|
|
|
mainThreadHandler.removeCallbacks(tryReloadPlayerTask)
|
|
|
mainThreadHandler.postDelayed(tryReloadPlayerTask, 15 * ONE_SECOND)
|
|
|
@@ -207,23 +257,52 @@ class YouTubePlayerWebView @JvmOverloads constructor(
|
|
|
private fun loadJSUrl(url: String) {
|
|
|
Log.i(TAG, "loadJs: $url")
|
|
|
if (hasInitialized.not()) {
|
|
|
- loadDataWithBaseURL(
|
|
|
- playerOptions.getOrigin(),
|
|
|
- videoHTMLBuilder() ?: "",
|
|
|
- "text/html",
|
|
|
- "utf-8",
|
|
|
- null
|
|
|
- )
|
|
|
+ initializePlayer(getCurrentPlayerConfig().loadType)
|
|
|
Log.w(TAG, "player not initialize yet")
|
|
|
- if (showErrorToast) {
|
|
|
-// Util.showToastFailed(context)
|
|
|
- }
|
|
|
-// reportVideoError("initialize_not")
|
|
|
return
|
|
|
}
|
|
|
mainThreadHandler.post { loadUrl(url) }
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 根据指定的加载类型初始化播放器
|
|
|
+ */
|
|
|
+ private fun initializePlayer(loadType: PlayerLoadType) {
|
|
|
+ when (loadType) {
|
|
|
+ PlayerLoadType.OFFICIAL_ORIGIN -> loadWithOfficialOrigin()
|
|
|
+ PlayerLoadType.ASSETS_HTML -> loadWithAssetsHtml()
|
|
|
+ PlayerLoadType.CUSTOM -> loadWithCustom()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 使用伪装origin为官方域名方式加载播放器
|
|
|
+ */
|
|
|
+ private fun loadWithOfficialOrigin() {
|
|
|
+ loadDataWithBaseURL(
|
|
|
+ playerOptions.getOrigin(),
|
|
|
+ videoHTMLBuilder(), "text/html", "utf-8", null
|
|
|
+ )
|
|
|
+ Log.d(TAG_YOUTUBE, "isLogin:${isLoginYoutube()}")
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加载assets里面的HTML文件方式
|
|
|
+ */
|
|
|
+ private fun loadWithAssetsHtml() {
|
|
|
+ // 加载assets中的HTML文件
|
|
|
+ loadUrl("https://${WebViewAssetLoader.DEFAULT_DOMAIN}/assets/youtube_embed.html")
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 自建网址方式加载
|
|
|
+ */
|
|
|
+ private fun loadWithCustom() {
|
|
|
+ val customUrl = getCurrentPlayerConfig().url ?: return
|
|
|
+ Log.d(TAG, "Loading custom URL: $url")
|
|
|
+ loadUrl(customUrl)
|
|
|
+ }
|
|
|
+
|
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
|
override fun onTouchEvent(ev: MotionEvent): Boolean {
|
|
|
return false
|