ionic background geolocation stop working - ionic-framework

whit this code i can get gps data and retrive address all works fine in background, for some minuts, after 20 minuts about,the app semms stop do what i aspect.
i tryed battery concession and other possible things, ive tryed backgroud service.
But nothing seems to wor for get position in background, after lomg time.
Any suggestion.
this.backgroundGeolocation.configure(config).then(() => {
console.log('backgroundGeolocation configconfigconfigconfigconfigconfig');
this.backgroundGeolocation.on(BackgroundGeolocationEvents.location).subscribe((location: BackgroundGeolocationResponse) => {
console.log(location);
this.ngZone.run(() => {
this.geolocationService.nativeGeocoder.reverseGeocode(location.latitude,
location.longitude).then((result: NativeGeocoderResult[]) =>{
console.log("JSON.stringify(result[0]",JSON.stringify(result[0]));
this.comunenoreplace = result[0]['locality'];
this.comune = result[0]['locality'].replace(/[^A-Z0-9]+/ig, "-");
this.provincia = result[0]['subAdministrativeArea'].replace(new RegExp('Città Metropolitana di|Provincia di', 'g'), '');
this.globalLatitude = location.latitude;
this.globalLongitude = location.longitude;
}).catch((error: any) => console.log("reverseGeocode", error));
});
// IMPORTANT: You must execute the finish method here to inform the native plugin that you're finished,
// and the background-task may be completed. You must do this regardless if your operations are successful or not.
// IF YOU DON'T, ios will CRASH YOUR APP for spending too much time in the background.
// this.backgroundGeolocation.finish;
});
});

you can use the https://ionicframework.com/docs/native/background-mode
it just modify the sleep mode for apps to make them work in background (without killing the process).
If the process is killed, so the app may stop sending datas.
Then you have "cordova.plugins.backgroundMode.excludeFromTaskList()"; to make it disappear from the tasklist (Android 5.0+)
Hope this help :)

Related

is there a way to check if the PWA was launched through a file or not?

I'm using the file handle API to give my web app the optional capability to launch through double-clicking files in the file explorer.
Writing the code below, I expected if (!("files" in LaunchParams.prototype)) to check if a file was used to launch the app, but apparently, it checks if the feature is supported. OK, that makes sense.
After that, I thought the setConsumer callback would be called in any launch scenario, and files.length would be zero if the app was launched in other ways (like by typing the URL in the browser). But on those use cases, the callback was not called at all, and my init logic was never executed.
if (!("launchQueue" in window)) return textRecord.open('a welcome text');
if (!("files" in LaunchParams.prototype)) return textRecord.open('a welcome text');
launchQueue.setConsumer((launchParams) => {
if (launchParams.files.length <= 0) return textRecord.open('a welcome text');
const fileHandle = launchParams.files[0];
textRecord.open(fileHandle);
});
I've also followed the Launch Handler API article instructions and enabled the experimental API.
The new code confirms that "targetURL" in LaunchParams.prototype is true, but the setConsumer callback is not executed if the user accesses the web app through a standard browser tab.
function updateIfLaunchedByFile(textRecord) {
if (!("launchQueue" in window)) return;
if (!("files" in LaunchParams.prototype)) return;
console.log({
'"targetURL" in LaunchParams': "targetURL" in LaunchParams.prototype,
});
// this is always undefined
console.log({ "LaunchParams.targetURL": LaunchParams.targetURL });
// setConsumer does not trigger if the app is not launched by file, so it is not a good place to branch what to do in every launch situation
launchQueue.setConsumer((launchParams) => {
// this never run in a normal tab
console.log({ setConsumer: launchParams });
if (launchParams.files.length <= 0) return;
const fileHandle = launchParams.files[0];
textRecord.open(fileHandle);
});
}
This is the result...
Is there a universal way to check if the web app was launched through a file?
Check out the Launch Handler origin trial. It lets you determine the launch behavior exactly and lets your app detect how the launch happened. This API works well together with the File Handling API that you already use. You could, for example, check the LaunchParams.targetURL to see how the app was launched. Your feedback is very welcome.
Since I was not able to guarantee that the setConsumer callback was called in every situation (especially when the app is launched in a regular browser tab), I hacked it through setTimeout:
function wasFileLaunched() {
if (!("launchQueue" in window)) return;
if (!("files" in LaunchParams.prototype)) return;
return new Promise((resolve) => {
let invoked = false;
// setConsumer does not triggers if the app is not launched by file, so it is not a good place to branch what to do in every launch situation
launchQueue.setConsumer((launchParams) => {
invoked = true;
if (launchParams.files.length <= 0) return resolve();
const fileHandle = launchParams.files[0];
resolve(fileHandle);
});
setTimeout(() => {
console.log({ "setTimeout invoked =": invoked });
if (!invoked) resolve();
}, 10);
});
}

Ionic 4 intercept android back button for navigation

