What are the differences between CodenameOne getCurrentLocation methods? - geolocation

I'm building an app for Android and iOS that takes a picture, retrieve the device location and send the package to a server for processing.
To get the device location, I know I need to use one of the LocationManager's getCurrentLocation method. But they all look alike to me, so I picked up one but I'm not sure I picked the right one since it does not work very well (I'll explain later) on Android (KitKat).
Indeed I have experienced the same kinf of oddities as recently reported [here] (How to make an immediate reading location using GPS) and even worse. For example connected to home/office Wifi the location (although indoor) is accurate. I understood that the device is basing its results on network. But then when I am 5km (and 40 min) away with open sky and performing a location test with getCurrentLocation or getCurrentLocationAsync or even with a timeout, the device outputs my home/office past location with an accuracy of eg 50 m.
Also I noticed that the location icon that appears normally in Android status bar near to the clock does not appear. To make it appear I noticed that launching Maps app from Google made the location icon appear and then my app was able to locate the device.
Here is the last method I used to get the location :
`public static final void updateGeolocation (){
Location location = null;
try {
location = LocationManager.getLocationManager().getCurrentLocation();
setLocation(location);
setGeolocationAccuracy(location.getAccuracy() > 0.0f ? location.getAccuracy() : DEFAULT_GEOLOCATION_ACCURACY);
} catch (IOException e) {
setLocation(null);
setGeolocationAccuracy(DEFAULT_GEOLOCATION_ACCURACY);
}
}`
Now here is how I update the location thanks to timerTask :
// On lance la mise à jour périodique de la position de l'appareil
// la tache se lance en dehors de l'EDT
ParametresGeneraux.setCheckTimer(new Timer());
ParametresGeneraux.setCheckTask(new TimerTask(){
#Override
public void run() {
ParametresGeneraux.updateGeolocation();
}
});
ParametresGeneraux.getCheckTimer().schedule(ParametresGeneraux.getCheckTask(), 0, ParametresGeneraux.GEOLOCATION_CHECK_INTERVAL);
NB : Regarding the build hints I explained my need for GPS with the hint ios.locationUsageDescription
and I disabled the android.captureRecord hint because I did need it and did not want to make the user suspicious about why I would ever need capture Record.
So my questions are :
do I use the getCurrentLocation in the proper way so that I can blame my phone's hardware or am I using it wrong ?
Why does the location icon in the upper part of the screen does appear only if I launched Google Maps and not my app (as if my app did not trigger the location). ?
What's if I don't use a timeout and the location needs 10 minutes to come ? What will happen ? What would be the difference if I set the timeout to 10 seconds and the location comes 10 minutes later (for example I am in a tunnel) ?
Is it preferred to use a LocationListener although it may only trigger when the device location changes ?
Thanks in advance to whoever can make this clearer to my mind,
Edit : Following #ShaiAlmog advices to make all smoothly works I had to :
do no use the above described updateGeolocation() method
create my GeolocationListener listener that implements LocationListener and do my stuff in the overriden updateLocation method (see below)
set the LocationListener to my GeolocationListener in the main class' init method
Now the updated location is available and the location icon appears as expected.
My GeolocationListener is as simple as the following code :
public class GeolocationListener implements LocationListener{
#Override
public void providerStateChanged(int newState) {
}
/**
* Met à jour les valeur de la position et la précision de la géolocalisation si le service de géoloc est dispo. Sinon met à jour les valeurs avec null pour la position
* et DEFAULT_GEOLOCATION_ACCURACY pour la précision
*/
#Override
public void locationUpdated(Location location) {
// Par défaut
ParametresGeneraux.setLocation(null);
ParametresGeneraux.setGeolocationAccuracy(ParametresGeneraux.DEFAULT_GEOLOCATION_ACCURACY);
/*On met à jour la position et la précision
*/
if (location != null && (location.getStatus() == LocationManager.AVAILABLE)){
ParametresGeneraux.setLocation(location);
if ( location.getAccuracy() > 0.0f ) {
ParametresGeneraux.setGeolocationAccuracy(location.getAccuracy());
}
} // fin de la mise à jour de la position
}
}
Regards

If you need to constantly monitor location you need to use setLocationListener which will let you know as your location changes. We use the hybrid location API in Google Play which tries to be more efficient in terms of GPS usage and only fire it up as needed.
Since getting a GPS signal can take minutes and might be inaccurate/unavailable this is a simpler way for adhoc requests. But if you use the listener and keep it open the location should slowly refine itself as you move, thanks to Google Play Services it shouldn't take that much battery either...
You shouldn't use getCurrentLocation or getCurrentLocationSync when using this approach.

Related

Network change state not getting detected in Release mode background - Xamarin.iOS

In my application, I have used Xamarin.Essentials to detect network changes in background & fire notifications based on network availability. The code works perfectly on the device & simulator during Debug. However, the Xamarin.Essentials fail to detect connectivity changes in Release mode, especially in the background. The events get triggered when the application reenters into the application (when application becomes ro foreground)
Following is the code I have used
CrossConnectivity.Current.ConnectivityChanged += Current_ConnectivityChanged;
private void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
{
if (_networkService.IsConnected())
{
ShowBannerNotificaiton("Internet", "Available", "data1");
}
else
{
ShowBannerNotificaiton("Internet", "Not Available", "data2");
}
}
Appreciate the solution given

Parsing Beacon Information in didEnterRegion Method of Altbeacon Library

I would like to use the didEnterRegion method in association with the RegionBootstrap or MonitorNotifier in my application. Currently I'm using the RegionBootstrap but perhaps the MonitorNotifier is better for my application.
In particular I'm adding an iBeacon parser to the beaconmanager and then setting "Id1" of a region to look for the UUID portion of my iBeacon and setting "Id2" and "Id3" to Null. Though they are set to Null in the Region, I would like to be able to parse the information from those locations upon entering the didEnterRegion method. I'm using "Id2" (Major) and "Id3" (Minor) to provide random identification parameters of the beacons.
This information along with a portion of the data from the UUID would then be sent in a notification to the phone user. When testing, I'm entering the didEnterRegion method but the data that is provided is only that which matches the set region of "Id1". If someone could provide any insight at all, it would be greatly appreciated!
I would also like to receive the didEnterRegion method for the same iBeacon every 10 seconds, but with testing it appeared that once that particular iBeacon was seen once, didEnterRegion wouldn't get a subsequent call again. Any way to clear that the iBeacon was captured so that subsequent captures could happen?
I'm trying to keep the battery usage as low as possible and when using the scanRecord data from a onNonBeaconLEScan to parse the information, I'm noticing significant battery drain even when setting the foreground and background time "BetweenScanPeriod" to something really large. I really only need to see that the iBeacon entered the region and pull the information, then 10 seconds later do it again.
Intended application flow -
User enters region of beacon with matching UUID (ID1)
Beacon information from ID2 and ID3 are parsed and sent along with ID1 to user via notification
10 seconds later user receives another notification with same data
repeat until person leaves region or iBeacon stops transmitting
The simplest way to get the information you need is to enable ranging in the didDetermineStateForRegion callback:
public void didDetermineStateForRegion(int state, Region region) {
beaconManager.startRangingBeaconsInRegion(region);
beaconManager.addRangeNotifier(this);
}
public void didRangeBeaconsInRegion(Region region, List<Beacon> beacons) {
for (Beacon beacon : beacons) {
Identifier id2 = beacon.getId2();
Identifier id3 = beacon.getId3();
// Now do something with id2 and id3
}
}
The didRangeBeaconsInRegion callback will be made every 1100 ms with default settings, but you can change this to be 10 seconds if you wish with a line like this the first time you access the BeaconManager:
beaconManager.setScanPeriod(10000l);
beaconManager.setBetweenScanPeriod(0l);
In terms of battery, if you want to be getting scan updates every 10 seconds, you will be using a lot of battery, because this means doing almost constant bluetooth scans. In the background, you may wish to back off and do a 10 second scan only once every 5 minutes with this:
beaconManager.setBackgroundScanPeriod(10000l);
beaconManager.setBackgroundBetweenScanPeriod(290000l);
BackgroundPowerSaver powerSaver = new BackgroundPowerSaver();

location based alarm/notification ios

I'm building an iOS app, however I want to get notification which may be a local and simple notification, such that on defined area of location, such that to provided the latitude and longitude to get the area around 200meter and when the user entered in that location, it alerts the notification.
How can I schedule the location based local notification in iOS.
Take a look at what is available in the SetSDK, https://cocoapods.org/pods/SetSDK. It will allow you to get notified whenever the user arrives to a new "location" (as learned on the fly by the sdk) and then just quickly evaluate to see if it is a location you care about. So it would look something like this,
SetSDK.instance.onArrival(to: .any) { newArrival in
/* Compare the new location with the one of interest */
if newArrival.location.distance(from: placeOfInterest) < 200 {
/* do your things here */
}
}
Use a CLRegion in combination with Background Location and your app will be woken up when the user enters that region. From there you can schedule a UILocationNotification for immediate display.

Get current location from the geo fence sample project

I was trying out the Google's Geo fence sample project. I'm getting the entry/exit events correctly. But how can I get the current location of the user from it. I would like to keep track of user location even after entry/exit points. Please help.
The sample project is from the developer portal.
in your broadcastrecievero or service you get a GeofencingEvent , use it to get the triggering position
public class GeofenceTransitionsIntentService extends IntentService {
//[...]
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
// ...
}
Location l = geofencingEvent.getTriggeringLocation()
}
//[...]
}
You'll need can get the user location from the Fused Location Provider in the normal fashion. The full tutorial is here: http://developer.android.com/training/location/retrieve-current.html
But basically, when you receive the geofence event inside your Receiver or Service, get an instance of LocationClient there, connect to it, and in the callback, onConnected(), get the last known location:
Location position = locationClient.getLastLocation();
99.9% of the time, or a little better, you'll find this location to be inside your geofence.
To continue keeping track of user location updates, follow the Receiving Location Updates: http://developer.android.com/training/location/receive-location-updates.html

