Making the Fused Location Provider LocationClient easier to use - android

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 */
});

Related

Getting user location with minimal impact for battery on Android

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.

Why use GoogleAPIClient to request location updates?

I noticed that it's possible to request location updates in (at least) two different ways.
Using GoogleAPIClient:
// Callback for when the GoogleAPIClient is connected
#Override
public void onConnected(Bundle connectionHint) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
Using LocationManager:
LocationManager locationManager = (LocationManager) getActivity().
getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 0, locationListener);
Google seems to promote method 1 in their tutorial "Receiving Location Updates". It's unclear to me what the benefit of method 1 is, because method 2 is working just as fine for me (I'm using both methods in two different places in an app).
Good news, from Google Play Services version 11.0, no need to connect GoogleApiClient
https://android-developers.googleblog.com/2017/06/reduce-friction-with-new-location-apis.html
You don't have to handle callbacks and states(connected, connecting), just request/remove location updates, similar taste of LocationManager.
The new method to get location updates is to use Fused Location Provider in android.
The best thing about Fused location provider API is that you not need to worry about location updates it gives you always latest and accurate location and updates location after a interval or on location change .
One more thing about Fused location provider API is you don't need to think about best location provider because it automatically choose best one suited for your hardware of your android device.
Here is a YouTube Video in I/O 2013, which may provide more details.

Android : LocationManager vs Google Play Services

