I have this extremely weird situation. I have this code:
useEffect(() => {
let timeout = undefined as NodeJS.Timeout | undefined;
if (dismissAfter && visible) {
timeout = setTimeout(() => { <--- This code get called, but all code inside it not being called
alert("HELLO"); <--- This alert does not even get called
setVisible(false);
}, dismissAfter);
}
return () => { if (timeout) clearTimeout(timeout); }
}, [dismissAfter, visible]);
The code is to clear a notification automatically if there is dismissAfter property. If I run on web browser this works fine, but not in Android Emulator.
What am I missing here? Is this bug?
Related
I have a requirement of pausing video and some other actions to perform when user clicks on home button or switch to another app using swiper action. I looked at react-native AppState, but it is not calling the event listener when home button clicked on android for some devices. Is there any compatibility minimum version requirements for the react-native app state to work?
The code I tried is as below
useEffect(() => {
AppState.addEventListener("change", _handleAppStateChange);
return () => {
AppState.removeEventListener("change", _handleAppStateChange);
};
}, []);
const _handleAppStateChange = (nextAppState: any) => {
console.log(nextAppState);
};
The console is not printed when clicked on home button/Swiped to another app on some android devices. Is there anyway I can achieve this using react-native preferably without using any external libraries.
As for your requirement, in react-native, to detect is application is in foreground or in background, you don't need to add home-button listener, we can easily achieve this with the help of AppState, check below example,
_handleAppStateChange = (nextAppState: any) => {
if (this.state.appState === "active" && nextAppState === "background") {
// this condition calls when app goes in background mode
// here you can detect application is in background, and you can pause your video
} else if (this.state.appState === "background" && nextAppState === "active") {
// this condition calls when app is in foreground mode
// here you can detect application is in active state again,
// and if you want you can resume your video
}
this.setState({ appState: nextAppState });
};
You also need to attach AppState listener to application to detect application states, for example,
componentDidMount() {
AppState.addEventListener("change", _handleAppStateChange);
}
and detach app-state listener when application component unmount, for example,
componentWillUnmount {
AppState.removeEventListener("change", _handleAppStateChange);
}
Or if you are working with functional component you attach or detach app-state listener in useEffect, for example,
useEffect(() => {
AppState.addEventListener("change", _handleAppStateChange);
return () => {
AppState.removeEventListener("change", _handleAppStateChange);
};
}, []);
I want to perform some actions when my app goes to the background—e.g., when pressing the home button. (I am testing on an Android device.)
I tried the following in my app.component.ts:
this.platform.ready().then(() => {
this.platform.pause.subscribe(async () => {
alert("Pause event detected");
//Do stuff here
});
this.platform.resume.subscribe(async () => {
alert("Resume event detected");
//Do stuff here
});
…
I also tried:
App.getState().then((result) => {
alert("state active?" + result.isActive);
});
No listener is triggered when the app goes to background (e.g., by pressing the home button). But when I start the app again, all events are triggered (in this case, the alerts), including the platform.pause event.
I am using Ionic 9 and Capacitor.
Am I misunderstanding something? What could be the problem?
You can use the event listeners provided in Capacitor's App API.
// Import the relevant stuff from Capacitor
import { Plugins, AppState } from '#capacitor/core';
const { App } = Plugins;
Then in your AppComponent class
this.platform.ready().then(() => {
App.addListener('appStateChange', (state: AppState) => {
if (state.isActive) {
console.log('App has become active');
} else {
console.log('App has become inactive');
}
});
})
Note that you can test this in a desktop browser as well by switching to another tab.
Ok... things work. The problem was, that I had both variants in code active.
I have a button when pressing it performs the request for some data. So, in my ts file of the page where the button is, I call the function in my provider.
The main problem comes when I compile my application for android platform (Generate apk with ionic cordova build --release android, then I Sign the apk, align and install it). In that case, when I press the button nothing happens, I debugged the code (I added some alerts), but only the first line of the function (The alert that I added) is executed, never returns anything.
But.. If I run the app with the commands: ionic cordova run android -l and ionic serve -l. It works like a charm (The provider return the data requested)
I mean, the problem is only when I generate the APK to install it into my device
I also tried with HttpClient but the problem persists.
The code of my Provider is:
Search(path): Promise<any> {
// ------------- The alert is shown
return this.http.get(path)
.map(res => res.json())
.toPromise()
.then(
response => {
// ------------- The alert is not shown
if (typeof response.user.name !== "undefined") {
this.storage.set('users', JSON.stringify(response));
return response;
} else {
return null;
}
},
error => {
// ------------- The alert is not shown
return null;
});
}
I also tried with something like this:
Search(path): Promise<any> {
// ------------- The alert is shown
return null;
}
But, also in this case the return line is never executed, only the alert is shown.
The code when I call my provider function in the page where the button is:
this.APIService.Search(final_path).then(res => {
if (res) {
this.storage.get('users').then(responseJson => {
if (responseJson) {
this.navCtrl.push(ObtenerPage);
}
});
} else {
this.presentToast("Bad request");
}
});
I want to catch uncaught exception of android react native app. For this some blogs suggesting to use following code:
ErrorUtils.setGlobalHandler(error => {
sentry.capture(error);
NativeModules.BridgeReloader.reload()
});
But I don't know the complete mechanism to implement this. Can any one let me know how do I implement code for such requirement?
I got solution, We should use ErrorUtils handler to detect run time exception. For this we have to add
if (ErrorUtils._globalHandler) {
instance.defaultHandler = ErrorUtils.getGlobalHandler && ErrorUtils.getGlobalHandler() || ErrorUtils._globalHandler;
ErrorUtils.setGlobalHandler(this.wrapGlobalHandler); //feed errors directly to our wrapGlobalHandler function
}
and in your wrapGlobalHandler method
async wrapGlobalHandler(error, isFatal) {
//* Report error here
setTimeout (() => {
this.defaultHandler(error, isFatal); //after you're finished, call the defaultHandler so that react-native also gets the error
if (Platform.OS == 'android') {
NodeModule.reload()
}
}, 1000);
}
I'm making an app with ionic for car drivers. The app takes coordinates every one minute and write them on remote server, this helps me to tracking route and show cars on Google map.
I use Cordova plugin and it works fine except when screen turns off or the app goes into the background. I installed katzer cordova-plugin-background-mode, when the app go into background I see the message : app is now in background, the plugin informs me but nothing else, the app stopped! .
No data sent to remote server, when I resume the app all is back to normal, I use Android platform. How can i solve?
app.js code
angular.module('starter', ['ionic', 'ngCordova','LocalStorageModule', 'starter.controllers', 'starter.services'])
.run(function ($ionicPlatform) {
$ionicPlatform.ready(function () {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleLightContent();
}
cordova.plugins.backgroundMode.enable();
});
})
.....
controllers.js
angular.module('starter.controllers', [])
.controller('GeoCtrl', function($scope, $cordovaGeolocation, $cordovaNetwork, $http, $interval) {
var reloadCoordinates = function() {
var watchOptions = {
timeout : 10000,
enableHighAccuracy: false // may cause errors if true
};
var watch = $cordovaGeolocation.watchPosition(watchOptions);
watch.then(
null,
function(err) {
// error
},
function(position) {
//Latitudine e Longitudine
var lat = position.coords.latitude
var lon = position.coords.longitude
$scope.latitude = lat
$scope.longitude = lon
$http.post('http://192.168.1.2/get-data.php', { "lat": lat, "lon" : lon }).then(function(resp) {
console.log('Success Lat:'+resp.data.lat+' Lon:'+resp.data.lon);
watch.clearWatch();
}, function(err) {
console.error('ERR', err);
// err.status will contain the status code
})
});
};//end reloadCoordinates
$interval(reloadCoordinates, 60000);
reloadCoordinates();
})
I know this is an old thread, but I did manage to get this working, with:
cordova.plugins.backgroundMode.on('enable', function(){
//your code here, will execute when background tasks is enabled
loop();
});
function loop(){
console.log("loop");
$timeout(loop, 1000);
}
cordova.plugins.backgroundMode.enable();
#Cristian,
after enabling plugin, you should call your function or write your logic in this function.
cordova.plugins.backgroundMode.onactivate = function() {
// your logic here
// or call any other service, factory function
};
Are you trying to make an app that does something every x minutes, even when the app is in the background and/or the screen is turned off.... tried backgound-mode plugin but it only works reliably when the phone is plugged in... did you ever found a solution to this?
Install the plugin using the cordova command line utility:
$ cordova plugin add https://github.com/boltex/cordova-plugin-powermanagement.git
here's how i use it along with the background mode plugin so the app is never in background and always running as a service...:
if( ionic.Platform.isAndroid() ){
cordova.plugins.backgroundMode.enable();
window.powerManagement.dim(function() {
console.log('Wakelock acquired');
}, function() {
console.log('Failed to acquire wakelock');
});
window.powerManagement.setReleaseOnPause(false, function() {
console.log('setReleaseOnPause successfully');
}, function() {
console.log('Failed to set');
});
}
Final Step Deactivate your plugin when you finished your service as
cordova.plugins.backgroundMode.disable()