应用程序被杀死时,React Native深层链接不起作用

时间:2019-11-19 10:27:58

标签: ios react-native deep-linking

可能的解决方案

与此同时,我自己也找到了解决方案,可能不是那么“干净”。

在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)

当应用程序不在后台运行时,为什么它不起作用?我发现了一些类似的问题,但没有对我有用或过时的答案。

3 个答案:

答案 0 :(得分:1)

如果对于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 linking中所述的步骤进行操作。

_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);
    }

那你很好。当应用程序处于foregroundbackground而不处于killed状态时,我正在获取深层链接回调。

为应用程序禁用调试,并使用一些Alert来显示url而不是使用控制台输出。启用调试后,Linking出现问题。之后,我可以在警报中看到网址。

上面提到的代码还具有用于动态链接的Firebase实现,您可以删除不需要的代码。

答案 1 :(得分:0)

请检查此软件包。

从'@ 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);
     
    });

答案 2 :(得分:0)

如果您使用 react-navigation 深层链接,请确保您的调试器关闭。你可以看到带有警报组件替换的参数