Deep linking not working when app is in background state React native
Asked Answered
G

4

12

i am creating e-commerce app based react native.here i need open single product page from url shared.actually it will work when app is in killed state, but incase of app is in background/inactive state it won't work. the sharing url gets null when opening on background/inactive state.I have attached my code.

// following code working for app killing state

componentWillMount() {

    if (Platform.OS === 'android') {
      console.log("Testing");debugger

      //Constants.OneTimeFlag == false;
          Linking.getInitialURL().then(url => {
            console.log(url);
            var str = url
            var name = str.split('/')[4]
            Constants.isLinking = true;
           this.setState({ shop_Id: name})


           if (str)
           {
            this.setState({ isFromHomeLinking:'FROM_LINK' })
            this.props.navigation.navigate('SingleProductScreen', { ListViewClickItemHolder: [this.state.shop_Id,1,this.state.isFromHomeLinking] });

           }


          });

    }

    else {
        Linking.addEventListener('url', this.handleNavigation);
      }

  }

Not working code following..



componentDidMount() {
    AppState.addEventListener('change', this._handleAppStateChange);
}

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

this.state.appState declared in constructor(props)

_handleAppStateChange = (nextAppState) => {
    if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
     console.log('App has come to the foreground!');debugger
 if (Platform.OS === 'android') {
          console.log("Testing");debugger

          //Constants.OneTimeFlag == false;
              Linking.getInitialURL().then(url => {
                console.log(url);
                var str = url
                var name = str.split('/')[4]
                Constants.isLinking = true;
               this.setState({ shop_Id: name})


               if (str)
               {
                this.setState({ isFromHomeLinking:'FROM_LINK' })
                this.props.navigation.navigate('SingleProductScreen', { ListViewClickItemHolder: [this.state.shop_Id,1,this.state.isFromHomeLinking] });

               }


              });

        }

        else {
            Linking.addEventListener('url', this.handleNavigation);
          }
    }
    }

when i open external link from whatsapp and app in background state Linking.getInitialURL() received as null ..

Following i have in manifest file

<activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
 <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="demo1.zgroo.com" />
</intent-filter>
      </activity>

following is my sample URL..

http://demo1.zgroo.com/xxxx

Kindly let me know any solutions..

thanks in advance..

Gorge answered 12/11, 2018 at 5:10 Comment(4)
Have you added deeplink code in manifest?Subcortex
with out deeplink code in manifest .. app closing state not works right..let me edit manifest code also waitGorge
Deep linking not working when app is not in background React native iOS only. it only show first screen.but if app is in background then particular screen will open. can you please help meTragedian
Please check the below link for a simple solution; #62694260Riddell
G
10

You need to register Linking listener for this case.

componentDidMount() {
  Linking.addEventListener('url', this._handleOpenURL);
},
componentWillUnmount() {
  Linking.removeEventListener('url', this._handleOpenURL);
},
_handleOpenURL(event) {
  console.log(event.url);
}

For more https://facebook.github.io/react-native/docs/linking

Gardell answered 12/11, 2018 at 12:5 Comment(4)
As far as I can tell, this only works when the app is in the foreground. Should this be working when the app is in the background? Because it's not, for me anywayOutstand
Use Linking.getInitialURL() at initial screen.Gardell
Linking.getInitialURL() always returns the first link that launched the app, not the latestOutstand
Please check the below link for a simple solution; #62694260Riddell
O
9

Here's a version of Anurag's answer using hooks:

export function useDeepLinkURL() {
  const [linkedURL, setLinkedURL] = useState<string | null>(null);

  // 1. If the app is not already open, it is opened and the url is passed in as the initialURL
  // You can handle these events with Linking.getInitialURL(url) -- it returns a Promise that
  // resolves to the url, if there is one.
  useEffect(() => {
    const getUrlAsync = async () => {
      // Get the deep link used to open the app
      const initialUrl = await Linking.getInitialURL();
      setLinkedURL(decodeURI(initialUrl));
    };

    getUrlAsync();
  }, []);

  // 2. If the app is already open, the app is foregrounded and a Linking event is fired
  // You can handle these events with Linking.addEventListener(url, callback)
  useEffect(() => {
    const callback = ({url}: {url: string}) => setLinkedURL(decodeURI(url));
    Linking.addEventListener('url', callback);
    return () => {
      Linking.removeEventListener('url', callback);
    };
  }, []);

  const resetURL = () => setLinkedURL(null);

  return {linkedURL, resetURL};
}

You can then use it with:

const {linkedURL, resetURL} = useDeepLinkURL();

useEffect(() => {
    // ... handle deep link
    resetURL();
}, [linkedURL, resetURL])

I added the function resetURL because if a user shares the same file twice with the app, you would want to load it twice. However, because the deep link would end up being the same, so the useEffect wouldn't be triggered again. You can cause it to be triggered again by setting the linkedURL to null, so the next time a file is shared, you can be sure that it will cause the useEffect to be run.

Also, I used decodeURI to decode the passed in URL because if you use a library like react-native-fs to load the file from the specified path, it won't be able to handle files with spaces in their names unless you use decodeURI.

Oreopithecus answered 15/4, 2020 at 1:26 Comment(1)
this is my stack. welcomescreen -> homescreen -> profilescreen - when app is not in background and try to open home screen but it alway open welcomescreen. - when app in background then it will redirect to homescreen. get value from Linking.getInitialURL(); is myapp://home but it will not redirect to homescreen.Tragedian
A
2

Remove listener from componentwillunmount. No need to write any code in componentwillunmount because the addListener of linking will always listen, then only if you coming from background (by clicking new deeplink) to active state will trigger.

Acquaintance answered 27/8, 2020 at 6:40 Comment(0)
P
0

dynamicLinks().onLink((item) => {

// Extract link data from 'item' const linkData = item.link;

// Handle navigation based on linkData // })

Pitchstone answered 10/1 at 6:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.