so in ionic 3 there was registerBackButton() but in ionic 4 this option is no longer there and has been sitting on the shelf for quite some time now.
I have read the post here that tries to solve the solution I am looking for, however, the back button still performs as it wants to.
this SO answer shows another way but it is the same idea of intercepting and navigating, however, I am just, for now, trying to dismiss the top modal in the stack.
scenario: users open a search modal(modal1) which then they click on a users profile modal(modal2). The person wants to go back to the search modal(modal1) but instead of clicking the nice button that allows them to do that, they use the hardware back button.
result: all modals(modal1 and modal2) are closed.
desired effect: using the hardware back button will allow for custom navigation based on logic in place.
attempted code:
this.platform.backButton.subscribeWithPriority(0, (): void => {
this.modalCtrl.getTop().then(
async (value: HTMLIonModalElement): Promise<void> => {
if (!!value) {
await this.modalCtrl.dismiss();
} else {
this.navCtrl.navigateRoot('/home');
}
},
);
});
also have tried :
// registering back, if there is a view on top, close it, don't go to home.
this.platform.backButton.subscribeWithPriority(0, async (): Promise<void>=> {
try {
console.log('try');
const element = await this.modalCtrl.getTop();
if (element) {
console.log('in true');
await element.dismiss();
}
} catch (error) {
console.log('error closing modal', error);
}
});
note when pressing the back button I never see ANY of the console logs... maybe things have changed a lot more? since the previous Stack overflow questions.
UPDATE:
If you are having this same issue then know you are not alone!
This, and many others are well known, see here for a list they are tracking the issues. Nothing else to do... but wait... I guess...
I will update this when there is a change

Ensure processing of a REST call in flutter app in background

