You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo框架下Android平台检测用户关闭浏览器事件的实现方案(3DS信用卡验证场景)

跨平台检测浏览器关闭:用WebBrowser事件监听替代平台差异逻辑

我明白你的困扰——Expo的WebBrowser.openBrowserAsync在Android和iOS上的Promise行为确实不一致,导致你没法用同一套逻辑检测用户关闭浏览器的操作。好在Expo提供了浏览器事件监听的API,完美解决这个跨平台问题。

下面是具体的实现方案,直接修改你的现有代码即可:

首先,在组件内部定义一个引用用来存储监听函数(方便后续移除):

import { useRef, useEffect } from 'react';
import { WebBrowser, Subscription } from 'expo';

// 在你的组件内部
const browserCloseListenerRef = useRef<Subscription | null>(null);

然后修改你的信用卡注册流程代码,添加事件监听并处理清理:

client.service('credit-cards')
  .patch(creditCardRef.current._id, {
    registrationId: creditCardRef.current.registrationId,
    registrationData: registrationDataRef.current,
    registrationIpAddress: ipAddressRef.current,
    // @ts-expect-error Unable to set the type of the parsed query.
    registrationBrowserInfo: {
      ...parsedUrl.query,
      acceptHeader: headersRef.current.accept,
    },
    secureModeRedirectUrl: Linking.createURL('paybox-3ds', {
      queryParams: { creditCardId: creditCardRef.current._id },
    }),
  })
  .then(ResultHelpers.toOne)
  .then((result) => {
    // 注册浏览器关闭事件监听,跨平台生效
    browserCloseListenerRef.current = WebBrowser.addBrowserEventListener(
      'browserDidClose',
      () => {
        setLoading(false);
        // 触发后立即移除监听,避免重复执行
        if (browserCloseListenerRef.current) {
          browserCloseListenerRef.current.remove();
          browserCloseListenerRef.current = null;
        }
      }
    );

    return WebBrowser.openBrowserAsync(result.secureModeUrl, {
      showInRecents: true,
    });
  })
  .then((browserResult: WebBrowser.WebBrowserResult): void => {
    // 保留原iOS的cancel判断作为双重保障
    if (browserResult.type === 'cancel') {
      setLoading(false);
      // iOS触发cancel时也清理监听
      if (browserCloseListenerRef.current) {
        browserCloseListenerRef.current.remove();
        browserCloseListenerRef.current = null;
      }
    }
    // Android这里会返回type: 'opened',无需额外处理,等待事件监听触发
  })
  .catch((error) => {
    handleCreditCardRegistrationError(error);
    // 出错时也要清理监听
    if (browserCloseListenerRef.current) {
      browserCloseListenerRef.current.remove();
      browserCloseListenerRef.current = null;
    }
  });

// 组件卸载时强制清理监听,防止内存泄漏
useEffect(() => {
  return () => {
    if (browserCloseListenerRef.current) {
      browserCloseListenerRef.current.remove();
    }
  };
}, []);

关键说明:

  • browserDidClose事件:这个事件在Android和iOS上都会触发,不管用户是通过系统返回键、浏览器关闭按钮还是关闭标签页来关闭窗口,都能准确捕获到关闭行为。
  • 监听清理:必须在事件触发、操作完成、出错以及组件卸载时移除监听,否则会导致内存泄漏,甚至在后续操作中重复触发回调。
  • 兼容原有逻辑:保留iOS平台的cancel类型判断,是为了在极端情况下(比如事件监听未及时触发)提供双重保障,确保加载状态能被正确重置。

这个方案完全基于Expo官方API,不需要引入额外依赖,完美解决Android平台无法检测浏览器关闭的问题。

内容的提问来源于stack exchange,提问作者Soullivaneuh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 21:27:33