首页 > Java > java教程 > 正文

Android WebView 应用实现深度链接:拦截外部 URL 并内部打开

花韻仙語
发布: 2025-12-03 17:02:44
原创
442人浏览过

Android WebView 应用实现深度链接:拦截外部 URL 并内部打开

本教程详细介绍了如何在基于 webview 的 android 应用中实现深度链接,使其能够拦截并处理特定 url,从而在应用内部而不是外部浏览器中打开这些链接。通过配置 `androidmanifest.xml` 中的 `intent-filter`,并学习如何在 activity 中获取和解析传入的 url 数据,开发者可以为用户提供更流畅的应用内体验,确保从分享链接或其他应用启动时,内容直接在您的应用中呈现。

深度链接基础与应用场景

在 Android 应用开发中,深度链接(Deep Linking)允许用户直接跳转到应用内的特定内容,而不是仅仅打开应用的主界面。对于包含 WebView 的应用而言,一个常见的需求是当用户点击一个指向应用所加载网页的 URL 时,希望该链接能在应用内部的 WebView 中打开,而非启动外部浏览器。这不仅提升了用户体验,也保持了应用的上下文一致性。

当通过 WhatsApp 或其他社交媒体分享包含应用相关域名的 URL 时,如果未正确配置深度链接,点击该 URL 会默认在设备的默认浏览器中打开。要解决此问题,核心在于告知 Android 操作系统您的应用能够处理特定类型的 URL。

配置 AndroidManifest.xml 实现深度链接

实现深度链接的关键在于在应用的 AndroidManifest.xml 文件中为相应的 Activity 添加一个 intent-filter。这个过滤器声明了您的应用可以响应特定的隐式 Intent,特别是那些用于查看(ACTION_VIEW)特定 URI 的 Intent。

假设您的应用旨在处理 https://tcg-wallet.ga 域名的所有链接,您需要将以下 intent-filter 添加到负责处理这些链接的 Activity(通常是启动 Activity 或一个专门的 DeepLinkActivity)中:

<activity android:name=".YourTargetActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="tcg-wallet.ga"
            android:scheme="https" />
    </intent-filter>
    <!-- 如果此 Activity 也是主启动器,保留以下过滤器 -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
登录后复制

intent-filter 各部分详解:

  • <action android:name="android.intent.action.VIEW" />: 声明此 Activity 能够执行“查看”操作。当用户点击一个 URL 时,Android 系统会发出一个 ACTION_VIEW Intent。
  • <category android:name="android.intent.category.DEFAULT" />: 表示此 Activity 是一个默认处理程序,可以被隐式 Intent 调用。这使得它成为系统在没有明确指定组件时,考虑作为 Intent 目标的一个选项。
  • <category android:name="android.intent.category.BROWSABLE" />: 使得 Activity 能够被网络浏览器通过链接启动。没有这个类别,即使 URL 匹配,浏览器也无法启动您的应用。
  • <data android:host="tcg-wallet.ga" android:scheme="https" />: 这是深度链接的核心配置。它指定了此 intent-filter 将响应的 URI 数据:
    • android:scheme="https": 表示应用能够处理使用 https 协议的链接。您也可以添加 http 以支持非加密链接。
    • android:host="tcg-wallet.ga": 指定应用将响应的域名。只有当 URL 的主机名与此完全匹配时,应用才会被考虑。

配置完成后,当用户点击一个形如 https://tcg-wallet.ga/home?search=MP21-EN056 的链接时,Android 系统将识别出您的应用能够处理此 URL,并会提示用户选择在您的应用中打开,或者如果您的应用是唯一的处理程序,则直接在应用中打开。

处理传入的深度链接数据

一旦您的应用通过深度链接被启动,您需要在接收该 Intent 的 Activity 中提取并处理 URL 数据。这通常在 Activity 的 onCreate() 方法中完成。

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.webkit.WebView;

public class YourTargetActivity extends AppCompatActivity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); // 假设您的布局包含一个WebView

        webView = findViewById(R.id.your_webview_id); // 替换为您的WebView ID
        // 配置 WebView 设置,例如启用JavaScript等
        webView.getSettings().setJavaScriptEnabled(true);

        // 检查是否有传入的 Intent 数据
        Intent intent = getIntent();
        if (intent != null && intent.getAction() != null && intent.getAction().equals(Intent.ACTION_VIEW)) {
            Uri data = intent.getData();
            if (data != null) {
                String fullUrl = data.toString();
                // 打印或处理接收到的完整 URL
                System.out.println("Received Deep Link URL: " + fullUrl);

                // 将 URL 加载到 WebView 中
                webView.loadUrl(fullUrl);

                // 您也可以解析 URL 的参数
                String scheme = data.getScheme(); // "https"
                String host = data.getHost();     // "tcg-wallet.ga"
                String path = data.getPath();     // "/home"
                String query = data.getQuery();   // "search=MP21-EN056&event=search"

                // 根据需要解析查询参数
                String searchValue = data.getQueryParameter("search");
                if (searchValue != null) {
                    System.out.println("Search Parameter: " + searchValue);
                    // 可以在 WebView 中执行 JavaScript 来处理这个参数
                    // webView.evaluateJavascript("javascript:handleSearchParam('" + searchValue + "');", null);
                }
            }
        } else {
            // 如果没有深度链接,加载默认 URL
            webView.loadUrl("https://tcg-wallet.ga");
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        // 如果 Activity 已经是运行状态,并且接收到新的深度链接 Intent,
        // 则需要在这里处理,否则 onCreate 不会被再次调用。
        setIntent(intent); // 更新当前 Activity 的 Intent
        // 重新执行 onCreate 中的 Intent 处理逻辑
        // 注意:这里需要根据实际情况决定是否重新加载整个页面或仅更新内容
        if (intent != null && intent.getAction() != null && intent.getAction().equals(Intent.ACTION_VIEW)) {
            Uri data = intent.getData();
            if (data != null) {
                String fullUrl = data.toString();
                System.out.println("Received New Deep Link URL: " + fullUrl);
                webView.loadUrl(fullUrl);
            }
        }
    }
}
登录后复制

