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

如何为ReactJS Ionic Android项目配置深度链接

问题描述

我有一个基础ReactJS项目,通过Ionic Capacitor转为Android项目,输出文件存于build目录,已生成可用APK。现在需要实现:移动端任意浏览器打开https://example.com/这类URL时,直接唤起已安装的我的应用。

目前已完成以下配置,但点击链接时仍会在浏览器中打开,仅在浏览器角落显示唤起图标:

  • 配置了AndroidManifest.xml中的intent-filter
  • 部署了assetlinks.json文件
  • 编写了React端的URL打开事件处理代码

已配置内容

1. 初始intent-filter配置

<intent-filter android:label="@string/title_activity_main">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https"
        android:host="m.clipdrop.io"
        android:pathPrefix="/" />
</intent-filter>
<intent-filter android:label="@string/title_activity_main">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="http"
        android:host="m.clipdrop.io"
        android:pathPrefix="/" />
</intent-filter>
<!-- Accepts URIs that begin with "clipdrop://login” -->
<intent-filter android:label="@string/title_activity_main">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="clipdrop"
        android:host="login" />
</intent-filter>

2. 点击链接示例

https://m.clipdrop.io/login?b=datahere

3. React端URL处理代码

import React, { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { App, URLOpenListenerEvent } from '@capacitor/app';

export default function AppUrlListener(){
    let history = useHistory();
    useEffect(() => {
      App.addListener('appUrlOpen', (event) => {
        var url = new URL(event.url);
        var benc = url.searchParams.get("b")?.replace("%3D", "=");
        if(benc){
          window.location.href = "/login?b=" + benc; 
        }
        // If no match, do nothing - let regular routing
        // logic take over
      });
    }, []);
  
    return null;
  };

4. 最终AndroidManifest.xml配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="io.clipdrop.clipdrop">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
            android:name="io.clipdrop.clipdrop.MainActivity"
            android:label="@string/title_activity_main"
            android:theme="@style/AppTheme.NoActionBarLaunch"
            android:launchMode="singleTask"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <!-- Accepts URIs that begin with "http(s)://m.clipdrop.io --&gt;
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="http" />
                <data android:scheme="https" />
                <data android:host="m.clipdrop.io" />
            </intent-filter>
        </activity>
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>
    </application>
    <!-- Permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.MICROPHONE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-feature android:name="android.hardware.camera" android:required="true" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-feature android:name="android.hardware.microphone"/>
    <uses-permission android:name="android.permission.AUDIO_CAPTURE" />
</manifest>

解决方案

1. 确保数字资产链接验证通过

  • 检查assetlinks.json内容:必须包含应用的包名io.clipdrop.clipdrop和正式签名的SHA-256指纹
  • 验证服务器配置:确保assetlinks.json能通过HTTPS访问,返回的Content-Type为application/json,且开启跨域访问
  • 使用官方验证工具确认链接有效性(需用正式签名APK测试,debug包无法通过验证)

2. 优化AndroidManifest.xml配置

  • 保持android:launchMode="singleTask"不变,确保应用从浏览器唤起时不会重复创建实例
  • 确认android:autoVerify="true"已添加到intent-filter中,这是实现直接唤起的关键

3. 调整React端URL处理逻辑

改用react-router的history.push替代window.location.href,更符合React路由机制:

import React, { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { App } from '@capacitor/app';

export default function AppUrlListener(){
    const history = useHistory();
    useEffect(() => {
        const listener = App.addListener('appUrlOpen', (event) => {
            const url = new URL(event.url);
            const benc = url.searchParams.get("b")?.replace("%3D", "=");
            if(benc){
                history.push(`/login?b=${benc}`);
            }
        });

        return () => {
            listener.remove();
        };
    }, [history]);

    return null;
};

4. 处理浏览器行为差异

  • 部分浏览器(如Chrome)首次打开链接时需用户手动点击唤起图标,后续会默认唤起
  • 可在网页中添加引导提示,引导用户点击唤起图标
  • 清除浏览器缓存或使用隐私模式测试,避免缓存影响

5. 测试注意事项

  • 必须使用正式签名的APK测试,debug签名包无法通过数字资产链接验证
  • 测试设备需为Android 6.0及以上版本,该版本才支持autoVerify功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 05:15:29