Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Headless event listener not called when app is killed #55

Open
mathiasmoeller opened this issue Mar 19, 2020 · 24 comments
Open

Headless event listener not called when app is killed #55

mathiasmoeller opened this issue Mar 19, 2020 · 24 comments

Comments

@mathiasmoeller
Copy link

Hey @eddieowens !

When the app is in foreground or background the boundary callbacks work perfectly!
But I am struggling with the Headless part when the app is killed.
In logcat I can see that the event is fired. I see the log message from boundary's index.js file:

ReactNativeJS: 'onExit', [ 'rated0' ]

which comes from this part of code here:

const HeadlessBoundaryEventTask = async ({event, ids}) => {
  console.log(event, ids);
  boundaryEventEmitter.emit(event, ids)
};

But my callback is never executed. I think the issue might be timing.
When the app starts because of a Headless event I can see that boundary receives the event as said above. I added log messages for the Callback Registration and it seems to happen after the Headless event:

15:03:19.837 ReactNativeJS: 'onExit', [ 'rated0' ] // from boundary's index.js
15:03:19.863 ReactNativeJS: Registering Boundary Callbacks // my code

I moved the callback registration to the very first line of my index.js but the order still seems to be incorrect. Any idea how to solve this? Where should I call the Boundary.on callback registration in my code?

Setup:

  • "react-native": "0.59.5"
  • "react-native-activity-recognition": "woffu/react-native-boundary" // fix for newer android versions

Help is very much appreciated :)

@NuclearKev
Copy link

@mathiasmoeller I was having the same issue and fixed it by registering another headless task in index.js for the event. Then I just have it run the same code as it normally would. This method doesn't work for iOS, however, so it's not a great solution. I can't get iOS to do stuff when the app is killed and I don't know why.

@aniksharif
Copy link

Hi @NuclearKev , can you share the code how you did that! That will be a big help!

@NuclearKev
Copy link

NuclearKev commented Apr 21, 2020

Sure! I use ClojureScript so it'll look kinda weird but you should be able to get the gist:

Somewhere in index.js you'll need to add the headless task register

(.registerHeadlessTask app-registry "OnBoundaryEvent" (fn [] async-boundary))

Make sure that you register the same event that react-native-boundary does, namely "OnBoundaryEvent".

registerHeadlessTask requires that the function you pass it be async. In CLJS I had to have a function that returns the async function but I don't think you need that in JS.

Then, somewhere else:

(defn async-boundary [d]
  (async
   (let [event (.-event ^js d)
         id (first (.-ids ^js d))]
     (when (= event "onEnter")
       ;; run some code in here!
      ))
   (js/Promise.resolve)))

and that's literally it!

EDIT: You may need to comment out the headless task in react-native-boundary to remove some warnings.

@matyasdanko
Copy link

@NuclearKev
How would that look like in TypeScript?
Do I just put

AppRegistry.registerHeadlessTask('OnBoundaryEvent', (event) => {
    if(event == "onEnter"){
        //my code here
     }
})

into the index.js?
My main concern is: how would I get access to the id?
Does it get passed along in the event ?

Your answer would be highly appreciated.

@NuclearKev
Copy link

NuclearKev commented Apr 21, 2020

@SufniDroid just like how react-native-boundary does it:

const HeadlessBoundaryEventTask = async ({event, ids}) => {
  console.log(event, ids);
  boundaryEventEmitter.emit(event, ids)
};

So in our case:

const HeadlessBoundaryEventTask = async ({event, ids}) => {
     if(event === "onEnter"){
        //my code here
     }
};

EDIT: or like this if you don't want to have a named function:

AppRegistry.registerHeadlessTask('OnBoundaryEvent', async ({event, ids}) => {
    if(event === "onEnter"){
        //my code here
     }
})

@NuclearKev
Copy link

I hope that works for you guys! I still have yet to figure out iOS....

@NuclearKev
Copy link

I know that the event gets triggered (if I put a breakpoint on the native code where the event gets triggered, it will stop there) but the code in the event listener doesn't get ran. No idea how to make it run. I was thinking it was maybe related to BGTaskScheduler but the more I look into it the less I think that's it.

@cladjules
Copy link

@NuclearKev I am working on a fix for iOS, should come very shortly.

@NuclearKev
Copy link

@cladjules please, keep us posted! :)

@NuclearKev
Copy link

Just tested this ability with react-native-background-geolocation and it worked. So it's definitely possible! Their library is far more complicated than react-native-boundary, so getting it to work would be excellent. Not to mention, the other one causes a lot of money to use on Android...

@mathiasmoeller
Copy link
Author

Yes a fix for iOS would be awesome! I managed to get it run on Android (the way @NuclearKev suggested). Now iOS needs to work 😁
Thanks for your help!

@cladjules
Copy link

cladjules commented Apr 26, 2020

I have opened a PR here: #56

It looks ok on my side, if you could do some testing, that would be great.

Thanks

@NuclearKev
Copy link

Thanks, @cladjules

I'll be testing that out later today!

@NuclearKev
Copy link

@cladjules your fixes worked!

@cladjules
Copy link

@NuclearKev Great. Thanks for the help on Android as well.
That should probably be documented?

@NuclearKev
Copy link

@cladjules where should it be documented?

@cladjules
Copy link

cladjules commented May 8, 2020

@NuclearKev How to add the Headless function, it's not obvious until you find that open issue.
In the Readme, I guess.

@NuclearKev
Copy link

NuclearKev commented May 12, 2020

Does anyone know if there is a way to force iOS to check the location upon app startup? It looks like if the user has the location permission set to "while using," it won't fire the event if they are in the radius when they open the app.

EDIT: I tried adding in a function that runs [self.locationManager checkLocation] but it doesn't seem to work.

@m-ruhl
Copy link

m-ruhl commented May 15, 2020

The native APIs are designed to work only if the user sets the location permission to always.

@xoapit
Copy link

xoapit commented Jun 7, 2020

@SufniDroid just like how react-native-boundary does it:

const HeadlessBoundaryEventTask = async ({event, ids}) => {
  console.log(event, ids);
  boundaryEventEmitter.emit(event, ids)
};

So in our case:

const HeadlessBoundaryEventTask = async ({event, ids}) => {
     if(event === "onEnter"){
        //my code here
     }
};

EDIT: or like this if you don't want to have a named function:

AppRegistry.registerHeadlessTask('OnBoundaryEvent', async ({event, ids}) => {
    if(event === "onEnter"){
        //my code here
     }
})

@NuclearKev Where can I put this code?
I put it in componentDidMount() but it is not working. There is an error: taskProvider() is not a function. (In 'taskProvider()(data)', 'taskProvider()' is an instance of Promise).

@xoapit
Copy link

xoapit commented Jun 7, 2020

It shoud be like this: AppRegistry.registerHeadlessTask('OnBoundaryEvent', () => async ({event, ids}) => { if(event === "onEnter"){ //my code here } })

@NuclearKev
Copy link

@xoapit I believe that in JavaScript you need to place it in the index.js file. (In ClojureScript it can be placed in the core.cljs)

@cladjules
Copy link

@xoapit @NuclearKev I doubt you need to add anything additional?
It's already included in that lib's index.js: https://github.com/eddieowens/react-native-boundary/blob/master/index.js

Should work out of the box, as long as your listeners are not within a React lifecycle.

@xoapit
Copy link

xoapit commented Jun 13, 2020

on Event doesn't work in Android when the app is killed so I have to use addAppRegistry.registerHeadlessTask outside of React lifecycle as a trick to observe event changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants