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

Android部分设备打开URL报ActivityNotFoundException异常如何解决

根因分析
  • Android 11及以上版本引入了包可见性限制,如果应用没有在AndroidManifest.xml中声明查询浏览器应用的权限,resolveActivity接口会返回null,无法正确获取可用的浏览器包名,进而导致跳转失败。
  • 现有Custom Tabs代码存在逻辑缺陷:使用仅携带http://的Intent查询浏览器,部分设备上默认浏览器可能仅注册了https scheme的响应,会导致查询结果不准确,强制设置错误的包名后触发异常。
  • 部分设备确实存在用户主动禁用所有系统/第三方浏览器、或是企业MDM策略限制浏览器启动的场景,此时外部跳转逻辑必然无法找到对应的处理Activity。
修复方案

该方案完全兼容Android 5.0及以上系统版本,按照优先级做多层降级可覆盖绝大多数场景。

1. 适配包可见性要求

在AndroidManifest.xml中加入如下queries配置,适配Android 11+的包可见性规则,低版本系统会自动忽略该配置不影响运行:

<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="https" />
    </intent>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="http" />
    </intent>
</queries>

添加后resolveActivity才能在高版本系统上正确查询到可用的浏览器应用。

2. 优化跳转逻辑,增加多级降级

按照「Custom Tabs跳转 -> 原生Intent跳转 -> 应用内置WebView打开」的优先级做降级处理:

优化后的跳转示例代码:

public void openUrl(Uri uri) {
    // 先尝试Custom Tabs跳转
    try {
        CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
        builder.setShowTitle(true);
        CustomTabsIntent customTabsIntent = builder.build();
        // 直接查询能处理目标uri的应用,不要用固定http://查询
        ResolveInfo resolveInfo = getPackageManager().resolveActivity(customTabsIntent.intent, PackageManager.MATCH_DEFAULT_ONLY);
        if (resolveInfo != null && !TextUtils.isEmpty(resolveInfo.activityInfo.packageName)) {
            customTabsIntent.intent.setPackage(resolveInfo.activityInfo.packageName);
            customTabsIntent.launchUrl(this, uri);
            return;
        }
    } catch (ActivityNotFoundException e) {
        // 捕获异常,走下一级降级逻辑
    }

    // 尝试原生Intent跳转
    try {
        Intent browserIntent = new Intent(Intent.ACTION_VIEW, uri);
        if (browserIntent.resolveActivity(getPackageManager()) != null) {
            startActivity(browserIntent);
            return;
        }
    } catch (ActivityNotFoundException e) {
        // 捕获异常,走下一级降级逻辑
    }

    // 终极兜底:跳转内置WebView页面加载链接
    Intent webViewIntent = new Intent(this, MyInnerWebViewActivity.class);
    webViewIntent.putExtra("target_url", uri.toString());
    startActivity(webViewIntent);
}

3. 实现内置WebView兜底页

新建一个轻量的MyInnerWebViewActivity作为终极兜底方案,哪怕用户禁用了所有外部浏览器也能在应用内打开链接:

public class MyInnerWebViewActivity extends AppCompatActivity {
    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_inner_webview);
        webView = findViewById(R.id.webview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient());
        String targetUrl = getIntent().getStringExtra("target_url");
        if (!TextUtils.isEmpty(targetUrl)) {
            webView.loadUrl(targetUrl);
        }
    }

    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
            return;
        }
        super.onBackPressed();
    }
}

注:仅在企业MDM策略同时限制了应用内WebView访问的极端场景下该方案会失效,此时可增加弹窗提示用户当前设备无法打开链接即可。

内容的提问来源于stack exchange,提问作者Aykut Uludağ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 09:06:10