I'm building an app that has a timer to request geolocation while the timer is active. For a timer I'm using react-native-background-timer. Which is kind of working, but not exactly as I want.
With this piece of code:
BackgroundTimer.runBackgroundTimer(() => {
console.log('tic');
},
1000);
the timer is stopping when the app is in the background. While with this piece of code:
const intervalId = BackgroundTimer.setInterval(() => {
console.log('tic');
}, 1000);
it runs constantly even in the background, but I'm not able to stop it. When I run BackgroundTimer.clearInterval(intervalId);, the timer still runs. Even when I leave the screen and go back to my Home screen, the timer still ticks and never stops. This is not ideal, because I need timer to run for a few minutes and then stop.
I set the timer to 1 second to update time left on the screen. I was thinking about setting a timer once for 6 minutes, but then how do I update the state every second? Making 2 timers for this feels like a bad practise, even though it would work.
So to make it more clear, the user suppose to engage in certain activity like walking for a few minutes. So I can't let the timer to stop when user is answering a call or opened a music app to switch music or something else. Timer still needs to run and I need to measure the number of steps and distance with geolocation. It need to work flawlessly even if user opened another app, forgot about my app, and it would still run for the remaining time, then made a record to the database and stopped.
Try the following code snippet,
works both on android and ios
import { DeviceEventEmitter, NativeAppEventEmitter, Platform } from 'react-native';
import _BackgroundTimer from 'react-native-background-timer';
const EventEmitter = Platform.select({
ios: () => NativeAppEventEmitter,
android: () => DeviceEventEmitter,
})();
class BackgroundTimer {
static setInterval(callback, delay) {
_BackgroundTimer.start();
this.backgroundListener = EventEmitter.addListener("backgroundTimer", () => {
this.backgroundTimer = _BackgroundTimer.setInterval(callback, delay);
});
return this.backgroundListener;
}
static clearInterval(timer) {
if (timer) timer.remove();
if (this.backgroundTimer)
_BackgroundTimer.clearInterval(this.backgroundTimer);
_BackgroundTimer.stop();
}
}
export default BackgroundTimer;
Usage
const timer = BackgroundTimer.setInterval(callback, 1000);
BackgroundTimer.clearInterval(timer)
For some reason I got the following error when using #Aravind Vemula's answer.
When calling BackgroundTimer.clearInterval(timer); the following error appears:
timer.remove is not a function
That's why I modified the code slightly.
// parameter removed
static clearInterval() {
// ADD this if statement
if (this.backgroundListener){
this.backgroundListener.remove();
}
if (this.backgroundTimer)
_BackgroundTimer.clearInterval(this.backgroundTimer);
_BackgroundTimer.stop();
}
The above code checks if a backgroundlistener is registered. If yes it removes all listeners and especially our backgroundTimer.
Usage:
BackgroundTimer.clearInterval(); // removed parameter
After my change, everything is working fine on iOS 14.3.
#Aravind Vemula's answer working properly. But if user open the app from the background and timer code is added in background handler then when you stop the timer it is not working. So following changes you need to make in both the methods.
static setInterval(callback, delay) {
if (!this.backgroundListener && !this.locationTimer) {
_BackgroundTimer.start();
this.backgroundListener = EventEmitter.addListener('backgroundTimer', () => {
this.locationTimer = _BackgroundTimer.setInterval(callback, delay);
});
return this.locationTimer;
}
}
static clearInterval() {
if (this.backgroundListener) {
this.backgroundListener.remove();
}
if (this.locationTimer) {
_BackgroundTimer.clearInterval(this.locationTimer);
}
this.backgroundListener = false;
this.locationTimer = false;
_BackgroundTimer.stop();
_BackgroundTimer.start();
}
Related
I am trying to build a dinosaur running game in React much like google chrome's.
My idea is that I will run a function at the exact moment the object is suppose to hit the dinosaur, around 3 seconds
function check4Death() {
if (playerClass !== '') {
console.log('safe')
}
else {
console.log('nope')
clearInterval()
}
}
setInterval(check4Death, 3000)
This function checks to see if the player is currently in the air
As my method of jumping is adding and then removing a class from my playerClass object
function Jump() {
setPlayerClass('jump')
setTimeout(() => {
setPlayerClass('')
}, 500);
}
Instead of the function telling me either safe or nope every three seconds, I get this
I am very confused as to why this is happening, I have a link to my full code here
I'm using react-native 0.63 and doing a simple 1sec interval when I mount a component.
e.g.
useEffect(() => {
// Start elapsed ticker
const levelTicker = setInterval(() => {
console.log('TICK...')
setSeconds((s) => s + 1)
}, 1000)
return () => {
console.log('CLEARING INTERVAL')
clearInterval(levelTicker)
}
}, [])
When I run the app without debugger on, the app will render the timer correctly (1 second every render). But when I activate the debugger, it runs much more quickly--0.00001s every render--which makes it almost impossible to click buttons or do whatever on the app. The same thing happens when trying to onPress on Buttons that has onLongPress. It will run so fast, that even a quick tap will trigger the onLongPress.
Any clues how to make at least to run at normal speed? Thanks in advance.
Device:
OnePlus 7T, Android 10
I have an IONIC 4 application where I need to call an api every 20 seconds and if the user moves to other page need to stop calling that api. I am able to make the api call at every 20 seconds but not able to stop it when I move to some other page. Here is my code below, may I know where I went wrong?
rateTimer:any;
constructor(private loginServiceService: LoginServiceService) {
this.loginServiceService.getappData();
this.rateTimer=setInterval(() => {
this.loginServiceService.getappData();
}, 10000);
}
// When I move to other page, I clear the setInterval from here
ngOnDestroy() {
clearInterval(this.rateTimer);
}
As far as I know Ionic has a cache for page-navigation which is why ngOnDestroy/ngOnInit will not always work. However, there's ionViewDidLeave which should definitely fire, once the current page is moved away from (see https://ionicframework.com/docs/api/router-outlet#life-cycle-hooks for more details):
export class YourComponent {
ionViewDidLeave() {
// Do actions here
}
}
I'm working on a React based timer app. The countdown works perfectly both in web and mobile but it freezes/miscounts when on the browser in mobile, it is minimized or closed to background. Is there any way of getting the timer to run as expected in the background when browser minimized or phone locked?
timer = () => {
if (!this.props.paused) {
this.setState(
prevState => ({ time: prevState.time - 1 }),
() => {
if (this.state.time === 0) {
clearInterval(this.state.countdown);
this.props.onEnd();
}
}
);
}
};
This is my code for the timer function which decrements time and calls onEnd function when countdown over.
componentDidMount() {
const countdown = setInterval(this.timer, 1000);
}
This is called every 1 second by the setInterval function.
Is there an easy way of getting the timer to work as expected from background for mobiles? I've been recommended service workers. In a create-react-app setup what can be done to implement this functionality using service workers?
So I'm attempting to make a Pomodoro Timer without using an API (I know, stupid choice) but I feel as if I'm over-complicating this issue.
I forked my CodePen so I could post the current code here without confusing anyone. My Code Pen
To see my issue: Just set Timer to .1 and Break to .1 - You'll see the Start to Resume works fine, but the Resume to start has issues.
I built in consoleLogs to track it and I see the Work Timer TRIES to start but then breakTimer over-runs it, and duplicates on every pass.
Why isn't my clearInterval working?
Things I've tried:
Adjusting names of clearInterval,
Setting it so it goes back to startTimer instead of start
force quitting it (instead of looping it back to startInterval.
The function is virtually identical to my startFunction yet fails to work properly. Would appreciate any input (I'm new to clearInterval but I believe I am using it right.)
function breakTimer() {
$('.jumbotron').css('visibility', 'visible');
setInterval(function() {
console.log("Break Timer...");
breakTime--;
if (breakTime < 0) {
clearInterval(timer);
working = false;
start();
} else {
showTime(breakTime);
}
}, 1000);
}
Edit:
To answer the reply:
function start() {
if (working == true){ //This keeps it from being spammable
return;
} //Else
workTime = $('#work').val()*60;
breakTime = $('#break').val()*60;
working = true;
checkStatus();
timer = startTimer();
}
Unsure if I should post every Function here
As per definition, the value returned by setInterval(...) is the ID of the created timer. As such, with your code you can only stop the last created timer because the ID in the timer variable gets overwritten, causing it to lose control over the previously created (and still running) timers.
The ID is what you pass on to clearInterval(...) to stop a timer. You will have to do this in a different way. You may ask for a different way in https://codereview.stackexchange.com/