In fairness Google has simplified the process greatly and claims following this approach improves battery performance in most cases. This makes sense as the Location Service is run as system process to which you subscribe. On the less bright side this approach depends on Google Play Services being installed in the phone.
So in order to implement this solution and make sure your app gracefully handles all possible combination of scenarios there are a few things you need to do.
Google Play Services comprises several services. To get the user current location and request location updates from your Android app you will need to include the play-services-location package.
In order to include this package in your app as a selective dependency of the Google Play Services you need to follow these steps:
If you haven't already done so, download and install Google Play Services from Android Studio's SDK Manager.
Include google() or maven { url "https://maven.google.com" } repository to top level build.gradle
Include play-services-location dependency to app level build.gradle
Your app should verify the required version of the Google Play Services APK is installed in the device. There are two strategies to perform this step:
Delegate the check on the service client object by passing an Activity at time on instatiation*
//this must be an Activity FusedLocationClient client = LocationServices.getFusedLocationProviderClient(this);
Use the GoogleApiAvailibility singlenton service to manually check:
public boolean checkPlayServices(final IcabbiActivity activity) { GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); int resultCode = apiAvailability.isGooglePlayServicesAvailable(context); if (resultCode != ConnectionResult.SUCCESS) { if (apiAvailability.isUserResolvableError(resultCode)) { Dialog playServicesErrorDialog = apiAvailability.getErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST); playServicesErrorDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialogInterface) { activity.finish(); } }); playServicesErrorDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { } }); playServicesErrorDialog.show(); }else { Timber.e(String.format("This device is not supported. Result code:%s", resultCode)); activity.finish(); } return false; } return true; }
Then in your activiy get the intent result
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PermissionHelper.PLAY_SERVICES_RESOLUTION_REQUEST) { if (resultCode != ConnectionResult.SUCCESS) { Timber.e(String.format("This device is not supported. Result code:%s", resultCode)); finish(); } } }
Handle App Permissions
Since Android M permission granting was moved from install time to runtime. This is good for the user and hell for the developer. There is no way around this one. Before accessing the device location you must cofirm you have permission to do so and fail gracefully if you don't.
If you need to get location updates from you app you need to be aware that since Android O, if your app is running in the background the number of requests your app can make to the FusedLocationManager and the LocationsManager are restricted to a few every hour.*.
Every app is different. If you need to request frequent updates you can run your location service as a foreground service*.