React-native-firebase: Can't seem to know when app was opened with dynamic link at first try

Created on 11 Feb 2018  路  15Comments  路  Source: invertase/react-native-firebase

Issue

Implemented dynamic links correctly, have it working with emailVerification and am able to open my Android app with a dynamic link, but within my app I can't seem to know if it was open with dynamic link or not. Am following this documentation: https://rnfirebase.io/docs/v3.2.x/links/reference/links

Added link listener to my component:

import * as React from "react";
import { Text } from "react-native";
import firebase from "react-native-firebase";

class VerifyEmailPage extends React.Component {
  componentDidMount() {
    this.unsubscribe = firebase.links().onLink(url => {
      console.warn(url);
    });
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  render() {
    return <Text style={{ color: "white" }}>Please Verify your email</Text>;
  }
}

export default VerifyEmailPage;

But when I enter app through dynamic link console.warn(url); is not triggered. Did I understand usage of onLink correctly? Also, at the moment app is just sent to background not exited completely so I don't think I need to use getInitialLink?

Environment

  1. Application Target Platform: Android
  1. Development Operating System: macOS High Siera
  1. Build Tools: Android Studio 3.0
  1. React Native version: 0.52.2
  1. RNFirebase Version: 3.2.4
  1. Firebase Module: Dynamic Links
Bug Android Links

Most helpful comment

Alright guys, I was able to fix this by performing following steps:

1) add android:launchMode="singleTask" to .MainActivity
2) Remove react-native-firebase link handling and replace with react-native one, without using AppState, i.e.

  componentDidMount() {
    Linking.getInitialURL().then(url => console.warn(url));
    Linking.addEventListener("url", url => console.warn(url));
  }

  componentWillUnmount() {
    Linking.removeEventListener("url", url => console.warn(url));
  }

This did the trick for me

All 15 comments

Update on the issue:
It works, but not as expected, I have to move app to background 2 times

1) Sign up
2) Send firebase emailVerification email with deeplink params
3) Move app back to background (clicking that circle button on android)
4) Open email
5) Click on the link and choose to open with the app
6) Getting into app, but onLink is not triggered

However if I move the app to background again, open email and click the link second time, it does work.

I will perform a different test with setState to show url link and build it to my device, just in case to make sure this is not emulator related and will update this issue latter today.

Looks like same issue occurs on device with release build

This is interesting. I hadn't really noticed it before, but the app we're building behaves the exact same way. I believe it's an Android bug, as the iOS version does trigger onLink if it receives a dynamic link during the first time it runs.

If it helps anyone I was able to find temporary work around using Linking: https://facebook.github.io/react-native/docs/linking.html

And AppState: https://facebook.github.io/react-native/docs/appstate.html

However would prefer default onLink to keep implementation clearer.

Hi @IljaDaderko,
In order to handle it you also have to use getInitialLink (try to invoke it before onLink).
The reason is that although the app is in the background, it could be destroyed, therefore sometimes the app will be invoked by an intent, and sometimes it will be as if the app is getting started again.

@omer88 will give both approaches a shot latter today, good call.

@omer88 so I tried this, still no luck it only opens it at second attempt, interesting thing I noticed is that I have 2 same running apps after clicking on that link, almost as if it opens duplicate or something? @pheromonez do you see same thing happening?

This is my updated code, executes correctly on every app state change, calls get link, but it has very inconsistent return in terms of url

import * as React from "react";
import { Text, AppState } from "react-native";
import firebase from "react-native-firebase";

class VerifyEmailPage extends React.Component<{}, State> {
  state = {
    appState: AppState.currentState,
    url: "no url"
  };

  componentDidMount() {
    AppState.addEventListener("change", this.onAppStateChange);
  }

  onAppStateChange = async (nextAppState) => {
    console.warn(nextAppState);
    if (this.state.appState.match(/inactive|background/) && nextAppState === "active") {
      const url = await firebase.links().getInitialLink();
      if (url) {
        this.setState({ url });
      } else {
        this.setState({ url: "Executed getInitialLink, but no url received" });
      }
    }
    this.setState({ appState: nextAppState });
  };

  render() {
    return (
      <Text style={{ color: "white" }}>{`App State: ${this.state.appState} URL: ${
        this.state.url
      }`}</Text>
    );
  }
}

export default VerifyEmailPage;

@IljaDaderko Try setting your MainActivity launchmode to 'singleTop' in the AndroidManifest.xml

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

This will stop it from opening multiple instances of the app

@chrisbianca tried it just now singleTop still opens new instance, there are singeTask and singleInstance options that prevent this, but using them results in no new link received ever.

After playing around with this find, I think its definitely related 2 instances somehow, I think it opens old activity and on second time it opens new one where new link is actually received.

But limiting it to one instance doesn't seem to pass the url at all, not only with react-native-firebase, but also using https://facebook.github.io/react-native/docs/linking.html

Doesn't seem like this is issue with your library in particular but rather react and android? If it helps anyone this was tested on Nexus 5, API 26, with play store

@IljaDaderko, Why are you checking the app state?
Please try just to call getInitialLink on componentDidMount.

@omer88 yeh true, I changed my original example to this

state = {
    url: "No Url Set Yet"
  };

  componentDidMount() {
    links()
      .getInitialLink()
      .then(url => {
        if (url) this.setState({ url });
      });
    this.unsubscribe = links().onLink(url => {
      this.setState({ url });
    });
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

But this doesn't do much, reason for me using AppState is to basically force the check even if page is not mounting i.e comes from background. I still have to click link in email twice to get it to update.

Alright guys, I was able to fix this by performing following steps:

1) add android:launchMode="singleTask" to .MainActivity
2) Remove react-native-firebase link handling and replace with react-native one, without using AppState, i.e.

  componentDidMount() {
    Linking.getInitialURL().then(url => console.warn(url));
    Linking.addEventListener("url", url => console.warn(url));
  }

  componentWillUnmount() {
    Linking.removeEventListener("url", url => console.warn(url));
  }

This did the trick for me

Should this issue be closed? It was mainly related to setting android:launchMode="singleTask" otherwise I think you don't even need to use Linking, rn-firebase listeners should work.

@IljaDaderko Probably should be :) will close now

Was this page helpful?
0 / 5 - 0 ratings

Related issues

joecaraccio picture joecaraccio  路  3Comments

ODelibalta picture ODelibalta  路  3Comments

dgruseck picture dgruseck  路  3Comments

n-scope picture n-scope  路  3Comments

Draccan picture Draccan  路  3Comments