I need to ensure that a certain HTTP request was send successfully. Therefore, I'm wondering if a simple way exists to move such a request into a background service task.
The background of my question is the following:
We're developing a survey application using flutter. Unfortunately, the app is intended to be used in an environment where no mobile internet connection can be guaranteed. Therefore, I’m not able to simply post the result of the survey one time but I have to retry it if it fails due to network problems. My current code looks like the following. The problem with my current solution is that it only works while the app is active all the time. If the user minimizes or closes the app, the data I want to upload is lost.
Therefore, I’m looking for a solution to wrap the upload process in a background service task so that it will be processed even when the user closes the app. I found several posts and plugins (namely https://medium.com/flutter-io/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124 and https://pub.dartlang.org/packages/background_fetch) but they don’t help in my particular use case. The first describes a way how the app could be notified when a certain event (namely the geofence occurred) and the second only works every 15 minutes and focuses a different scenario as well.
Does somebody knows a simple way how I can ensure that a request was processed even when there is a bad internet connection (or even none at the moment) while allowing the users to minimize or even close the app?
Future _processUploadQueue() async {
int retryCounter = 0;
Future.doWhile(() {
if(retryCounter == 10){
print('Abborted after 10 tries');
return false;
}
if (_request.uploaded) {
print('Upload ready');
return false;
}
if(! _request.uploaded) {
_networkService.sendRequest(request: _request.entry)
.then((id){
print(id);
setState(() {
_request.uploaded = true;
});
}).catchError((e) {
retryCounter++;
print(e);
});
}
// e ^ retryCounter, min 0 Sec, max 10 minutes
int waitTime = min(max(0, exp(retryCounter)).round(), 600);
print('Waiting $waitTime seconds till next try');
return new Future.delayed(new Duration(seconds: waitTime), () {
print('waited $waitTime seconds');
return true;
});
})
.then(print)
.catchError(print);
}
You can use the plugin shared_preferences to save each HTTP response to the device until the upload completes successfully. Like this:
requests: [
{
id: 8eh1gc,
request: "..."
},
...
],
Then whenever the app is launched, check if any requests are in the list, retry them, and delete them if they complete. You could also use the background_fetch to do this every 15 minutes.

On subscription run a "callback" function once

I'm working with cordova's BLE (bluetooth low energy)
After I subscribe to notifications of BLE (which returns Observable), I want to send some message to the ble device, what is the best way to perform this, basically I need to run a function once after the subscription is made so that once device responds back to me, the code in the subscription is run.
ble.startNotification(deviceId, uuid1, uuid2).subscribe(bufferData=> {
//do something with bufferData
})
now after this, I want to run something like a callback,
.then(()=> {
//send message to device (only once), after the message is sent, the device will respond back and the `do something with bufferData` code will be run
})
I could easily do a setTimeout and send a message to the device after few seconds, and of course it works, but I want to do it cleanly, after I'm sure the subscription happened (subscription to the Observable of course)
You can wrap existing method using create operator and add custom code that will be executed on every new subscription.
See the example:
// emulate cordova with "dummy" bluetooth interface
const BLE = {
startNotification: () => Rx.Observable.interval(1000)
}
const wrappedBLE = (...params) =>
Rx.Observable.create(observer => {
// constructor fn will be executed on every new subscribtion
const disposable = BLE.startNotification(...params).subscribe(observer);
// place code to send notification here, instead of console log
console.log('New subscriber for BLE with params: ', params);
return disposable;
});
wrappedBLE("param1", "param2", "param3")
.subscribe(e => console.log("received notification: ", e));
<script src="https://unpkg.com/rxjs#5.4.3/bundles/Rx.min.js"></script>

Xamarin.Forms Taking picture with Plugin.Media not working

I'm using the Plugin.Media from #JamesMontemagno version 2.4.0-beta (which fixes picture orientation), it's working on Adroind 4.1.2 (Jelly Bean) and Marshmallow, but NOT on my Galaxy S5 Neo with Android version 5.1.1.
Basically when I take a picture it never returns back on the page from where I started the process; always returns back to the initial home page.
On devices where it works, when I take a picture, I see that first of all the application fires OnSleep, then after taking the picture fires OnResume.
On my device where is NOT working it fires OnSleep and after taking the picture doesn't fire OnResume, it fires the initialization page and then OnStart.
For this reason it doesn't open the page where I was when taking the picture.
What should I do to make sure it fires OnResume returning to the correct page and not OnStart which returns on initial fome page ?
In addition, when I take a picture it takes almost 30 seconds to get back to the code after awaiting TakePhotoAsync process, and it's too slow!
Following my code:
MyTapGestureRecognizerEditPicture.Tapped += async (sender, e) =>
{
//Display action sheet
String MyActionResult = await DisplayActionSheet(AppLocalization.UserInterface.EditImage,
AppLocalization.UserInterface.Cancel,
AppLocalization.UserInterface.Delete,
AppLocalization.UserInterface.TakePhoto,
AppLocalization.UserInterface.PickPhoto);
//Execute action result
if (MyActionResult == AppLocalization.UserInterface.TakePhoto)
{
//-----------------------------------------------------------------------------------------------------------------------------------------------
//Take photo
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert(AppLocalization.UserInterface.Alert, AppLocalization.UserInterface.NoCameraAvailable, AppLocalization.UserInterface.Ok);
}
else
{
var MyPhotoFile = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "MyApp",
Name = "MyAppProfile.jpg",
SaveToAlbum = true,
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Small
});
if (MyPhotoFile != null)
{
//Render image
MyProfilePicture.Source = ImageSource.FromFile(MyPhotoFile.Path);
//Save image on database
MemoryStream MyMemoryStream = new MemoryStream();
MyPhotoFile.GetStream().CopyTo(MyMemoryStream);
byte[] MyArrBytePicture = MyMemoryStream.ToArray();
await SaveProfilePicture(MyArrBytePicture);
MyPhotoFile.Dispose();
MyMemoryStream.Dispose();
}
}
}
if (MyActionResult == AppLocalization.UserInterface.PickPhoto)
{
//-----------------------------------------------------------------------------------------------------------------------------------------------
//Pick photo
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert(AppLocalization.UserInterface.Alert, AppLocalization.UserInterface.PermissionNotGranted, AppLocalization.UserInterface.Ok);
}
else
{
var MyPhotoFile = await CrossMedia.Current.PickPhotoAsync();
if (MyPhotoFile != null)
{
//Render image
MyProfilePicture.Source = ImageSource.FromFile(MyPhotoFile.Path);
//Save image on database
MemoryStream MyMemoryStream = new MemoryStream();
MyPhotoFile.GetStream().CopyTo(MyMemoryStream);
byte[] MyArrBytePicture = MyMemoryStream.ToArray();
await SaveProfilePicture(MyArrBytePicture);
MyPhotoFile.Dispose();
MyMemoryStream.Dispose();
}
}
}
};
Please help!! We need to deploy this app but we cannot do it with this problem.
Thank you in advance!
It is perfectly normal to have the Android OS terminate and restart an Activity. As you are seeing, your app's Activity it will be automatically restarted when the camera app exits and the OS returns control to your app. The odds are it just needed more memory in order to take that photo with the Neo's 16MP camera, you can watch the logcat output to confirm that.
Restarted – It is possible for an activity that is anywhere from paused to stopped in the lifecycle to be removed from memory by Android. If the user navigates back to the activity it must be restarted, restored to its previously saved state, and then displayed to the user.
What to do:
So on the Xamarin.Forms OnStart lifecycle method you need to restore your application to a valid running state (initializing variables, preforming any bindings, etc...).
Plug code:
The Android platform code for the TakePhotoAsync method looks fine to me, but remember that the memory for that image that is passed back via the Task will be doubled as it is marshaled from the ART VM back the Mono VM. Calling GC.Collect() as soon as possible after the return will help (but your Activity is restarting anyway...)
public async Task<MediaFile> TakePhotoAsync(StoreCameraMediaOptions options)
{
~~~
var media = await TakeMediaAsync("image/*", MediaStore.ActionImageCapture, options);
In turn calls:
this.context.StartActivity(CreateMediaIntent(id, type, action, options));
Not much less you can really do within the Android OS to popup the Camera.
In addition, when I take a picture it takes almost 30 seconds to get back to the code after awaiting TakePhotoAsync process, and it's too slow!
Is that on your Neo? Or all devices?
I would call that very suspect (ie. a bug) as even flushing all the Java memory after the native Camera Intent/Activity and the restart time for your app's Activity should not take 30 seconds on a oct-core 1.6 GHz Cortex... but I do not have your device, app and code in front of me....