Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ open class WebViewFragment : Fragment() {
*/
@SuppressLint("SetJavaScriptEnabled")
private fun createWebView(): WebView {
return WebView(context).apply {
return try {
WebView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
Expand All @@ -187,13 +188,37 @@ open class WebViewFragment : Fragment() {

override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
// Re-establish focus and key listeners when page finishes
// activity?.runOnUiThread {
// setupBackPressHandling()
// mainWebView.requestFocus()
// }
}
}

webChromeClient = object : WebChromeClient() {
// override fun onProgressChanged(view: WebView?, newProgress: Int) {
// super.onProgressChanged(view, newProgress)
// if (newProgress == 100) {
// val url = view?.url
// Log.d("WebViewFragment", "Page loaded 100%: $url")
// // Check if this is the problematic white screen
// if (url != null && url.contains("stripe.com")) {
// Log.d("WebViewFragment", "Stripe page detected, re-establishing focus")
// activity?.runOnUiThread {
// // Force focus back to our views
// mainWebView.requestFocus()
// webViewContainer.requestFocus()
// view?.requestFocus()
// }
// }
// }
// }

override fun onCreateWindow(
view: WebView?, dialog: Boolean, userGesture: Boolean, resultMsg: Message
): Boolean {
Log.d("WebViewFragment", "Creating new window")
val newWebView = createNewWebView()
webViews.add(newWebView)
webViewContainer.addView(newWebView)
Expand Down Expand Up @@ -227,8 +252,13 @@ open class WebViewFragment : Fragment() {
} else {
WebAppInterfaceWithoutScanCard(activity,this@WebViewFragment,this,bundleUrl)
}
addJavascriptInterface(webAppInterface, "AndroidInterface")
loadUrl(bundleUrl)
addJavascriptInterface(webAppInterface, "AndroidInterface")
loadUrl(bundleUrl)
}
} catch (e: Exception) {
Log.e("WebViewFragment", "Failed to create WebView", e)
// Re-throw the exception to maintain existing error handling behavior
throw e
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import io.hyperswitch.paymentsheet.PaymentSheet
*/
class WebViewUtils(private val activity: Activity) : SDKInterface {

init {
// Initialize WebView warm-up to prevent Resources$NotFoundException crashes
// This ensures WebViewFactory is initialized safely before any WebView instances are created
WebViewWarmUpHelper.warmUpWhenIdle(activity)
}

/**
* The WebViewFragment used for displaying payment sheets.
*
Expand Down Expand Up @@ -67,4 +73,4 @@ class WebViewUtils(private val activity: Activity) : SDKInterface {
transaction.attach(webFragment).commit()
return true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.hyperswitch.lite

import android.content.Context
import android.os.Handler
import android.os.Looper
import android.webkit.WebView
import java.util.concurrent.atomic.AtomicBoolean

object WebViewWarmUp {
private val done = AtomicBoolean(false)

fun isDone(): Boolean = done.get()

fun init(context: Context) {
if (done.get()) return

Looper.getMainLooper().queue.addIdleHandler {
var success = false
try {
val wv = WebView(context.applicationContext)
Handler(Looper.getMainLooper()).post {
runCatching { wv.destroy() }
}
success = true
} catch (e: Throwable) {
} finally {
if (success) done.set(true)
}
false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.hyperswitch.lite

import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.os.Handler
import android.os.Looper

object WebViewWarmUpHelper {
private val idleHandlerQueued = java.util.concurrent.atomic.AtomicBoolean(false)

fun warmUpWhenIdle(activity: Activity) {
if (WebViewWarmUp.isDone()) {
return
}

// Prevent multiple idle handlers from being queued
if (idleHandlerQueued.compareAndSet(false, true)) {
Looper.getMainLooper().queue.addIdleHandler {
WebViewWarmUp.init(activity.applicationContext)
false // Remove this IdleHandler after execution
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Activity
import android.os.Bundle
import io.hyperswitch.PaymentConfiguration
import io.hyperswitch.lite.WebViewUtils
import io.hyperswitch.lite.WebViewWarmUpHelper
import io.hyperswitch.paymentsheet.PaymentSheet
import io.hyperswitch.paymentsheet.PaymentSheetResult

Expand All @@ -29,6 +30,10 @@ open class DefaultPaymentSessionLauncherLite(
customParams
)
}

// Early WebView warm-up to prevent Resources$NotFoundException crashes
// This happens before WebView preloading, ensuring WebViewFactory is initialized safely
WebViewWarmUpHelper.warmUpWhenIdle(activity)
}

// Method to initialize the payment session
Expand Down