如何通过深度链接重新启动本机应用程序

时间:2018-11-29 11:39:21

标签: android react-native react-native-android deep-linking react-native-navigation

我正在尝试在我的本机Android应用程序中实现深度链接。链接通过SMS发送,当单击链接时,它会打开应用程序,并基于URL使用android:launchMode="singleTop"导航到垂直屏幕。我面临的问题是单击链接时,打开了该应用程序的新实例,但我不希望这样做,所以我更改为    android:launchMode="singleTask"activity中我的AndroidManifest.xml,现在只有一个实例。    但是现在,当单击来自SMS的链接时,它将恢复现有页面,而我无法单击该URL。

我实现了“ 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);
    }       
  }

请提出建议。

谢谢 R

1 个答案:

答案 0 :(得分:1)

这是最适合我的解决方案。

启动模式,我将其设置为singleTask Manifest.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
          }

      }

希望有帮助。

让我知道您是否需要其他信息

谢谢  R