React Native 0.66 Android冷启动Deeplink getInitialURL返回null
问题根因
Android端冷启动(完全关闭状态)下RN层拿不到deeplink,是核心问题叠加导致的:
- 现有
MainActivity的初始化顺序错误:你在super.onCreate()执行前就调用了SplashScreen初始化、读取Intent,部分闪屏库版本会在这个阶段临时替换Activity的Intent引用,后续RN桥接层初始化时读取到的Intent已经丢失了deeplink携带的data字段。 - RN 0.66版本Android端Linking模块的初始化时机早于deeplink Intent挂载的时机,默认的ReactActivity实现没有主动把冷启动的deeplink数据透传给JS层,导致
getInitialURL()直接返回null。 - 额外代码问题:你贴的RN层事件监听代码中事件名写错了,正确的deeplink事件名是
url,不是https。
修复步骤
1. 调整MainActivity代码
先修正onCreate执行顺序,主动给RN层透传冷启动deeplink数据,同时补全onNewIntent逻辑避免前后台场景下的Intent丢失:
// 补充缺失的导包 import android.content.Intent; import android.net.Uri; import android.os.Bundle; import com.facebook.react.modules.core.DeviceEventManagerModule; // 如果你用的是其他闪屏库,替换成对应导包即可 import org.devio.rn.splashscreen.SplashScreen; @Override protected void onCreate(Bundle savedInstanceState) { // 必须先调用super.onCreate,保证RN基础桥接环境优先初始化 super.onCreate(savedInstanceState); // 再初始化闪屏 SplashScreen.show(this); Intent intent = getIntent(); Uri deeplinkData = intent.getData(); if (deeplinkData != null) { String deeplinkUrl = deeplinkData.toString(); // 等RN桥接初始化完成后主动同步初始URL getReactNativeHost().getReactInstanceManager().addReactInstanceEventListener(reactContext -> { // 主动下发url事件,补全冷启动场景下的事件触发 reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit("url", deeplinkUrl); // 重新绑定Intent,保证Linking.getInitialURL能正常读取 setIntent(intent); }); } } // 必须重写onNewIntent,避免后台/前台场景下Intent被覆盖 @Override public void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); }
2. 修正AndroidManifest配置
给MainActivity加上singleTask启动模式,避免deeplink触发时生成多Activity实例导致数据丢失:
<activity android:name=".MainActivity" android:launchMode="singleTask" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:label="@string/app_name" android:windowSoftInputMode="adjustResize"> <!-- 保留你原来的deeplink intent-filter配置即可 --> <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:host="my.site.com" android:pathPrefix="/my/path" android:scheme="https" /> </intent-filter> </activity>
注意:把原来写在无name属性<activity>标签下的intent-filter移到上面的MainActivity标签下,你当前贴的manifest里<activity>没有指定name属性,配置不会生效到实际承载RN页面的MainActivity上。
3. 修正RN层代码
修正事件名,把getInitialURL的调用放到App尽可能早的入口(比如入口文件的初始化阶段,不要等页面渲染完成后再调用,避免时机过晚):
import { Linking } from 'react-native'; // 正确的deeplink事件名是url,不是https const deeplinkHandler = (event) => { const url = event.url; // 写你的业务处理逻辑 console.log('收到deeplink:', url); }; // 尽可能早注册监听 Linking.addEventListener('url', deeplinkHandler); // 入口初始化阶段就调用getInitialURL Linking.getInitialURL().then(url => { if (url) { console.log('冷启动deeplink:', url); // 写冷启动场景下的deeplink业务处理逻辑 } });
验证注意事项
- 测试前必须完全杀掉App进程,不要通过Android Studio直接运行启动App,用你之前的adb命令触发deeplink启动,避免调试状态下的进程缓存干扰结果。
- 如果用了react-navigation、react-native-navigation这类路由库,这类库会默认接管deeplink处理,不要重复写多套监听逻辑,按照路由库官方文档配置deeplink即可。
- 如果用的是3.3.0以下版本的react-native-splash-screen,建议升级到最新版,旧版本存在冷启动替换Intent的已知bug。
内容的提问来源于stack exchange,提问作者shogitai
相关产品推荐
相关产品推荐

