WebView показывает пустой экран, когда возвращается из приложения на фонеAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 WebView показывает пустой экран, когда возвращается из приложения на фоне

Сообщение Anonymous »

Недавно мне было поручено создать приложение WebView на работе. Все работает отлично, кроме одной вещи. Когда он постукивает по нему, он исчезает. Элементы, стоящие за ним, кликабельны, поэтому пользователь рискует что -то нажать на что -то и отступать от экрана, в котором он был.@AndroidEntryPoint
class WebViewFragment : Fragment() {

private var _binding: FragmentWebViewBinding? = null
private val binding get() = _binding!!

private val viewModel: WebViewFragmentViewModel by viewModels()
private var pendingGpsHandler: String? = null

private var shouldEmulateOnRestore = false

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentWebViewBinding.inflate(inflater, container, false)
handleDeviceBackPress()
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

shouldEmulateOnRestore = savedInstanceState != null

setupUI(savedInstanceState == null)

if (savedInstanceState != null) {
binding.webView.restoreState(savedInstanceState)
}

observeForAction()
requestNotificationsPermission()
}

override fun onPause() {
binding.webView.onPause()
viewModel.persistCookies()
super.onPause()
}

override fun onResume() {
super.onResume()
binding.webView.onResume()
binding.webView.resumeTimers()

if (viewModel.isCustomTabVisible) {
viewModel.isCustomTabVisible = false
viewModel.abortPayment()
}
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
binding.webView.saveState(outState)
}

@SuppressLint("JavascriptInterface")
private fun setupUI(shouldLoad: Boolean) {
val imageRes = if (viewModel.isEnglishPreSet()) R.drawable.ic_gregorys_english else R.drawable.ic_gregorys

binding.timeoutView.logoImageView.setImageResource(imageRes)
binding.timeoutView.timeoutTitleTextView.text = viewModel.getTimeoutString()

viewModel.enableCookies(binding.webView)

binding.webView.configureSettings()

binding.webView.webViewClient = createRobustWebViewClient()

binding.webView.addJavascriptInterface(
WebAppInterface { command, commandPayload ->
viewModel.processWebviewCommand(
command = command,
commandPayload = commandPayload
)
},
"AppWebInterface"
)

if (shouldLoad) binding.webView.loadUrl(viewModel.buildWebviewUrl())
}

private fun createRobustWebViewClient(): WebViewClient = object : WebViewClient() {

override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
viewModel.resetTimeOutCounter()
// if (restoreJustHappened) view?.emulateTap()
}

override fun onPageCommitVisible(view: WebView, url: String) {
super.onPageCommitVisible(view, url)
if (shouldEmulateOnRestore) {
// view.emulateTap()
shouldEmulateOnRestore = false
}
}

override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
Log.d("ErrorDebugging", "error: $error")

if (!request.isForMainFrame) {
super.onReceivedError(view, request, error)
return
}

when (error.errorCode) {
ERROR_HOST_LOOKUP, ERROR_TIMEOUT -> viewModel.showTimeOutImmediately()
ERROR_CONNECT, ERROR_UNKNOWN -> viewModel.increaseTimeoutCounter()
else -> viewModel.resetTimeOutCounter()
}

super.onReceivedError(view, request, error)
}

}

// ...

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
< /code>
@SuppressLint("SetJavaScriptEnabled")
fun WebView.configureSettings(
lowEndDevice: Boolean = context.packageManager
.hasSystemFeature(PackageManager.FEATURE_RAM_LOW) ||
(context.getSystemService(ActivityManager::class.java)
?.isLowRamDevice == true)
) {
setWebContentsDebuggingEnabled(true)

// ───────────── WebSettings ───────────────────────────────────────────
settings.apply {
javaScriptEnabled = true // run site JavaScript
domStorageEnabled = true // enable localStorage / sessionStorage

databaseEnabled = true // enable Web SQL / IndexedDB
javaScriptCanOpenWindowsAutomatically = true // allow window.open()

mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW// allow http inside https (payments)

allowContentAccess = true // content:// URIs
allowFileAccess = true // file:// URIs
setSupportMultipleWindows(false) // no new WebViews for pop-ups
mediaPlaybackRequiresUserGesture = false // autoplay videos
safeBrowsingEnabled = true // Google Safe-Browsing

useWideViewPort = true // respect
loadWithOverviewMode = true // zoom-out to fit width
builtInZoomControls = false // pinch-zoom widgets off
displayZoomControls = false // hide tiny +/- buttons
textZoom = 100 // ignore sys. font scale

cacheMode = WebSettings.LOAD_DEFAULT
setSupportZoom(false) // legacy zoom API off

// ---------- Legacy AppCache (API < 28) --------------------------
if (Build.VERSION.SDK_INT < 28) runCatching {
// use reflection so we can still compile with SDK 35
val enable = WebSettings::class.java.getMethod(
"setAppCacheEnabled",
Boolean::class.javaPrimitiveType
)

enable.invoke(this, true)

val path = WebSettings::class.java.getMethod(
"setAppCachePath", String::class.java)
path.invoke(this, context.cacheDir.absolutePath)
}.onFailure { Log.w("WebViewSettings", "AppCache not available", it) }

// offscreenPreRaster = !lowEndDevice // pre-raster on capable hw

// @Suppress("DEPRECATION")
// setRenderPriority(WebSettings.RenderPriority.HIGH) // smoother scroll (pre-KitKat)
}

// ───────────── Rendering layer ───────────────────────────────────────
// if (lowEndDevice)
// setLayerType(View.LAYER_TYPE_SOFTWARE, null) // CPU render (avoids GPU crashes)
// else
// setLayerType(View.LAYER_TYPE_HARDWARE, null) // GPU render for smoothness

// ───────────── Appearance ────────────────────────────────────────────
setBackgroundColor(Color.WHITE) // keep WebView background invisible
}

fun WebView.emulateTap() {
post {
val x = width - 1f
val y = 1f
val downTime = System.currentTimeMillis()
val eventTime = System.currentTimeMillis()

val motionEventDown = android.view.MotionEvent.obtain(
downTime,
eventTime,
android.view.MotionEvent.ACTION_DOWN,
x, y, 0
)
val motionEventUp = android.view.MotionEvent.obtain(
downTime,
eventTime + 50,
android.view.MotionEvent.ACTION_UP,
x, y, 0
)

dispatchTouchEvent(motionEventDown)
dispatchTouchEvent(motionEventUp)

motionEventDown.recycle()
motionEventUp.recycle()

requestFocus(View.FOCUS_DOWN)
dispatchWindowFocusChanged(true)
invalidate()
}
}


Подробнее здесь: https://stackoverflow.com/questions/796 ... he-backgro
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»