Nativescript-plugin-firebase: Opening dynamic links from background

Created on 26 Mar 2018  路  9Comments  路  Source: EddyVerbruggen/nativescript-plugin-firebase

Hey all,
I'm trying to implement a mechanism where dynamic link is sent to a user and it triggers some action (e.g. adding the user to specific group).
I'm able to implement it using the onDynamicLinkCallback, but this is triggered only when the app is launched using the the link (and not when it is on the background).

Will be happy if someone could help figure this out :)

Most helpful comment

@shabib3 I would have probably posted that here.

All 9 comments

I'm not sure what you mean.. can you perhaps explain in more detail, possibly with a screenrecording?

Hi @EddyVerbruggen - thanks for answering here. I'm trying to implement a mechanism where a user gets a dynamic link, and when he opens it the app uses the link to perform some action.
I'm currently testing on android only.

My code looks like this:

export class AppComponent {
  constructor() {
    firebase.init({
      onAuthStateChanged: (data) => { // optional but useful to immediately re-logon the user when he re-visits your app
        console.log(data.loggedIn ? "Logged in to firebase" : "Logged out from firebase");
        if (data.loggedIn) {
          console.log("user's email address: " + (data.user.email ? data.user.email : "N/A"));
        }
      },
      onDynamicLinkCallback: (result) => {
        alert("Dynamic Link: " + result); 
      }
    })
      .then(() => console.log(">>>>> Firebase initialized"))
      .catch(err => console.log(">>>>> Firebase init error: " + err));
  }
}

application.on(application.launchEvent, (args) => {
    if (args.android) {
        // For Android applications, args.android is an android.content.Intent class.
        console.log("Launched Android application with the following intent: " + args.android + ".");
    } else if (args.ios !== undefined) {
        // For iOS applications, args.ios is NSDictionary (launchOptions).
        console.log("Launched iOS application with options: " + args.ios);
    }
});

application.on(application.resumeEvent, (args) => {
  if (args.android) {
      // For Android applications, args.android is an android.content.Intent class.
      console.log("Launched Android application with the following intent: " + args.android + ".");
  } else if (args.ios !== undefined) {
      // For iOS applications, args.ios is NSDictionary (launchOptions).
      console.log("Launched iOS application with options: " + args.ios);
  }
});

When the app is just launched, the onDynamicLink callback is called (alert is shown).
When the app is already opened in the background (on resume is called and not launch), the onDynamicLink callback is not called (alert is not shown).

I have also tried to somehow extract this data from the args param on the application.on(application.resumeEvent...) callback but it seems not to have any useful data as well.

I have also encountered some similar issues on background notifications as well (on android as well, payload is sent on launch but not onResume), so I wonder whether there is some bigger background issue hiding.
Thanks

Thanks for the clarification!

Hi @EddyVerbruggen. Do you have any further thoughts/info on this at all?

We are struggling to understand how to catch the event of users tapping a notification when the app is in background. Is this onDynamicLinkCallback the right way to handle this?

Thanks.

I think this is very likely related to #692
I had to downgrade from NativeScript 4.0 to 3.4.2 because of this.
With NativeScript 3.4.2 it's working just fine for Android and iOS.

@EddyVerbruggen - any update about this?

@shabib3 I would have probably posted that here.

I would have probably posted that here.

So, no updates... I've continued to get this issue and no idea how to solve it.... :(((((

I had a similar issue where when receiving a dynamicLink I was trying to show a modal allowing the user to do something with the data. There were two problems:

  • The callback was executing outside of the Angular zone (this might not be relevant to Core or Vue users)
  • Because my android:launchMode is standard, any code that is run in the Angular zone would be disconnected from the main activity, so the user wouldn't see anything happen when I tried to show a dialog

This Stack Overflow answer applying the service locator pattern to Angular saved me a lot of trouble, I'll try to summarize:

1. Run onDynamicLinkCallback's contents in the Angular zone

I wrap my callback's contents in NgZone.run as soon as I can so it comes back into Angular. I run firebase.init in a FirebaseService that stores my DynamicLinkData in a BehaviorSubject other services can subscribe to, so:

onDynamicLinkCallback: (data: DynamicLinkData) => this.dynamicLink.next(data),

becomes

onDynamicLinkCallback: (data: DynamicLinkData) => this.zone.run(() => this.dynamicLink.next(data)),

2. Use a service locator to run code in the main activity

a. Make injected dependencies available to other activities

  1. Here's a service locator. Isn't it cute?

    import { Injector } from '@angular/core'
    
    export class ServiceLocator {
      static injector: Injector
    }
    
    export default ServiceLocator
    
  2. In my main module, I provide the service locator with a reference to the dependency injector:
    ts export class AppModule { constructor(private injector: Injector) { ServiceLocator.injector = this.injector } }

I can reference any injected dependencies using ServiceLocator.injector.get.

b. Call the main activity's services from other activities

Now I can jump back into the main activity by using my ServiceLocator in a subscription to my dynamicLink BehaviorSubject:

this.firebase.dynamicLink.asObservable().subscribe(async x => {
  const id = someFunctionThatParsesDynamicLinks(x)
  if (!!id) SomeService.someFunctionThatShowsADialog({ id })
})

becomes

this.firebase.dynamicLink.asObservable().subscribe(async x => {
  const id = someFunctionThatParsesDynamicLinks(x)
  if (!!id) ServiceLocator.injector.get(SomeService).someFunctionThatShowsADialog({ id })
})

Forgive me if the terminology is off, I'm pretty far outside my comfort zone here

Was this page helpful?
0 / 5 - 0 ratings