Am working with the location update application which will update the user location periodically to the server.
I have used the fused location provider to get the location update. I have referred the following link Android Location Update.
Regarding the location update I have following clarifications,
1) I requested Location using Pending Intent. I had given the Time
interval as 5 min in the location request. I am getting the location
information successfully at every 5 min. But my question is "How effectively
Android uses the GPS to get the location - GPS need not to be on for
the whole 5 min". Around 4 min 50 seconds it starts using the GPS to
get the user location. I just want to know how the fused location provider effectively using the GPS.
2) And also I want to know the time taken to fetch the user location
by using available providers. How much time approximately taken by the
android api to get the user location by using fusion location
provider.
3) The Fused Location Provider uses GPS only at the nearest time of given interval to get
the user location. The remaining time the GPS is not usable. Is there
is better solution to switch off the GPs or effective way to use the
GPS to save the mobile battery power.
4) Am giving the time interval as 1 min. Some time am not getting the
location update every one minute. For Example, First minute successfully
I am getting the user location. Then not getting the user location at 2nd Minute. Then 3rd minute
getting fine and so. I have GPS ON and with mobile network available and WiFi
connected.
5) And what is the maximum time interval we can give. Am not finding
any maximum time limit in the document. We can give the minimum time interval as zero. But it is not recommended.
6) And also I want to know the minimum OS support while using this feature. I have referred below link Does Google Activity Recognition work on older versions of Android? Which says Everything in Google Play Services should work back to API level 8(Android 2.3).
Please help me on this. I hope this could help other developer also who are working on Android Location Updates.
Thanks in advance.
I have used the fused location provider API's in our project and it's was really helpful to improve battery usage.Earlier We were using Android's Location framework APi's .
Please read below article which I have prepared ,you can refer the information to implement it in your project.
In simple words, it’s the best way to get location data in Android platform as of now.
GooglePlay Services provide many location APi’s to get the location data(e.g. User’s current location or you can say device’s last known location).
The Fused Location Provider is one of the location APIs in Google Play services.
Prerequisite is that:
1- Google Play services sdk is used as library project(and also Google PlayService is properly installed in your device)
Download and install the Google Play services component from the SDK Manager and add the library to your project.
Import GooglePlayServices lib from android google-play-services_lib in your development project as Library project.
2- You should have an actual device as this APi won’t work in Emulator.
The Fused Location Provider intelligently manages the underlying location technology (GPS/Wi-Fi/Network provider’s connection) and gives us the best location according to our needs.
Why to use
=============
We could choose one of the location providers (network or GPS) and request location updates or set up proximity alert. But there were two main issues with this approach:
1. In case we need to define precise location, we had to switch between network and GPS location providers (as GPS doesn’t work indoors).
2. Proximity alerts were used to notify a user about proximity to a location, and this took its toll on the battery life.
Benefits
==========
1. Simple APIs: Lets us specify high-level needs like “high accuracy” or “low power”, instead of having to worry about location providers.
2. Battery efficient: Minimizes out app’s use of power. Based on all incoming location requests and available sensors, fused location provider chooses the most efficient way to meet those needs.
Steps to use this Api:
=====================
1- Declare the location related permission in the manifest file.
<uses-permission android:name="android.permission.ACCESS_COURSE_LOCATION"/>
Or
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
2. Implement related interfaces and callbacks.
Before we request location updates, we must first implement the interfaces that Location Services uses to communicate connection status to our app:
2.1 com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks: Specifies methods that Location Services calls when a location client is connected or disconnected.
2.2
com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener
3 Connect to Google Play Services
Connecting LocationClient to Google api.To do this , create a LocationClient object (it’s actually instance of GoogleApiClient object) as below:
mLocationClient = new GoogleApiClient.Builder(getApplicationContext())
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
and then call connect() :
mLocationClient.connect();
4- Create an instance of FusedLocationProviderApi by using LocationServices class as below:
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
5- Retrieve the current location
Inside onConnected(Bundle bundle){
Location currentLocation = fusedLocationProviderApi .getLastLocation(mLocationClient);
if (mCurrentLocation != null) {
Log.d(TAG, "last location =" + mCurrentLocation.getLatitude()
+ " - " + mCurrentLocation.getLongitude());
}
}
6- Receive periodic location updates
Create and setup LocationRequest object:
mLocationRequest = new LocationRequest();
private void setLocationParameter() {
// Set the update interval
mLocationRequest.setInterval(Constants.SECONDS_TO_UP);
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the interval ceiling to one minute
mLocationRequest.setFastestInterval(Constants.SECONDS_TO_UP);
// Set the distance to 10 meters.
mLocationRequest.setSmallestDisplacement(Constants.METERS_TO_UP);
}
6- Request for periodic Location updates: To get periodic location updates from Location Services, we send a request using a location client.
LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Utils.locationUpdates = Utils.locationUpdates + 1;
if (Utils.locationUpdates == 1) {
mLocationRequest
.setPriority(LocationRequest.PRIORITY_LOW_POWER);
LocationServices.FusedLocationApi.requestLocationUpdates(
mLocationClient, mLocationRequest, listener);
}
}
}
};
Related
I would like to discuss with everyone, sharing why using location services is not as fast as google-map.
Now, I created two thread location-services:
GoogleApiClient (With LocationServices.API)
Custom own location services with GPS & Network provider
With GoogleAPIClient (LocationServices) I config
PRIORITY_HIGH_ACCURACY
FAST_INTERVAL_FUSED_POSITION (10 sec)
INTERVAL_FUSED_POSITION (60 sec)
With own thread receive location from gps, network with 3 minutes I request get location from gps, network providers.
But sometime My app receive not fast as GoogleMap app. Ex:
When a long time my app can't receive location, open Google Map takes
location right away and re-open My App is ok.
I always noticed google-map gets position in few seconds, and my app
not fast as.
Everyone, who are using location service together discuss, sharing something to improve the speed of locating position.
Try using the Play Services fused location provider and its getLastLocation() method. Documentation is available at https://developer.android.com/training/location/retrieve-current.html.
If location is enabled on your device before your app opens and you use this method, you should get a location fairly quickly.
I'm starting to develop an app that will stay in background forever and detect when a user is staying in a certain location for a while (and then display a notification to invite the user to open the app to obtain informations about that place).
It's something very similar to what Google Maps does when you're in a restaurant and it shows you a notification to check ratings about it.
What I want is to have a minimal impact on device, so location updates should be very "passive", getting the location only when user is not moving and, if possible, recycling location data that is already got by other activities - maybe by Google Maps itself or other location apps that are running on the devices.
This is not a navigation app, so I don't need to have the live fine location but simply the approximate place with the best accuracy and minimal effort, and only if user is not moving.
LocationListener and onLocationChanged seems to be my men, but can I specify that I don't want to trigger device's sensors and only re-use location data when it's available for other scopes? My app should check these informations and then decide to do a reverse geocode if and when they are accurate enough.
Yes, LocationListener and onLocationChanged are your men, though for a passive implementation, there are a few options you can go through.
First you can check for the last known location, maybe compare it in terms of its time; i.e. getTime() and verify whether it is of use to you.
In terms of code, literally...
Google samples, android location has what is relevant for the last location part:
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) {
// Provides a simple way of getting a device's location and is well suited for
// applications that do not require a fine-grained location and that do not need location
// updates. Gets the best and most recent location currently available, which may be null
// in rare cases when a location is not available.
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Further, you can combine it with LocationRequest object, this helps your implementation as you can call it right after trying getLastLocation() and basically have a more reliable arrangement for obtaining location.
// Create the location request
mLocationRequest = LocationRequest.create()
//priority object needs to be set, the following will definitely get results for you
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
//interval updates can be on the lines of 15mins or 30... acc to your requirement
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
// Request location updates
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
i suggest give PRIORITY_NO_POWER a try, could work well in combination with getLastLocation(). These power modes have been added specifically for optimising battery/power consumption and efficiency for retrieving location.
I want to ask if getLastLocation() from FusedLocationProviderApi get Location with HIGH_ACCURACCY or not?
when I read the documentation, it says:
public abstract Location getLastLocation (GoogleApiClient client)
Returns the best most recent location currently available.
If a location is not available, which should happen very rarely, null will be returned. The best accuracy available while respecting the location permissions will be returned.
This method provides a simplified way to get location. It is particularly well suited for applications that do not require an accurate location and that do not want to maintain extra logic for location updates.
does the best means get the most accurate location? or like automatically request last location using LocationRequest.PRIORITY_HIGH_ACCURACY?
getLastLocation will not create a new request to get the current location. It gives already available/saved location based on previous location request.
This already available/saved location details is based on the last location data requested by any client/app on the user's device.
Eg: If user has Google Maps installed and running , it gives you the accurate location of the device. In this case once you start your app and check for last location it will give you location with high accuracy.
In case your device doesn't have Google Maps but another app which requested location updates with low accuracy , your getLastLocation will return that low accuracy location .
I have some code that runs multiple times per second in my app. I'm trying to get my location in every cycle. I am using the following:
Location myLastPos = LocationServices.FusedLocationApi.getLastLocation(googleApiClient)
My app also runs in the background using a PARTIAL_WAKE_LOCK. With the screen on everything seems OK. When I turn the screen off my app still runs normally but I no longer get location updates consistently.
It appears that I get updates much less frequently (often minutes in between updates). I'm checking the timestamp of the location using:
myLastPos.getElapsedRealtimeNanos()
I also found that even when the screen is on I get some strange results. Sometimes I get a few milliseconds between updates, other times I get a few seconds. This is all very concerning. Can someone either help me use FusedLocationApi properly or suggest an alternative. All I really want is to poll the gps directly for lat/long a few times a second without google libraries getting in the way.
The getLastLocation() method just gets the last known location that the device happens to know. The "last known location" here means exactly that: It may not be up-to-date. Locations do come with a time stamp which could be used to asses if the location might still be relevant.
The device doesn't determine its location on its own, but only when some application request the location. So your app is now dependent on other applications requesting location updates.
If you need updates every few seconds, then request regular location updates yourself.
Android documentation recommends the FusedLocationProvider, but the LocationManager is also a perfectly valid option, if there's any reason to avoid the Google Play services.
The basic idea is to first request location updates:
// Using LocationManager as an example.
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Using GPS, requesting location updates as soon as available and even for
// the smallest changes. Here 'this' refers to our LocationListener
// implementation.
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
The updates are then received by a listener:
#Override
public void onLocationChanged(Location location) {
// We received a location update.
// Copy the value from the method parameter to our
// class member variable.
mLocation = location;
}
And when you no longer need the updates you should cancel the request:
mLocationManager.removeUpdates(this);
The approach is very similar for the FusedLocationProvider.
Let's say I have 5 different activities in my app that wish to use LocationClient.getLastLocation() to get the last known location. This seems simple.
Ideally, I would just create a LocationClient in each activity and call getLastLocation(). However, there's some additional work one has to do to connect to the Google Play Services, such as call LocationClient.connect() and handle the onConnected, onDisconnected, and onConnectionFailed callbacks. The documentation is here: https://developer.android.com/training/location/retrieve-current.html
As far as I can tell, each of my five different activities must all handle the lifecycle methods of the LocationClient. They also can't call getLastLocation() right away in onCreate() because the connection for that activity may not have been established yet.
Is there an easy way to simplify the lifecycle of the LocationClient so that getLastLocation() will work right away in any new activity once I get the connection established once for my app?
I have used fused location provider APIs to get periodic location updates. I have implemented it inside a background service (e.g. LocationUpdateService extends Service). Earlier I was using Android Location framework APIs but it's not good for battery usage. Fused Location Provider APIs are the best for efficient battery usage.
I have also prepared a notes of steps which are necessary to implement it (along with other useful information). In simple words, it's the best way to get location data in Android platform as of now. Google Play Services provide many location APIs to get the location data (e.g. user’s current location or you can say device’s last known location).
The Fused Location Provider is one of the location APIs in Google Play services.
These are the prerequisites:
Google Play services SDK is used as library project (and also Google PlayService is properly installed in your device).
Download and install the Google Play services component from the SDK Manager and add the library to your project.
Import the GooglePlayServices library from android google-play-services_lib in your development project as Library project.
You should have an actual device as this API won't work in the emulator.
The Fused Location Provider intelligently manages the underlying location technology (GPS/Wi-Fi/Network provider’s connection) and gives us the best location according to our needs.
Why use it
We could choose one of the location providers (network or GPS) and request location updates or set up proximity alert. But there were two main issues with this approach:
1. In case we need to define precise location, we had to switch between network and GPS location providers (as GPS doesn’t work indoors).
2. Proximity alerts were used to notify a user about proximity to a location, and this took its toll on the battery life.
Benefits
Simple APIs: It let's us specify high-level needs like “high accuracy” or “low power”, instead of having to worry about location providers.
Battery efficient: It minimizes the app power usage. Based on all incoming location requests and available sensors, fused location provider chooses the most efficient way to meet those needs.
Steps to use this API:
Declare the location related permission in the manifest file.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
Or
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Implement related interfaces and callbacks. Before we request location updates, we must first implement the interfaces that Location Services uses to communicate connection status to our app:
com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks: Specifies methods that Location Services calls when a location client is connected or disconnected.
com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener
Connect to Google Play Services, connecting LocationClient to the Google API. To do this, create a LocationClient object (instance of GoogleApiClient) as:
mLocationClient = new GoogleApiClient.Builder(getApplicationContext())
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
And then call mLocationClient.connect();.
Create an instance of FusedLocationProviderApi by using the LocationServices class as:
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
Retrieve the current location inside onConnected(Bundle bundle):
Location currentLocation = fusedLocationProviderApi .getLastLocation(mLocationClient);
if (mCurrentLocation != null) {
Log.d(TAG, "last location = " + mCurrentLocation.getLatitude() +
" - " + mCurrentLocation.getLongitude());
}
Create and setup a LocationRequest object:
mLocationRequest = new LocationRequest();
private void setLocationParameter() {
// Set the update interval
mLocationRequest.setInterval(Constants.SECONDS_TO_UP);
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the interval ceiling to one minute
mLocationRequest.setFastestInterval(Constants.SECONDS_TO_UP);
// Set the distance to 10 meters.
mLocationRequest.setSmallestDisplacement(Constants.METERS_TO_UP);
}
To get periodic location updates from Location Services, we send a request using a location client.
LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Utils.locationUpdates = Utils.locationUpdates + 1;
if (Utils.locationUpdates == 1) {
mLocationRequest .setPriority(LocationRequest.PRIORITY_LOW_POWER);
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, listener);
}
}
};
You can create a service to handle the fused location provider on background, and broadcast the location and state to your activity. Refer to the link https://gist.github.com/blackcj/20efe2ac885c7297a676
You can create a base activity which implements all these methods and then all of your activities will only need to extend this.
For reference check: android how to create my own Activity and extend it?
If you are familiar with the reactive-programming, you have to try the RxLocation library, which wrapped the Fused API into the RX way.
Example:
// Create one instance and share it
RxLocation rxLocation = new RxLocation(context);
LocationRequest locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(5000);
rxLocation.location().updates(locationRequest)
.flatMap(location -> rxLocation.geocoding().fromLocation(location).toObservable())
.subscribe(address -> {
/* do something */
});