可能的解决方案
与此同时,我自己找到了一个解决方案,可能不那么"干净"。
在App.js中,我这样指定initialRouteName:
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import Home from './screens/Home';
import Form from './screens/Form';
import {Linking, Platform} from 'react-native';
import React from 'react';
function getRoute() {
let route = "";
Linking.getInitialURL().then(url => {
route = url;
})
if (route === 'playgroundapp://form') {
return 'Form';
} else {
return "Home"
}
}
const AppNavigator = createStackNavigator(
{
Home: { screen: Home },
Form: { screen: Form },
}, {
initialRouteName: getRoute()
});
export default createAppContainer(AppNavigator);
问题
我希望能够从我的iOS小部件深度链接到我的React Native应用程序
当应用程序在后台运行时,链接工作正常,它会导航到正确的页面。但当应用程序被杀死时,它只会打开应用程序,但不会再导航到正确的页面。
我遵循了本教程:https://medium.com/react-native-training/deep-linking-your-react-native-app-d87c39a1ad5e
对官方文件进行了一些调整:https://facebook.github.io/react-native/docs/linking
AppDelegate.m
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTLinkingManager.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
@end
App.js
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import Home from './screens/Home';
import Form from './screens/Form';
const AppNavigator = createStackNavigator({
Home: { screen: Home },
Form: { screen: Form },
});
export default createAppContainer(AppNavigator);
Home.js
import React, {Component} from 'react';
import {
Linking,
Platform,
Text,
View,
} from 'react-native';
import Form from './Form';
export default class Home extends Component {
componentDidMount() {
if (Platform.OS === 'android') {
Linking.getInitialURL().then(url => {
this.navigate(url);
});
} else {
Linking.addEventListener('url', this.handleOpenURL);
}
}
componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL);
}
handleOpenURL = event => {
console.log(event.url)
this.navigate(event.url);
};
navigate = url => {
const {navigate} = this.props.navigation;
const route = url.replace(/.*?:///g, '');
const routeName = route.split('/')[0];
if (routeName === 'form') {
navigate('Form');
}
};
}
render() {
return (
<View style={styles.container}>
<Text style={styles.h1}>Playground</Text>
</View>
);
}
}
因此,我从我的小部件链接到应用程序,如下所示:extensionContext?.open(URL(string: "playgroundapp://form")! , completionHandler: nil)
当应用程序不在后台运行时,为什么它不起作用?我发现了一些类似的问题,但没有对我有效或过时的答案。
如果对于iOS,您已经按照以下处理了RCTLinkingManager
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<NSString *, id> *)options
{
BOOL handled = [[RNFirebaseLinks instance] application:application openURL:url options:options];
if(!handled)
{
handled = [RCTLinkingManager application:application openURL:url options:options];
}
return handled;
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
BOOL handled = [[RNFirebaseLinks instance] application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
if(!handled)
{
handled = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}
return handled;
}
您已经遵循了React Native链接中提到的过程。
_dynamicLinkListener; // variable defined to hold listeener instance
componentDidMount() {
this.setUpDynamicLink();
this.setUpDeepLink();
}
componentWillUnmount() {
this.cleanUpDynamicLink();
this.cleanUpDeepLink();
}
setUpDynamicLink = () => {
// will work when link is opening the app
Firebase.links()
.getInitialLink()
.then((url) => {
this.handleURL(url);
});
// listener will work when app is already opened or in background
this._dynamicLinkListener = Firebase.links().onLink((url) => {
this.handleURL(url);
});
}
setUpDeepLink = () => {
// will work when link is opening the app
Linking.getInitialURL().then(url => {
this.handleURL(url);
});
// listener will work when app is already opened or in background
Linking.addEventListener('url', this.handleURL);
}
cleanUpDynamicLink = () => {
this._dynamicLinkListener();
}
cleanUpDeepLink = () => {
Linking.removeEventListener('url', this.handleURL);
}
handleURL = (event) => {
let url = "";
if (!event) {
return "";
}
if (typeof event == 'string') {
url = event;
} else {
url = (event.url) ? event.url : "";
}
if (!url) {
return;
}
console.debug(url);
}
那你就可以走了。当应用程序处于foreground
、background
但不处于killed
状态时,我正在获取深度链接回调。
禁用应用程序的调试,并使用一些Alert
来显示url
,而不是使用控制台输出。启用调试时,Linking
出现一些问题。在此之后,我能够在警报中看到url。
上面提到的代码也有动态链接的Firebase
实现,你可以删除你不想要的
使用此软件包进行检查。
从"@react native firebase/dynamic links"导入dynamicLinks;
dynamicLinks().getInitialLink()
.then(link => {
// this method will call when app is closer or killed
console.log('dynamicLinksnew :', link);
});
dynamicLinks().onLink(async (link) => {
// this method call when app is in background or foreground
console.log('dynamicLinks :', link);
});
如果你使用react导航深度链接,请确保你的调试器关闭。你可以看到带有Alert组件的params替换
这样写配置。
const config = {
...config,
const onReceiveURL = ({ url }: { url: string }) => {
listener(url);
};
// Listen to incoming links from deep linking
Linking.addEventListener('url', onReceiveURL);
return () => {
// Clean up the event listeners
Linking.removeEventListener('url', onReceiveURL);
};
}