如何通过深度链接重新启动反应原生应用程序

Posted

技术标签:

【中文标题】如何通过深度链接重新启动反应原生应用程序【英文标题】:How to restart react native app through deep linking 【发布时间】:2018-11-29 11:39:21 【问题描述】:

我正在尝试在我的 react 本机 android 应用程序中实现深度链接。链接是通过短信发送的,当点击链接时,它会打开应用程序并根据我使用android:launchMode="singleTop" 导航到特定屏幕的 url。我面临的问题是单击链接时,打开了一个新的应用程序实例,我不希望这样,所以我改为 android:launchMode="singleTask" 到我的activity AndroidManifest.xml,现在只有一个实例。 但是现在当点击短信中的链接时,它会恢复现有页面,我无法点击网址。

我实现了“AppState”来了解屏幕何时恢复,但这也没有给我网址。

我希望能够实现的要么是

应用程序从头开始完全重新启动Splash activity,我知道我可以获取 URL 并根据 URL 从那里导航。 (android:launchMode="singleTop" 不会重启应用,而是打开一个新实例) 或者当用户单击 URL 链接时,即使它恢复现有屏幕,我也想获取 URL 并导航到特定屏幕。

清单

   <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.abcdabcdapp">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleTop"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        //This is what is required to open from the link
        <intent-filter android:label="ABCD App">
          <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="abcd"
            android:pathPrefix="/createpassword" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>
</manifest>

以短信形式发送的链接 - http://abcd/createpassword

初始屏幕 - 初始屏幕。

componentDidMount() 
        setTimeout(() => 
            this.whereShoulINavigateTo();
        , 2500);        
    

whereShoulINavigateTo = async () => 
    if (Platform.OS === 'android') 
        Linking.getInitialURL().then( async (url) => 
          //this.navigate(url);
          if(url === 'http://abcd/createpassword')
           
            this.props.navigation.navigate('CreatePasswordScreen');
          else
            //do something
          
        );
       else 
          alert('ios url -' + url );
          //Linking.addEventListener('url', this.handleOpenURL);
           

以上设置适用于 android:launchMode="singleTop",但唯一的问题是我不想要应用的新实例。

所以我尝试了以下更改

清单

android:launchMode="singleTask"

这样只有一个实例,当点击 URL 时,应用程序会恢复。

所以我将 AppState 添加到恢复的页面并尝试获取 URL 但没有用。

  componentDidMount()
    //this.whereShoulINavigateTo();       
    AppState.addEventListener('change', this._handleAppStateChange);
  

  componentWillUnmount() 
    AppState.removeEventListener('change', this._handleAppStateChange);
  

  _handleAppStateChange = (nextAppState) => 
    if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') 
      console.log('App has come to the foreground!')
      this.whereShoulINavigateTo();   
    
    this.setState(appState: nextAppState);
  

  whereShoulINavigateTo = async () => 
    if (Platform.OS === 'android') 
        Linking.getInitialURL().then( async (url) => 
          alert('url - ' + url)
          if(url === 'http://abcd/createpassword')
           
            this.props.navigation.navigate('CreatePasswordScreen');
          
        );
       else 
          alert('ios url -' + url );
          //Linking.addEventListener('url', this.handleOpenURL);
           
  

请提出建议。

谢谢 回复

【问题讨论】:

你找到解决办法了吗? 你好@Simon 我在这里添加答案。让我知道这是否有帮助。我现在开始工作了,如果您有任何问题,请告诉我 感谢您的帮助。可悲的是,我们不再需要深度链接功能。但我真的很感谢你的帮助。 不用担心@Simon 【参考方案1】:

这是适合我的解决方案。

启动模式我已经设置为singleTask 清单.xml

       <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
            android:windowSoftInputMode="adjustResize">

在我的应用程序中打开的初始屏幕是启动屏幕。 假设您收到了短信并且您的应用已关闭,我们将重新打开该应用,因此它始终会在我的案例初始屏幕中打开初始屏幕。

这是我的初始屏幕代码。

    componentDidMount() 
        setTimeout(() => 
            this.whereShoulINavigateTo();
        , 2500);        
    

    whereShoulINavigateTo = async () => 
        encryptString('abcd');
        decryptString('abcd');
        if (Platform.OS === 'android') 
            Linking.getInitialURL().then( async (url) =>                
                if(url === 'http://abcd/1234')
                 
                    //if the url is right do something
                else

                
            );
           else 
              alert('ios url -' + url );
              //Linking.addEventListener('url', this.handleOpenURL);
              //Not implemented for iOS yet
               
    

当应用程序打开并收到消息时,在其他屏幕上。您单击该链接,它会打开相同的屏幕。所以下面的逻辑是 在该屏幕上需要。

    componentDidMount()
        Linking.addEventListener('url', this.handleOpenURL);
        

      componentWillUnmount() 
        Linking.removeEventListener('url', this.handleOpenURL);
      

       handleOpenURL = async (event) =>  
        consoleLog('url - ' + event.url);      
          if(event.url === 'http://abcd/1234')
           
              //if the url is right do something
          

      

希望对你有帮助。

如果您需要任何进一步的信息,请告诉我

谢谢 回复

【讨论】:

谢谢你,在 IOS 链接上工作就像一个魅力,但在 Android 中,任何时候 url 调用重新启动应用程序,但是在将 android:launchMode="singleTask" 添加到 AndroidManifest.xml 之后就像 ios。跨度>

以上是关于如何通过深度链接重新启动反应原生应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何在反应原生 Firebase 动态链接中从收到的链接中提取参数?

在启动画面加载 iOS 之前反应原生黑屏

在反应原生中链接谷歌地图应用程序时如何呈现方向?

反应原生。 Firebase 消息在启动应用程序几分钟后停止工作

反应原生 |如何使用 Typescript 访问键盘的 endCoordinates 并重新组合

缺少领域构造函数反应原生ios但领域是链接的