在 onCreate 方法中,我们通过 getIntent() 获取启动 Activity 的 Intent。如果其 action 是 ACTION_VIEW 且包含数据,我们就可以通过 intent.getData() 获取到完整的 URI。然后,您可以将此 URI 直接加载到 WebView 中,或者解析其参数,根据业务逻辑进行进一步处理。如果您的 Activity 启动模式是 singleTop 或 singleTask,并且应用已经在运行,新的深度链接会通过 onNewIntent() 方法传递,因此也需要在此方法中处理。

课游记AI
课游记AI

AI原生学习产品

课游记AI 86
查看详情 课游记AI

WebView 与 JavaScript 交互(分享功能回顾)

原始问题中提到了从 WebView 内部通过 JavaScript 调用原生分享功能。这部分与深度链接的接收机制是独立的,但对于理解整个流程仍然有益。

JavaScript 代码(在网页中):

const shareData = {
    title: '搜索价格',
    text: '搜索卡片:"' + document.getElementById('search').value + '"',
    url: document.URL // 当前页面的 URL
};

const btn = document.getElementById('share-url');

if (typeof btn !== 'undefined') {
    btn.addEventListener('click', async () => {
        try {
            // 检查 AndroidShareHandler 接口是否存在,如果存在则调用原生分享
            if (typeof (window.AndroidShareHandler) != 'undefined') {
                window.AndroidShareHandler.shareSearch(JSON.stringify(shareData));
            } else {
                // 如果不存在,尝试使用 Web Share API
                alert('Shared Working');
                await navigator.share(shareData);
            }
        } catch (err) {
            console.error('分享错误:', err);
            alert('[错误]: 分享链接出错!');
        }
    });
}
登录后复制

Java 代码(在 Android 应用中):

为了让 JavaScript 能够调用原生代码,需要使用 addJavascriptInterface 方法将一个 Java 对象暴露给 WebView:

public class YourActivity extends AppCompatActivity {
    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.your_webview_id);
        webView.getSettings().setJavaScriptEnabled(true);
        // 将 Java 对象暴露给 JavaScript
        webView.addJavascriptInterface(new JavaScriptShareInterface(this), "AndroidShareHandler");

        // ... 其他 WebView 配置和加载 URL
    }

    // 用于 JavaScript 调用的接口
    public class JavaScriptShareInterface {
        Context app_context;

        JavaScriptShareInterface(Context c) {
            app_context = c;
        }

        @JavascriptInterface
        public void shareSearch(String javascript_data) {
            try {
                JSONObject search = new JSONObject(javascript_data);
                String title = search.getString("title");
                String text = search.getString("text");
                String url = search.getString("url");
                String content = title + "\n" + text + "\n\n" + url;

                Intent sendIntent = new Intent(Intent.ACTION_SEND);
                sendIntent.setType("text/plain");
                sendIntent.putExtra(Intent.EXTRA_TEXT, content);
                // 使用 createChooser 确保用户可以选择分享到哪个应用
                app_context.startActivity(Intent.createChooser(sendIntent, "分享链接到..."));

            } catch (Exception ex) {
                System.err.println("分享数据解析错误: " + ex.getMessage());
            }
        }
    }
}
登录后复制

这段代码实现了从 WebView 内部触发原生分享,分享的内容中包含了 URL。当用户在 WhatsApp 中点击这个分享出去的 URL 时,如果您的应用已经正确配置了深度链接,系统就会优先选择在您的应用中打开该链接。

注意事项与最佳实践

  1. 测试彻底性: 在不同 Android 版本和设备上测试深度链接的行为。有些旧设备或特定 ROM 可能对深度链接的处理方式略有不同。
  2. App Links (Android 6.0+): 对于 Android 6.0 (API level 23) 及更高版本,建议使用 Android App Links。App Links 提供了更强的验证机制,可以验证您的应用是特定 URL 的官方处理程序,从而绕过用户选择器,直接在您的应用中打开链接。这需要将 autoVerify="true" 添加到 intent-filter 中,并在您的网站上放置一个 assetlinks.json 文件进行验证。
  3. 用户体验:
    • 当通过深度链接启动应用时,确保应用能够快速加载并显示相关内容。
    • 如果深度链接指向的内容需要登录,请妥善处理登录流程,并在登录后将用户重定向到原始深度链接目标。
    • 处理无效或过时的深度链接,提供友好的错误提示或回退到应用主页。
  4. 唯一性: 确保您的 intent-filter 足够具体,以避免与其他应用发生冲突。如果多个应用声称可以处理同一个 URL,系统会显示一个选择器让用户选择。
  5. 数据解析: 仔细解析传入的 URI 数据,特别是查询参数,以确保 WebView 能够根据这些参数加载正确的内容或执行相应的操作。

总结

通过在 AndroidManifest.xml 中配置 intent-filter,并结合 Activity 中对 Intent 数据的解析,Android WebView 应用可以有效地实现深度链接功能。这使得应用能够无缝地拦截并处理特定 URL,从而在应用内部提供更一致、更流畅的用户体验。正确实现深度链接是提升应用用户参与度和可发现性的重要一步。

以上就是Android WebView 应用实现深度链接:拦截外部 URL 并内部打开的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号