@@ -11,6 +11,7 @@ import android.graphics.Bitmap
1111import android.graphics.Rect
1212import android.net.Uri
1313import android.view.ViewTreeObserver
14+ import android.view.WindowManager
1415import android.webkit.JavascriptInterface
1516import android.webkit.JsResult
1617import android.webkit.PermissionRequest
@@ -423,8 +424,13 @@ internal class StripeConnectWebView private constructor(
423424 }
424425 }
425426
426- // Hook into the Activity lifecycle
427427 val activity = (view.findActivity() as ? ComponentActivity )
428+ if (activity == null || activity.isFinishing || activity.isDestroyed) {
429+ result.cancel()
430+ return true
431+ }
432+
433+ // Hook into the Activity lifecycle
428434 val activityLifecycleObserver =
429435 object : DefaultLifecycleObserver {
430436 override fun onDestroy (owner : LifecycleOwner ) {
@@ -433,7 +439,7 @@ internal class StripeConnectWebView private constructor(
433439 returnResult()
434440 }
435441 }
436- activity? .lifecycle? .addObserver(activityLifecycleObserver)
442+ activity.lifecycle.addObserver(activityLifecycleObserver)
437443
438444 val okText = alert.buttons?.ok
439445 ? : view.context.getString(android.R .string.ok)
@@ -444,30 +450,36 @@ internal class StripeConnectWebView private constructor(
444450 // Use the two-arg Builder to enforce an AppCompat theme. On some devices/OEM WebView
445451 // implementations, view.context may not carry AppCompat theme attributes, which causes
446452 // AppCompatDelegateImpl.createSubDecor to throw an IllegalStateException.
447- AlertDialog .Builder (view.context, androidx.appcompat.R .style.Theme_AppCompat_Light_Dialog_Alert )
448- .setCancelable(true )
449- .setOnCancelListener {
450- didConfirm = false
451- }
452- .setOnDismissListener {
453- // Invoked on dialog dismissals but not configuration changes.
454- returnResult()
455- // Clean up the observer.
456- activity?.lifecycle?.removeObserver(activityLifecycleObserver)
457- }
458- .setMessage(alert.message)
459- .setPositiveButton(okText) { _, _ ->
460- didConfirm = true
461- }
462- .apply {
463- alert.title?.let { setTitle(it) }
464- cancelText?.let {
465- setNegativeButton(it) { _, _ ->
466- didConfirm = false
453+ try {
454+ AlertDialog .Builder (view.context, androidx.appcompat.R .style.Theme_AppCompat_Light_Dialog_Alert )
455+ .setCancelable(true )
456+ .setOnCancelListener {
457+ didConfirm = false
458+ }
459+ .setOnDismissListener {
460+ // Invoked on dialog dismissals but not configuration changes.
461+ returnResult()
462+ // Clean up the observer.
463+ activity.lifecycle.removeObserver(activityLifecycleObserver)
464+ }
465+ .setMessage(alert.message)
466+ .setPositiveButton(okText) { _, _ ->
467+ didConfirm = true
468+ }
469+ .apply {
470+ alert.title?.let { setTitle(it) }
471+ cancelText?.let {
472+ setNegativeButton(it) { _, _ ->
473+ didConfirm = false
474+ }
467475 }
468476 }
469- }
470- .show()
477+ .show()
478+ } catch (e: WindowManager .BadTokenException ) {
479+ logger.error(" ($loggerTag ) Error showing alert dialog" , e)
480+ activity.lifecycle.removeObserver(activityLifecycleObserver)
481+ result.cancel()
482+ }
471483 return true
472484 }
473485
0 commit comments