4k
This commit is contained in:
@@ -144,10 +144,12 @@ class BrowserActivity : AppCompatActivity(), RemoteControlCallback {
|
|||||||
@Volatile private var contentFilterActive: Boolean = false
|
@Volatile private var contentFilterActive: Boolean = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 已切到原生 / 外部播放器、网页视频被暂停:期间拒绝网页的子资源请求(shouldInterceptRequest 在后台线程读取)。
|
* 已切到原生 / 外部播放器或退到后台、网页视频被暂停:期间拒绝网页的子资源请求(shouldInterceptRequest 在后台线程读取)。
|
||||||
* 网页播放器暂停后仍会继续缓冲分片(部分站点还带 P2P 加速),会和原生播放器抢网速;回到本页或打开新页面时解除。
|
* 网页播放器暂停后仍会继续缓冲分片(部分站点还带 P2P 加速),会和原生播放器抢网速;回到本页或打开新页面时解除。
|
||||||
*/
|
*/
|
||||||
@Volatile private var webMediaSuspended: Boolean = false
|
@Volatile private var webMediaSuspended: Boolean = false
|
||||||
|
/** 当前 Activity 是否处于前台可见状态(onResume ~ onPause),供后台网络拦截与页面完成回调判断是否立即暂停网页媒体 */
|
||||||
|
@Volatile private var isActivityResumed: Boolean = false
|
||||||
|
|
||||||
/** 防跳转劫持:用户最近一次真实点击的链接与时间(JS 线程写入,UI 线程读取) */
|
/** 防跳转劫持:用户最近一次真实点击的链接与时间(JS 线程写入,UI 线程读取) */
|
||||||
@Volatile private var lastUserLink: String? = null
|
@Volatile private var lastUserLink: String? = null
|
||||||
@@ -316,10 +318,10 @@ class BrowserActivity : AppCompatActivity(), RemoteControlCallback {
|
|||||||
request: WebResourceRequest?
|
request: WebResourceRequest?
|
||||||
): WebResourceResponse? {
|
): WebResourceResponse? {
|
||||||
val reqUrl = request?.url?.toString() ?: return null
|
val reqUrl = request?.url?.toString() ?: return null
|
||||||
// 原生 / 外部播放器播放中:网页不再加载任何子资源(分片、清单刷新、P2P 回源、广告轮询),把网速留给播放器
|
// 原生 / 外部播放器播放中或已退到后台:网页不再加载任何子资源(分片、清单刷新、P2P 回源、广告轮询),把网速留给播放器或避免后台偷跑
|
||||||
if (request.isForMainFrame) {
|
if (request.isForMainFrame) {
|
||||||
webMediaSuspended = false
|
if (isActivityResumed) webMediaSuspended = false
|
||||||
} else if (webMediaSuspended) {
|
} else if (webMediaSuspended || !isActivityResumed) {
|
||||||
return VideoSnifferHelper.createRejectedResponse()
|
return VideoSnifferHelper.createRejectedResponse()
|
||||||
}
|
}
|
||||||
// 0. 记录请求头,原生播放器回放时使用(Referer / UA 等)
|
// 0. 记录请求头,原生播放器回放时使用(Referer / UA 等)
|
||||||
@@ -376,6 +378,10 @@ class BrowserActivity : AppCompatActivity(), RemoteControlCallback {
|
|||||||
// 强力过滤:隐藏可疑动图 / 色情博彩广告
|
// 强力过滤:隐藏可疑动图 / 色情博彩广告
|
||||||
updateContentFilterState(url)
|
updateContentFilterState(url)
|
||||||
if (contentFilterActive) view?.evaluateJavascript(ContentFilterHelper.JS_CONTENT_FILTER, null)
|
if (contentFilterActive) view?.evaluateJavascript(ContentFilterHelper.JS_CONTENT_FILTER, null)
|
||||||
|
if (!isActivityResumed) {
|
||||||
|
suspendWebMedia()
|
||||||
|
view?.onPause()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageCommitVisible(view: WebView?, url: String?) {
|
override fun onPageCommitVisible(view: WebView?, url: String?) {
|
||||||
@@ -385,6 +391,10 @@ class BrowserActivity : AppCompatActivity(), RemoteControlCallback {
|
|||||||
injectDesktopModeFallback(view)
|
injectDesktopModeFallback(view)
|
||||||
// 新页面首帧可见时再注入一次,尽量在广告图显示前隐藏
|
// 新页面首帧可见时再注入一次,尽量在广告图显示前隐藏
|
||||||
if (contentFilterActive) view?.evaluateJavascript(ContentFilterHelper.JS_CONTENT_FILTER, null)
|
if (contentFilterActive) view?.evaluateJavascript(ContentFilterHelper.JS_CONTENT_FILTER, null)
|
||||||
|
if (!isActivityResumed) {
|
||||||
|
suspendWebMedia()
|
||||||
|
view?.onPause()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageFinished(view: WebView?, url: String?) {
|
override fun onPageFinished(view: WebView?, url: String?) {
|
||||||
@@ -404,6 +414,10 @@ class BrowserActivity : AppCompatActivity(), RemoteControlCallback {
|
|||||||
view?.evaluateJavascript(VideoSnifferHelper.JS_SITE_ADAPTER_MACCMS, null)
|
view?.evaluateJavascript(VideoSnifferHelper.JS_SITE_ADAPTER_MACCMS, null)
|
||||||
url?.let { injectUserScripts(it) }
|
url?.let { injectUserScripts(it) }
|
||||||
url?.let { historyRepository.add(it, currentPageTitle.ifEmpty { it }) }
|
url?.let { historyRepository.add(it, currentPageTitle.ifEmpty { it }) }
|
||||||
|
if (!isActivityResumed) {
|
||||||
|
suspendWebMedia()
|
||||||
|
view?.onPause()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
@Deprecated("Deprecated in Java")
|
||||||
@@ -2554,8 +2568,12 @@ class BrowserActivity : AppCompatActivity(), RemoteControlCallback {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
// 从原生 / 外部播放器回来:恢复网页加载
|
isActivityResumed = true
|
||||||
if (::webView.isInitialized) resumeWebMediaIfSuspended()
|
// 从后台或原生 / 外部播放器回来:恢复 WebView 与网页加载
|
||||||
|
if (::webView.isInitialized) {
|
||||||
|
webView.onResume()
|
||||||
|
resumeWebMediaIfSuspended()
|
||||||
|
}
|
||||||
// 从播放器返回首页时刷新追剧列表(进度 / 下一集)
|
// 从播放器返回首页时刷新追剧列表(进度 / 下一集)
|
||||||
if (isOnHomePage && ::binding.isInitialized) updateContinueWatchingBanner()
|
if (isOnHomePage && ::binding.isInitialized) updateContinueWatchingBanner()
|
||||||
// 自愈:回到前台时重新计算光标显示状态
|
// 自愈:回到前台时重新计算光标显示状态
|
||||||
@@ -2563,10 +2581,25 @@ class BrowserActivity : AppCompatActivity(), RemoteControlCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
isActivityResumed = false
|
||||||
cancelAutoPlay(markHandled = true)
|
cancelAutoPlay(markHandled = true)
|
||||||
|
if (::webView.isInitialized) {
|
||||||
|
suspendWebMedia()
|
||||||
|
webView.onPause()
|
||||||
|
}
|
||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
isActivityResumed = false
|
||||||
|
cancelAutoPlay(markHandled = true)
|
||||||
|
if (::webView.isInitialized) {
|
||||||
|
suspendWebMedia()
|
||||||
|
webView.onPause()
|
||||||
|
}
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
@Deprecated("Deprecated in Java")
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
// 自动接管播放倒计时中:返回键只取消倒计时
|
// 自动接管播放倒计时中:返回键只取消倒计时
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
/** 当前片源是否已做过片头检查 / 已触发片尾 */
|
/** 当前片源是否已做过片头检查 / 已触发片尾 */
|
||||||
private var introChecked = false
|
private var introChecked = false
|
||||||
private var outroTriggered = false
|
private var outroTriggered = false
|
||||||
|
/** 是否已退到后台(按 Home 键等触发 onPause / onStop,非画中画状态):防止后台异步解析完成后自动出声播放 */
|
||||||
|
private var isInBackground = false
|
||||||
|
|
||||||
/** 下一集预解析:独立的后台解析器(VideoResolver 一个实例同时只能解析一个页面) */
|
/** 下一集预解析:独立的后台解析器(VideoResolver 一个实例同时只能解析一个页面) */
|
||||||
private var preloadResolver: VideoResolver? = null
|
private var preloadResolver: VideoResolver? = null
|
||||||
@@ -250,6 +252,8 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
private fun initPlayer() {
|
private fun initPlayer() {
|
||||||
val p = ExoPlayer.Builder(this, createRenderersFactory())
|
val p = ExoPlayer.Builder(this, createRenderersFactory())
|
||||||
.setLoadControl(PlayerTuning.buildLoadControl())
|
.setLoadControl(PlayerTuning.buildLoadControl())
|
||||||
|
.setAudioAttributes(androidx.media3.common.AudioAttributes.DEFAULT, true)
|
||||||
|
.setHandleAudioBecomingNoisy(true)
|
||||||
.build()
|
.build()
|
||||||
p.addAnalyticsListener(diagnostics)
|
p.addAnalyticsListener(diagnostics)
|
||||||
binding.playerView.player = p
|
binding.playerView.player = p
|
||||||
@@ -407,16 +411,20 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
p.setMediaSource(mediaSource, startPos)
|
p.setMediaSource(mediaSource, startPos)
|
||||||
p.setPlaybackSpeed(speeds[currentSpeedIndex])
|
p.setPlaybackSpeed(speeds[currentSpeedIndex])
|
||||||
p.prepare()
|
p.prepare()
|
||||||
p.playWhenReady = true
|
val canPlayNow = !isInBackground
|
||||||
|
p.playWhenReady = canPlayNow
|
||||||
|
if (!canPlayNow) p.pause()
|
||||||
if (carried <= 0 && record != null && startPos > 0) showFeedback("已自动续播至 ${record.formatPosition()}")
|
if (carried <= 0 && record != null && startPos > 0) showFeedback("已自动续播至 ${record.formatPosition()}")
|
||||||
|
|
||||||
Log.d(TAG, "play: ${source.url} hls=${source.isHls} headers=${source.headers.keys}")
|
Log.d(TAG, "play: ${source.url} hls=${source.isHls} canPlayNow=$canPlayNow headers=${source.headers.keys}")
|
||||||
lastSavedSec = 0
|
lastSavedSec = 0
|
||||||
suppressSave = false
|
suppressSave = false
|
||||||
introChecked = false
|
introChecked = false
|
||||||
outroTriggered = false
|
outroTriggered = false
|
||||||
mainHandler.removeCallbacks(updateProgressRunnable)
|
mainHandler.removeCallbacks(updateProgressRunnable)
|
||||||
mainHandler.post(updateProgressRunnable)
|
if (canPlayNow) mainHandler.post(updateProgressRunnable)
|
||||||
|
updatePlayPauseButtonText()
|
||||||
|
updatePauseOverlay()
|
||||||
updateEpisodeUi()
|
updateEpisodeUi()
|
||||||
showOsdTemporarily()
|
showOsdTemporarily()
|
||||||
}
|
}
|
||||||
@@ -456,7 +464,11 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
private fun handlePlayerError(error: PlaybackException) {
|
private fun handlePlayerError(error: PlaybackException) {
|
||||||
binding.playerLoading.visibility = View.GONE
|
binding.playerLoading.visibility = View.GONE
|
||||||
val cause = PlayerSsl.rootCauseText(error)
|
val cause = PlayerSsl.rootCauseText(error)
|
||||||
Log.e(TAG, "playback error: ${error.errorCodeName} cause=$cause", error)
|
Log.e(TAG, "playback error: ${error.errorCodeName} cause=$cause inBg=$isInBackground", error)
|
||||||
|
if (isInBackground) {
|
||||||
|
pauseForBackground()
|
||||||
|
return
|
||||||
|
}
|
||||||
val page = currentPageUrl
|
val page = currentPageUrl
|
||||||
// 证书 / SSL 握手失败:网页会忽略证书错误继续播,原生播放器这里同样放宽后重试一次
|
// 证书 / SSL 握手失败:网页会忽略证书错误继续播,原生播放器这里同样放宽后重试一次
|
||||||
if (PlayerSsl.isSslError(error) && PlayerSsl.enableLenient()) {
|
if (PlayerSsl.isSslError(error) && PlayerSsl.enableLenient()) {
|
||||||
@@ -711,6 +723,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun maybeSkipOutro(current: Long, duration: Long) {
|
private fun maybeSkipOutro(current: Long, duration: Long) {
|
||||||
|
if (isInBackground || player?.isPlaying != true) return
|
||||||
if (outroTriggered || duration <= 0 || !hasNextEpisode()) return
|
if (outroTriggered || duration <= 0 || !hasNextEpisode()) return
|
||||||
val outro = AppSettings.getSkip(this, skipKey()).outroMs
|
val outro = AppSettings.getSkip(this, skipKey()).outroMs
|
||||||
if (outro <= 0 || outro >= duration) return
|
if (outro <= 0 || outro >= duration) return
|
||||||
@@ -1209,17 +1222,19 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
override fun onUserLeaveHint() {
|
override fun onUserLeaveHint() {
|
||||||
super.onUserLeaveHint()
|
super.onUserLeaveHint()
|
||||||
val inPip = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInPictureInPictureMode
|
val inPip = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInPictureInPictureMode
|
||||||
if (!inPip) pauseForBackground()
|
if (!inPip) {
|
||||||
|
isInBackground = true
|
||||||
|
pauseForBackground()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 切到后台时暂停播放,并同步按钮文字 / 暂停浮层,回到前台时保持暂停状态 */
|
/** 切到后台时暂停播放,并同步按钮文字 / 暂停浮层,回到前台时保持暂停状态 */
|
||||||
private fun pauseForBackground() {
|
private fun pauseForBackground() {
|
||||||
val p = player ?: return
|
val p = player ?: return
|
||||||
if (p.playWhenReady) {
|
p.playWhenReady = false
|
||||||
p.pause()
|
p.pause()
|
||||||
updatePlayPauseButtonText()
|
updatePlayPauseButtonText()
|
||||||
updatePauseOverlay()
|
updatePauseOverlay()
|
||||||
}
|
|
||||||
saveCurrentProgress()
|
saveCurrentProgress()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1431,17 +1446,30 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
isInBackground = false
|
||||||
hideSystemUI()
|
hideSystemUI()
|
||||||
|
if (currentSource != null) {
|
||||||
|
mainHandler.removeCallbacks(updateProgressRunnable)
|
||||||
|
mainHandler.post(updateProgressRunnable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
val inPip = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) isInPictureInPictureMode else false
|
val inPip = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) isInPictureInPictureMode else false
|
||||||
if (!inPip) pauseForBackground() else saveCurrentProgress()
|
if (!inPip) {
|
||||||
|
isInBackground = true
|
||||||
|
pauseForBackground()
|
||||||
|
} else {
|
||||||
|
saveCurrentProgress()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
|
isInBackground = true
|
||||||
|
mainHandler.removeCallbacks(updateProgressRunnable)
|
||||||
|
cancelPreload()
|
||||||
// 兜底:任何情况下界面完全不可见(含关闭画中画小窗)都暂停,避免后台继续出声
|
// 兜底:任何情况下界面完全不可见(含关闭画中画小窗)都暂停,避免后台继续出声
|
||||||
pauseForBackground()
|
pauseForBackground()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,13 +325,20 @@ object VideoSnifferHelper {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
// 记录页面里的 hls.js 实例:切到原生播放器时 stopLoad(),否则网页播放器暂停后仍会在后台继续缓冲分片,和原生播放器抢网速
|
// 记录页面里的 hls.js 实例:切到原生播放器或退到后台时 stopLoad(),否则网页播放器暂停后仍会在后台继续缓冲分片,和原生播放器抢网速
|
||||||
var hlsList = [];
|
var hlsList = [];
|
||||||
|
var mediaSuspended = false;
|
||||||
function trackHls(h) {
|
function trackHls(h) {
|
||||||
try {
|
try {
|
||||||
if (!h || hlsList.indexOf(h) >= 0) return;
|
if (!h) return;
|
||||||
hlsList.push(h);
|
if (hlsList.indexOf(h) < 0) {
|
||||||
if (hlsList.length > 20) hlsList.shift();
|
hlsList.push(h);
|
||||||
|
if (hlsList.length > 20) hlsList.shift();
|
||||||
|
}
|
||||||
|
if (mediaSuspended && !h.__tvSuspended && typeof h.stopLoad === 'function') {
|
||||||
|
h.stopLoad();
|
||||||
|
h.__tvSuspended = true;
|
||||||
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
function wrapHls(H) {
|
function wrapHls(H) {
|
||||||
@@ -372,6 +379,27 @@ object VideoSnifferHelper {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
var origPlay = HTMLMediaElement.prototype.play;
|
||||||
|
if (typeof origPlay === 'function') {
|
||||||
|
HTMLMediaElement.prototype.play = function() {
|
||||||
|
if (mediaSuspended) {
|
||||||
|
try { this.pause(); } catch (_) {}
|
||||||
|
return window.Promise ? Promise.resolve() : undefined;
|
||||||
|
}
|
||||||
|
return origPlay.apply(this, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function onMediaPlay(ev) {
|
||||||
|
if (!mediaSuspended) return;
|
||||||
|
var t = ev && ev.target;
|
||||||
|
if (t && typeof t.pause === 'function') {
|
||||||
|
try { t.pause(); } catch (_) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener('play', onMediaPlay, true);
|
||||||
|
document.addEventListener('playing', onMediaPlay, true);
|
||||||
|
} catch (e) {}
|
||||||
try {
|
try {
|
||||||
window.addEventListener('message', function(e) {
|
window.addEventListener('message', function(e) {
|
||||||
try {
|
try {
|
||||||
@@ -379,6 +407,7 @@ object VideoSnifferHelper {
|
|||||||
if (!data || (data.__tvcmd !== 'pause' && data.__tvcmd !== 'resume')) return;
|
if (!data || (data.__tvcmd !== 'pause' && data.__tvcmd !== 'resume')) return;
|
||||||
var i;
|
var i;
|
||||||
if (data.__tvcmd === 'pause') {
|
if (data.__tvcmd === 'pause') {
|
||||||
|
mediaSuspended = true;
|
||||||
var vs = document.querySelectorAll('video,audio');
|
var vs = document.querySelectorAll('video,audio');
|
||||||
for (i = 0; i < vs.length; i++) { try { vs[i].pause(); } catch (_) {} }
|
for (i = 0; i < vs.length; i++) { try { vs[i].pause(); } catch (_) {} }
|
||||||
// 暂停后 hls.js 仍会缓冲到上限(不少站点设到几分钟),停止加载,回到网页时再恢复
|
// 暂停后 hls.js 仍会缓冲到上限(不少站点设到几分钟),停止加载,回到网页时再恢复
|
||||||
@@ -386,6 +415,7 @@ object VideoSnifferHelper {
|
|||||||
try { if (!hlsList[i].__tvSuspended) { hlsList[i].stopLoad(); hlsList[i].__tvSuspended = true; } } catch (_) {}
|
try { if (!hlsList[i].__tvSuspended) { hlsList[i].stopLoad(); hlsList[i].__tvSuspended = true; } } catch (_) {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
mediaSuspended = false;
|
||||||
for (i = 0; i < hlsList.length; i++) {
|
for (i = 0; i < hlsList.length; i++) {
|
||||||
try { if (hlsList[i].__tvSuspended) { hlsList[i].__tvSuspended = false; hlsList[i].startLoad(); } } catch (_) {}
|
try { if (hlsList[i].__tvSuspended) { hlsList[i].__tvSuspended = false; hlsList[i].startLoad(); } } catch (_) {}
|
||||||
}
|
}
|
||||||
@@ -408,7 +438,13 @@ object VideoSnifferHelper {
|
|||||||
for (var k = 0; k < fs.length; k++) { try { pauseIn(fs[k].contentDocument); } catch (e) {} }
|
for (var k = 0; k < fs.length; k++) { try { pauseIn(fs[k].contentDocument); } catch (e) {} }
|
||||||
}
|
}
|
||||||
try { pauseIn(document); } catch (e) {}
|
try { pauseIn(document); } catch (e) {}
|
||||||
try { window.postMessage({ __tvcmd: 'pause' }, '*'); } catch (e) {}
|
var cmd = { __tvcmd: 'pause' };
|
||||||
|
try { window.postMessage(cmd, '*'); } catch (e) {}
|
||||||
|
try {
|
||||||
|
for (var j = 0; j < window.frames.length; j++) {
|
||||||
|
try { window.frames[j].postMessage(cmd, '*'); } catch (e) {}
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
})();
|
})();
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package com.tv.browser
|
package com.tv.browser
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.webkit.WebSettings
|
import android.view.ViewGroup
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.tv.browser.databinding.ActivityVideoWebBinding
|
import com.tv.browser.databinding.ActivityVideoWebBinding
|
||||||
@@ -13,10 +12,12 @@ import com.tv.browser.databinding.ActivityVideoWebBinding
|
|||||||
*/
|
*/
|
||||||
class VideoWebActivity : AppCompatActivity() {
|
class VideoWebActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var binding: ActivityVideoWebBinding
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val binding = ActivityVideoWebBinding.inflate(layoutInflater)
|
binding = ActivityVideoWebBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
val url = intent.getStringExtra(EXTRA_VIDEO_URL) ?: ""
|
val url = intent.getStringExtra(EXTRA_VIDEO_URL) ?: ""
|
||||||
@@ -59,6 +60,44 @@ class VideoWebActivity : AppCompatActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (::binding.isInitialized) {
|
||||||
|
binding.webView.onResume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
if (::binding.isInitialized) {
|
||||||
|
try {
|
||||||
|
binding.webView.evaluateJavascript(VideoSnifferHelper.JS_PAUSE_ALL_MEDIA, null)
|
||||||
|
binding.webView.onPause()
|
||||||
|
} catch (_: Exception) { }
|
||||||
|
}
|
||||||
|
super.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
if (::binding.isInitialized) {
|
||||||
|
try {
|
||||||
|
binding.webView.evaluateJavascript(VideoSnifferHelper.JS_PAUSE_ALL_MEDIA, null)
|
||||||
|
binding.webView.onPause()
|
||||||
|
} catch (_: Exception) { }
|
||||||
|
}
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
if (::binding.isInitialized) {
|
||||||
|
try {
|
||||||
|
binding.webView.stopLoading()
|
||||||
|
(binding.webView.parent as? ViewGroup)?.removeView(binding.webView)
|
||||||
|
binding.webView.destroy()
|
||||||
|
} catch (_: Exception) { }
|
||||||
|
}
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
private fun escapeHtmlAttr(s: String): String {
|
private fun escapeHtmlAttr(s: String): String {
|
||||||
return s.replace("&", "&")
|
return s.replace("&", "&")
|
||||||
.replace("\"", """)
|
.replace("\"", """)
|
||||||
|
|||||||
Reference in New Issue
Block a user