I want to build an app that centers around getting the user's current location and then find points of interest(such as bars,restaurants,etc) that are close to him/her via the Google Places API.
Upon searching the web for a place to start I came across some tutorials that use the LocationManager class and some others that use Google Play Services in order to find the users location.
On first sight both of them do the same thing, but since I am new to this I got a little confused and I don't know which method suits my needs the best. So, I want to ask you :
What are the differences between these two methods of finding locations (if there are any) ?
User Location on Android
Getting the user’s location on Android is a little less straightforward than on iOS. To start the confusion, there are two totally different ways you can do it. The first is using Android APIs from android.location.LocationListener, and the second is using Google Play Services APIs com.google.android.gms.location.LocationListener. Let’s go through both of them.
Android’s Location API
The Android’s location APIs use three different providers to get location -
LocationManager.GPS_PROVIDER — This provider determines location using satellites. Depending on conditions, this provider may take a while to return a location fix.
LocationManager.NETWORK_PROVIDER — This provider determines location based on availability of cell tower and WiFi access points. Results are retrieved by means of a network lookup.
LocationManager.PASSIVE_PROVIDER — This provider will return locations generated by other providers. You passively receive location updates when other applications or services request them without actually requesting the locations yourself.
The gist of it is that you get an object of LocationManager from the system, implement the LocationListener, and call the requestLocationUpdates on the LocationManager.
Here’s a code snippet:
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
Google’s API Guide on Location Strategies explains the code pretty nicely. But they also mention that in most cases, you’ll get better battery performance, as well as more appropriate accuracy, by using the Google Location Services API instead. Now the confusion starts!
Google’s Location Services API
Google’s Location Services API is a part of the Google Play Services APK (here’s how to set it up) . They’re built on top of Android’s API. These APIs provide a “Fused Location Provider” instead of the providers mentioned above. This provider automatically chooses what underlying provider to use, based on accuracy, battery usage, etc. It is fast because you get location from a system-wide service that keeps updating it. And you can use more advanced features such as geofencing.
To use the Google’s Location Services, your app needs to connect to the GooglePlayServicesClient. To connect to the client, your activity (or fragment, or so) needs to implement GooglePlayServicesClient.ConnectionCallbacks and GooglePlayServicesClient.OnConnectionFailedListener interfaces.
Here’s a sample code:
public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
LocationClient locationClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
locationClient = new LocationClient(this, this, this);
}
#Override
public void onConnected(Bundle bundle) {
Location location = locationClient.getLastLocation() ;
Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show();
}
#Override
public void onDisconnected() {
Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// code to handle failed connection
// this code can be found here — http://developer.android.com/training/location/retrieve-current.html
}
Why is locationClient.getLastLocation() null?
The locationClient.getLastLocation() gets the last known location from the client. However, the Fused Location Provider will only maintain background location if at least one client is connected to it. Once the first client connects, it will immediately try to get a location. If your activity is the first client to connect and you call getLastLocation() right away in onConnected(), that might not be enough time for the first location to come in. This will result in location being null.
To solve this issue, you have to wait (indeterminately) till the provider gets the location and then call getLastLocation(), which is impossible to know. Another (better) option is to implement the com.google.android.gms.location.LocationListener interface to receive periodic location updates (and switch it off once you get the first update).
public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
// . . . . . . . . more stuff here
LocationRequest locationRequest;
LocationClient locationClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
// . . . . other initialization code
locationClient = new LocationClient(this, this, this);
locationRequest = new LocationRequest();
// Use high accuracy
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the update interval to 5 seconds
locationRequest.setInterval(UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
locationRequest.setFastestInterval(FASTEST_INTERVAL);
}
// . . . . . . . . other methods
#Override
public void onConnected(Bundle bundle) {
Location location = locationClient.getLastLocation();
if (location == null)
locationClient.requestLocationUpdates(locationRequest, this);
else
Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
// . . . . . . . . other methods
#Override
public void onLocationChanged(Location location) {
locationClient.removeLocationUpdates(this);
// Use the location here!!!
}
In this code, you’re checking if the client already has the last location (in onConnected). If not, you’re requesting for location updates, and switching off the requests (in onLocationChanged() callback) as soon as you get an update.
Note that the locationClient.requestLocationUpdates(locationRequest, this); has to be inside the onConnected callback, or else you will get an IllegalStateException because you will be trying to request for locations without connected to the Google Play Services Client.
User has disabled Location Services
Many times, the user would have location services disabled (to save battery, or privacy reasons). In such a case, the code above will still request for location updates, but onLocationChanged will never get called. You can stop the requests by checking if the user has disabled the location services.
If your app requires them to enable location services, you would want to show a message or a toast. Unfortunately, there is no way of checking if the user has disabled location services in Google’s Location Services API. For this, you will have to resort back to Android’s API.
In your onCreate method:
LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationEnabled = false;
Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show();
}
else locationEnabled = true;
And use the locationEnabled flag in your onConnected method like this:
if (location != null) {
Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
else if (location == null && locationEnabled) {
locationClient.requestLocationUpdates(locationRequest, this);
}
UPDATE
Document is updated, LocationClient is removed and the api supports to enable GPS with one click from dialog:
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
}
});
task.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
Link https://developer.android.com/training/location/change-location-settings#prompt
New location client: FusedLocationProviderClient
private FusedLocationProviderClient fusedLocationClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
It is recommended to go through https://developer.android.com/training/location before doing any location tasks.
In my experience, "more appropriate accuracy" doesn't mean better by any means. Unless I'm missing something, if you want to make sure GPS is used, LocationManager is the only way to go. We track vehicles with our app and, again, unless I'm missing something, Google Play Services provides some very inaccurate locations quite often.
I have been using the Google Location Services API for quite a while. It does have advantages, since it encapsulates the complexity of having several sources for determining positions. However it encapsulates too heavily, so that when you get a strange position, you have no way to determine where that strange position came from.
In real life I have had several freak values pop up, being 10's of kilometers away from the actual position. The only explanation is that these crazy locations stem from errors in Googles Wi-Fi or NWK databases - errors which will always be there, since Wi-Fi and Network topologies change every day. But unfortunately (and surprisingly) the API gives you no information as to how an individual position was derived.
This leaves you with the problems of having to filter out freak values based on plausibility checking on speed, acceleration, bearing etc.
... or go back to the good old framework API and use GPS only, which is what I decided to do until Google improves the fused API.
You should use the Google Play Services location api instead of LocationManager. According to the docs:
The Google Play services location APIs are preferred over the Android
framework location APIs (android.location) as a way of adding location
awareness to your app. If you are currently using the Android
framework location APIs, you are strongly encouraged to switch to the
Google Play services location APIs as soon as possible.
As to why to switch, Google says this:
The Google Location Services API, part of Google Play Services,
provides a more powerful, high-level framework that automatically
handles location providers, user movement, and location accuracy. It
also handles location update scheduling based on power consumption
parameters you provide. In most cases, you'll get better battery
performance, as well as more appropriate accuracy, by using the
Location Services API.
The Google Location Services API, part of Google Play Services, provides a more powerful, high-level framework that automatically handles location providers, user movement, and location accuracy. It also handles location update scheduling based on power consumption parameters you provide. In most cases, you’ll get better battery performance, as well as more appropriate accuracy, by using the Location Services API.
More detailed diffferences between the two apis Google Play Service Location API and Android Framework Location API can be found here
Diffferences between the two apis Google Play Service Location API and Android Framework Location API based on GPS service
FusedLocationProviderClient
For the 1st fetch, the location must not be null(i.e: Some other app need to update the Lastknown location in the GoogleplayService database. if it is null, need work around)
For the next sequential Fetch, it uses requestLocationUpdates() method to fetch the location.
The location fetch is only based on locationRequest.setInterval(milliseconds)and setFastestInterval(milliseconds), not based on user location change
The LatLng value returned has contain only 7 decimal values (e.g: 11.9557996, 79.8234599), not as accurate
Recommended, when your app requirement takes current location distance negligible of (50 - 100 meters accuracy)
Effective in Battery usage.
LocationManager Api
The user location fetch is invoked using locationManager.requestLocationUpdates()
The location fetch based on user location change and time intervals locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, milliseconds, mindistance, Mylocationlistener)
The LatLng value returned has contain 14 decimal values (e.g: 11.94574594963342 79.81166719458997) accurate location values
Recommended for location based app, when needs more accuracy even in meters.
Battery usage is based on fetch interval and fetch distance.
Yes, the Google Play Services Location Services API can give very misleading Location info. WiFi modems get moved, WiFi modems get updated with incorrect location information (ie if location is spoofed by an Android device that updates the WiFi modem's location) and there are a host of other circumstances that can result in incorrect Location data from WiFi modem triangulation. In all our apps where precise Location is mandatory, we use GPS only.
Android Location
LocationManager - Context.getSystemService(Context.LOCATION_SERVICE)
ACCESS_COARSE_LOCATION - provide less accurate location(city block) but faster and does not drain a battery so much
NETWORK_PROVIDER - uses cell towers, wifi access points
PASSIVE_PROVIDER - subscribes on location updates when somebody else in the system uses another providers
ACCESS_FINE_LOCATION - provides better and accurate location(up to few meters). Uses the same providers as ACCESS_COARSE_LOCATION
GPS_PROVIDER - satellites are used
Google API Location Services - GoogleApiClient based on Google Play Services. High level API with access to location events which go through the system. It has better battery performance but could not be installed on some devices
Fused Location Provider - automatically select an appropriate provider based on your needs and device conditions
Adding to the accepted answer, when enabling GPS through AlertDialog solution provided by Google. The implementation with ActivityResultContract is as follows:
// Global Activity Scope
ActivityResultLauncher<IntentSenderRequest> gpsRequestLauncher = registerForActivityResult(
new ActivityResultContracts.StartIntentSenderForResult(), callback -> {
if(callback.getResultCode() == RESULT_CANCELED) {
// Request Cancelled
} else {
// GPS Enabled
}
});
Since the code from documentation is outdated with deprecation of onActivityResults
task.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
IntentSenderRequest request = new IntentSenderRequest.Builder(
e.resolution).build();
gpsRequestLauncher.launch(request);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});

Android Location Update Clarification

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);
}
}
}
};

How to avoid use of GPS using LocationClient of Google Play Services?

I have an app that runs in background and I want to avoid use of GPS.
According to official doc LocationRequest API:
(...) Applications cannot specify the exact location sources, such as GPS, that are used by the LocationClient. (...)
Is it really impossible to prevent the app from using GPS when using Google Play Services Fused Location Provider?
In my case, I know the Wi-Fi is always ON and it should be enough to retrieve a good position using NETWORK_PROVIDER. May I use the old-school location retriever to avoid use of GPS?
You're looking for LocationManager, which provides much more control, but requires far more code. If you don't request ACCESS_FINE_LOCATION permission, the GPS will never be used.
Check out this guide: https://developer.android.com/guide/topics/location/strategies.html
It should be noted, if you designate ACCESS_COARSE_LOCATION with LocationRequest, it will intentionally obfuscate the location result.
Location requests from applications with ACCESS_COARSE_LOCATION and
not ACCESS_FINE_LOCATION will be automatically throttled to a slower
interval, and the location object will be obfuscated to only show a
coarse level of accuracy.

Categories

Resources