Last active
May 30, 2017 07:23
-
-
Save rakshakhegde/3d1952817d42c76aa0f1e053cc465030 to your computer and use it in GitHub Desktop.
If GPS disabled, show dialog to enable GPS and provide location updates: FusedLocationEnabler using Lifecycle from Arch Components
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.rakshakhegde.locationapp | |
import android.app.Activity | |
import android.arch.lifecycle.Lifecycle | |
import android.arch.lifecycle.LifecycleObserver | |
import android.arch.lifecycle.OnLifecycleEvent | |
import android.content.IntentSender | |
import android.location.Location | |
import android.os.Bundle | |
import android.util.Log | |
import com.google.android.gms.common.ConnectionResult | |
import com.google.android.gms.common.api.GoogleApiClient | |
import com.google.android.gms.common.api.ResultCallback | |
import com.google.android.gms.location.* | |
/** | |
* Created by rakshakhegde on 29/05/17. | |
*/ | |
class FusedLocationEnabler(val act: Activity, lifecycle: Lifecycle) : | |
LifecycleObserver, | |
GoogleApiClient.ConnectionCallbacks, | |
GoogleApiClient.OnConnectionFailedListener, | |
LocationListener, | |
ResultCallback<LocationSettingsResult> { | |
private val TAG = "FusedLocationEnabler" | |
/** | |
* Constant used in the location settings dialog. | |
*/ | |
val REQUEST_CHECK_SETTINGS = 0x1 | |
/** | |
* The desired interval for location updates. Inexact. Updates may be more or less frequent. | |
*/ | |
private val UPDATE_INTERVAL_IN_MILLISECONDS: Long = 60 * 1000 | |
/** | |
* The fastest rate for active location updates. Exact. Updates will never be more frequent | |
* than this value. | |
*/ | |
private val FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2 | |
private val mGoogleApiClient by lazy { | |
GoogleApiClient.Builder(act) | |
.addConnectionCallbacks(this) | |
.addOnConnectionFailedListener(this) | |
.addApi(LocationServices.API) | |
.build() | |
} | |
private val mLocationRequest: LocationRequest by lazy { | |
LocationRequest().apply { | |
// Sets the desired interval for active location updates. This interval is | |
// inexact. You may not receive updates at all if no location sources are available, or | |
// you may receive them slower than requested. You may also receive updates faster than | |
// requested if other applications are requesting location at a faster interval. | |
interval = UPDATE_INTERVAL_IN_MILLISECONDS | |
// Sets the fastest rate for active location updates. This interval is exact, and your | |
// application will never receive updates faster than this value. | |
fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS | |
priority = LocationRequest.PRIORITY_HIGH_ACCURACY | |
} | |
} | |
private val mLocationSettingsRequest: LocationSettingsRequest by lazy { | |
LocationSettingsRequest.Builder() | |
.addLocationRequest(mLocationRequest) | |
.build() | |
} | |
init { | |
lifecycle.addObserver(this@FusedLocationEnabler) | |
} | |
@OnLifecycleEvent(Lifecycle.Event.ON_START) | |
fun onStart() { | |
mGoogleApiClient.connect() | |
} | |
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME) | |
fun onResume() { | |
if (mGoogleApiClient.isConnected) { | |
startLocationUpdates() | |
checkLocationSettings() | |
} | |
} | |
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) | |
fun onPause() { | |
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object. | |
if (mGoogleApiClient.isConnected) { | |
stopLocationUpdates() | |
} | |
} | |
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) | |
fun onStop() { | |
mGoogleApiClient.disconnect() | |
} | |
private fun checkLocationSettings() { | |
val result = LocationServices.SettingsApi.checkLocationSettings( | |
mGoogleApiClient, | |
mLocationSettingsRequest | |
) | |
result.setResultCallback(this) | |
} | |
/** | |
* Runs when a GoogleApiClient object successfully connects. | |
*/ | |
override fun onConnected(connectionHint: Bundle?) { | |
Log.i(TAG, "Connected to GoogleApiClient") | |
startLocationUpdates() | |
checkLocationSettings() | |
} | |
override fun onConnectionSuspended(cause: Int) { | |
Log.i(TAG, "Connection suspended") | |
} | |
override fun onConnectionFailed(result: ConnectionResult) { | |
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in | |
// onConnectionFailed. | |
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.errorCode) | |
} | |
/** | |
* Callback that fires when the location changes. | |
*/ | |
override fun onLocationChanged(location: Location?) { | |
Log.i(TAG, "onLocationChanged $location") | |
} | |
/** | |
* The callback invoked when | |
* [com.google.android.gms.location.SettingsApi.checkLocationSettings] is called. Examines the | |
* [com.google.android.gms.location.LocationSettingsResult] object and determines if | |
* location settings are adequate. If they are not, begins the process of presenting a location | |
* settings dialog to the user. | |
*/ | |
override fun onResult(locationSettingsResult: LocationSettingsResult) { | |
val status = locationSettingsResult.status | |
when (status.statusCode) { | |
LocationSettingsStatusCodes.SUCCESS -> { | |
Log.i(TAG, "All location settings are satisfied.") | |
startLocationUpdates() | |
} | |
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> { | |
Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to" + | |
" upgrade location settings.") | |
try { | |
// Show the dialog by calling startResolutionForResult(), and check the result | |
// in onActivityResult(). | |
status.startResolutionForResult(act, REQUEST_CHECK_SETTINGS) | |
} catch (e: IntentSender.SendIntentException) { | |
Log.i(TAG, "Location status PendingIntent unable to execute request") | |
} | |
} | |
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> | |
Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog not created.") | |
} | |
} | |
/** | |
* Requests location updates from the FusedLocationApi. | |
*/ | |
fun startLocationUpdates() { | |
LocationServices.FusedLocationApi.requestLocationUpdates( | |
mGoogleApiClient, | |
mLocationRequest, | |
this | |
).setResultCallback { status -> | |
println("startLocationUpdates() ${status.statusMessage}") | |
} | |
} | |
/** | |
* Removes location updates from the FusedLocationApi. | |
*/ | |
private fun stopLocationUpdates() { | |
// It is a good practice to remove location requests when the activity is in a paused or | |
// stopped state. Doing so helps battery performance and is especially | |
// recommended in applications that request frequent location updates. | |
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this@FusedLocationEnabler) | |
.setResultCallback { status -> | |
println("stopLocationUpdates() ${status.statusMessage}") | |
} | |
} | |
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { | |
when (requestCode) { | |
// Check for the integer request code originally supplied to startResolutionForResult(). | |
REQUEST_CHECK_SETTINGS -> when (resultCode) { | |
Activity.RESULT_OK -> { | |
Log.i(TAG, "User agreed to make required location settings changes") | |
startLocationUpdates() | |
} | |
Activity.RESULT_CANCELED -> | |
Log.i(TAG, "User chose not to make required location settings changes") | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.rakshakhegde.locationapp | |
import android.app.Activity | |
import android.arch.lifecycle.LifecycleActivity | |
class LocationMapActivity : LifecycleActivity() { | |
private val fusedLocationEnabler = FusedLocationEnabler(this@LocationMapActivity, lifecycle) | |
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { | |
fusedLocationEnabler.onActivityResult(requestCode, resultCode, data) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// In case you cannot use LifecycleActivity directly, implement interface LifecycleRegistryOwner | |
package me.rakshakhegde.locationapp | |
import android.arch.lifecycle.LifecycleRegistry | |
import android.arch.lifecycle.LifecycleRegistryOwner | |
abstract class SuperActivity : LifecycleRegistryOwner { | |
private val mRegistry = LifecycleRegistry(this@SuperActivity) | |
override fun getLifecycle() = mRegistry | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment