Android library project that intends to simplify the usage of location providers with a twist: you can modify the location strategy based in your activity.
The principle behind it is detecting the activity the user is doing (moving in a vehicle, riding a bicycle, walking, running, being still) and based on those results, changing the accuracy for the detection and the sensors used.
All this is aimed to be more battery efficient than the usual location strategies.
Supported Android versions: Android 2.3+
You should add this to your dependencies:
compile 'io.nlopez.smartlocation:library:2.0.7'
For starting the location service, you can perform just one call with a listener.
SmartLocation.getInstance().start(
context,
new SmartLocation.OnLocationUpdatedListener() {
@Override
public void onLocationUpdated(Location location, DetectedActivity detectedActivity) {
// In here you have the location and the activity. Do whatever you want with them!
}
});
You have some different methods to be able to do this in different ways.
This one above is the simplest one, because it would do all the boilerplate stuff for you. But you could also intercept an intent that is launched everytime the location is updated (see below).
For stopping the location (but with a chance to restarting it) you should use the stop method.
SmartLocation.getInstance().stop(context);
For stopping it for good and avoid service leaks, you must call the cleanup method this way.
SmartLocation.getInstance().cleanup(context);
The best practices for using these methods would be:
- Adding the start call on the onResume method of the Activity.
- Adding the stop call on the onPause method of the Activity.
- Adding the cleanup call on the onDestroy method of the Activity.
The Service will also send the information of user's location and current activity via intents.
The default intent that will be broadcasted will be io.nlopez.smartlocation.LOCATION_UPDATED
. You can configure the package by passing a SmartLocationOptions object to the start method but more on that later. You can capture it if you want, but the listener should be enough.
We can customize the update strategy in the options class, both the default behavior and the behavior derived from the activity recognizer. Check out the comments of the UpdateStrategy class for more info. By default, it is set to BEST_EFFORT location, which will perform the best location accuracy without the battery drainage of pure-GPS location strategies.
For example, we will set a typical strategy for a navigation app (for both cars and bicycles) in this code.
SmartLocationOptions options = new SmartLocationOptions();
options.setDefaultUpdateStrategy(UpdateStrategy.BEST_EFFORT);
options.setOnActivityRecognizerUpdatedNewStrategy(new SmartLocationOptions.OnActivityRecognizerUpdated() {
@Override
public UpdateStrategy getUpdateStrategyForActivity(DetectedActivity detectedActivity) {
switch (detectedActivity.getType()) {
case DetectedActivity.IN_VEHICLE:
case DetectedActivity.ON_BICYCLE:
return UpdateStrategy.NAVIGATION;
default:
return UpdateStrategy.BEST_EFFORT;
}
}
});
SmartLocation.getInstance().start(context, options);
We can force the deactivation of the fused location provider strategies (using LocationManager instead) and the Activity Recognizer with some settings. We would want to do this if we wanted to get the speed value from the GPS (thus, using NAVIGATION as UpdateStrategy) and we don't care about the activity the user is performing.
SmartLocationOptions options = new SmartLocationOptions()
.setDefaultUpdateStrategy(UpdateStrategy.NAVIGATION)
.setFusedProvider(false)
.setActivityRecognizer(false);
Of course, they both exist on their own and it is possible to use the Activity Recognizer with a LocationManager based strategy if we wanted to.
Please note that it is allowed to interact with the options object in a fluid fashion.
And we can enable or disable the debug mode. In the debug mode, we would have some feedback in logcat about how it is going with the localization stuff. It is recommended the value is false always for production builds. You could use something like this line.
options.setDebugging(BuildConfig.DEBUG);
If we want to interact with the intents being fired by the service, instead of using the interface provided, you can do it. You can either use the default intent action, io.nlopez.smartlocation.LOCATION_UPDATED
, or set up your own.
options.setPackageName("com.mypackage.name");
With this call, the intent you will want to watch for is com.mypackage.name.LOCATION_UPDATED
.
These permissions will be automatically merged into your AndroidManifest.xml by gradle. There is NO NEED for you to add them to your app, though I'm leaving them here so you know what's happening behind closed doors in your application.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
Forks, patches and other feedback are welcome.
Nacho López @mrmans0n
The MIT License (MIT)
Copyright (c) 2013-2014 Nacho Lopez
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.