How to determine orientation of Windows Phone 7 in XNA game?

Similar to this question, but looking for an answer that will work in the context of an XNA game.
How can I determine whether the device is in a landscape or portrait orientation? The answer given in the general question relies upon functionality built into PhoneApplicationPage. AFAIK, you wouldn't normally be using that class within the context of an XNA game on Windows Phone 7.
From Nick Gravelyn: http://forums.xna.com/forums/p/49684/298915.aspx#298915
Accelerometer isn't in the XNA Framework anymore. You can access it through these steps:
Add a reference to Microsoft.Devices.Sensors.dll
Add 'using Microsoft.Devices.Sensors;' to your using statements.
Hook up an event and start reading the accelerometer:
Try this:
try
{
AccelerometerSensor.Default.ReadingChanged += Default_ReadingChanged;
AccelerometerSensor.Default.Start();
}
catch (AccelerometerStartFailedException)
{
}
Add the event handler itself:
Like this:
void Default_ReadingChanged(object sender, AccelerometerReadingAsyncEventArgs e)
{
}
And you're good to go. Keep in mind, though, that accelerometer doesn't work with the emulator so there's no way to really test this without a device. You do need that try/catch because Start will throw an exception in the emulator because it doesn't support accelerometer.
This has changed it seems. In order to hook into the 'reading changed' you have to create an accelerometer, and then start it. The code required can be found at MSDN. Retrieving Accelerometer Input (Windows Phone)
it looks something like this:
#if WINDOWS_PHONE
Accelerometer accelerometer;
try
{
accelerometer = new Accelerometer();
accelerometer.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(a_ReadingChanged);
accelerometer.Start();
}
catch (AccelerometerFailedException e)
{
}
...
}
void a_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
{
//this function is not supported by the window 7 phone emulator
throw new NotImplementedException();
}
#endif
Here's a post from Shawn Hargreaves' Blog
http://blogs.msdn.com/b/shawnhar/archive/2010/07/12/orientation-and-rotation-on-windows-phone.aspx?utm_source=twitterfeed&utm_medium=twitter
If you want to automatically switch between both landscape and portrait orientations as the phone is rotated:
graphics.SupportedOrientations = DisplayOrientation.Portrait |
DisplayOrientation.LandscapeLeft |
DisplayOrientation.LandscapeRight;
Switching between LandscapeLeft and LandscapeRight can be handled automatically with no special help from the game, and is therefore enabled by default. But switching between landscape and portrait alters the backbuffer dimensions (short-and-wide vs. tall-and-thin), which will most likely require you to adjust your screen layout. Not all games will be able to handle this (and some designs only make sense one way up), so dynamic switching between landscape and portrait is only enabled for games that explicitly opt-in by setting SupportedOrientations.

Resources