Last active
April 21, 2017 05:09
-
-
Save simform-solutions/d0243efb151214ffe0785432d402bd7e to your computer and use it in GitHub Desktop.
LocationUpdateFragment - Android
This file contains hidden or 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 com.places; | |
import android.app.Activity; | |
import android.app.Fragment; | |
import android.content.Intent; | |
import android.content.IntentSender; | |
import android.location.Location; | |
import android.os.Bundle; | |
import android.support.annotation.Nullable; | |
import android.util.Log; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.api.GoogleApiClient; | |
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; | |
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; | |
import com.google.android.gms.common.api.PendingResult; | |
import com.google.android.gms.common.api.ResultCallback; | |
import com.google.android.gms.common.api.Status; | |
import com.google.android.gms.location.LocationListener; | |
import com.google.android.gms.location.LocationRequest; | |
import com.google.android.gms.location.LocationServices; | |
import com.google.android.gms.location.LocationSettingsRequest; | |
import com.google.android.gms.location.LocationSettingsResult; | |
import com.google.android.gms.location.LocationSettingsStatusCodes; | |
import java.text.DateFormat; | |
import java.util.Date; | |
/** | |
* Using location settings. | |
* <p/> | |
* Uses the {@link com.google.android.gms.location.SettingsApi} to ensure that the device's system | |
* settings are properly configured for the app's location needs. When making a request to | |
* Location services, the device's system settings may be in a state that prevents the app from | |
* obtaining the location data that it needs. For example, GPS or Wi-Fi scanning may be switched | |
* off. The {@code SettingsApi} makes it possible to determine if a device's system settings are | |
* adequate for the location request, and to optionally invoke a dialog that allows the user to | |
* enable the necessary settings. | |
* <p/> | |
* This sample allows the user to request location updates using the ACCESS_FINE_LOCATION setting | |
* (as specified in AndroidManifest.xml). The sample requires that the device has location enabled | |
* and set to the "High accuracy" mode. If location is not enabled, or if the location mode does | |
* not permit high accuracy determination of location, the activity uses the {@code SettingsApi} | |
* to invoke a dialog without requiring the developer to understand which settings are needed for | |
* different Location requirements. | |
*/ | |
/** | |
* Refrence : | |
* This class is made from google samples Android-play-location | |
* https://github.com/googlesamples/android-play-location | |
*/ | |
/** | |
* How to use? | |
* | |
* Setp - 1 | |
* your fragment needs to exetend with this fragment. | |
* You need to ask for location permission (ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION) | |
* where you want to get location. | |
* | |
* Step - 2 | |
* once you extend this class, you'll have to implement | |
* abstract method void onLocation(Location location) of this class. | |
* | |
* Step - 3 | |
* if(location_permission_granted){ | |
* //call these 3 method of LocationUpdateFragment. | |
* startLocation(); | |
* connect(); | |
* startUpdate(); | |
* } | |
* | |
* Step - 4 | |
* At end, You need to override onActivityResult() on your activity and | |
* need to pass to your fragment by below method | |
* | |
* protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
* super.onActivityResult(requestCode, resultCode, data); | |
* Fragment fragment = getFragmentManager().findFragmentById(R.id.YOUR_CONTAINER_ID); | |
* fragment.onActivityResult(requestCode, resultCode, data); | |
* } | |
* | |
* | |
*/ | |
public abstract class LocationUpdateFragment extends Fragment implements | |
ConnectionCallbacks, | |
OnConnectionFailedListener, | |
LocationListener, | |
ResultCallback<LocationSettingsResult> { | |
protected static final String TAG = "LocationActivity"; | |
/** | |
* Constant used in the location settings dialog. | |
*/ | |
protected static final int REQUEST_CHECK_SETTINGS = 0x1; | |
/** | |
* The desired interval for location updates. Inexact. Updates may be more or less frequent. | |
*/ | |
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000; | |
/** | |
* The fastest rate for active location updates. Exact. Updates will never be more frequent | |
* than this value. | |
*/ | |
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = | |
UPDATE_INTERVAL_IN_MILLISECONDS / 2; | |
// Keys for storing activity state in the Bundle. | |
protected final static String KEY_REQUESTING_LOCATION_UPDATES = "requesting-location-updates"; | |
protected final static String KEY_LOCATION = "location"; | |
protected final static String KEY_LAST_UPDATED_TIME_STRING = "last-updated-time-string"; | |
/** | |
* Provides the entry point to Google Play services. | |
*/ | |
protected GoogleApiClient mGoogleApiClient; | |
/** | |
* Stores parameters for requests to the FusedLocationProviderApi. | |
*/ | |
protected LocationRequest mLocationRequest; | |
/** | |
* Stores the types of location services the client is interested in using. Used for checking | |
* settings to determine if the device has optimal location settings. | |
*/ | |
protected LocationSettingsRequest mLocationSettingsRequest; | |
/** | |
* Represents a geographical location. | |
*/ | |
protected Location mCurrentLocation; | |
/** | |
* Tracks the status of the location updates request. Value changes when the user presses the | |
* Start Updates and Stop Updates buttons. | |
*/ | |
protected Boolean mRequestingLocationUpdates; | |
/** | |
* Time when the location was updated represented as a String. | |
*/ | |
protected String mLastUpdateTime; | |
@Nullable | |
@Override | |
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { | |
return super.onCreateView(inflater, container, savedInstanceState); | |
} | |
@Override | |
public void onActivityCreated(Bundle savedInstanceState) { | |
super.onActivityCreated(savedInstanceState); | |
// Set labels. | |
/*mLatitudeLabel = getResources().getString(R.string.latitude_label); | |
mLongitudeLabel = getResources().getString(R.string.longitude_label); | |
mLastUpdateTimeLabel = getResources().getString(R.string.last_update_time_label);*/ | |
mRequestingLocationUpdates = false; | |
mLastUpdateTime = ""; | |
// Update values using data stored in the Bundle. | |
updateValuesFromBundle(savedInstanceState); | |
} | |
protected void startLocation(){ | |
// Kick off the process of building the GoogleApiClient, LocationRequest, and | |
// LocationSettingsRequest objects. | |
buildGoogleApiClient(); | |
createLocationRequest(); | |
buildLocationSettingsRequest(); | |
checkLocationSettings(); | |
} | |
/** | |
* Updates fields based on data stored in the bundle. | |
* | |
* @param savedInstanceState The activity state saved in the Bundle. | |
*/ | |
private void updateValuesFromBundle(Bundle savedInstanceState) { | |
if (savedInstanceState != null) { | |
// Update the value of mRequestingLocationUpdates from the Bundle, and make sure that | |
// the Start Updates and Stop Updates buttons are correctly enabled or disabled. | |
if (savedInstanceState.keySet().contains(KEY_REQUESTING_LOCATION_UPDATES)) { | |
mRequestingLocationUpdates = savedInstanceState.getBoolean( | |
KEY_REQUESTING_LOCATION_UPDATES); | |
} | |
// Update the value of mCurrentLocation from the Bundle and update the UI to show the | |
// correct latitude and longitude. | |
if (savedInstanceState.keySet().contains(KEY_LOCATION)) { | |
// Since KEY_LOCATION was found in the Bundle, we can be sure that mCurrentLocation | |
// is not null. | |
mCurrentLocation = savedInstanceState.getParcelable(KEY_LOCATION); | |
} | |
// Update the value of mLastUpdateTime from the Bundle and update the UI. | |
if (savedInstanceState.keySet().contains(KEY_LAST_UPDATED_TIME_STRING)) { | |
mLastUpdateTime = savedInstanceState.getString(KEY_LAST_UPDATED_TIME_STRING); | |
} | |
} | |
} | |
/** | |
* Builds a GoogleApiClient. Uses the {@code #addApi} method to request the | |
* LocationServices API. | |
*/ | |
protected synchronized void buildGoogleApiClient() { | |
Log.i(TAG, "Building GoogleApiClient"); | |
mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) | |
.addConnectionCallbacks(this) | |
.addOnConnectionFailedListener(this) | |
.addApi(LocationServices.API) | |
.build(); | |
} | |
/** | |
* Sets up the location request. Android has two location request settings: | |
* {@code ACCESS_COARSE_LOCATION} and {@code ACCESS_FINE_LOCATION}. These settings control | |
* the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in | |
* the AndroidManifest.xml. | |
* <p/> | |
* When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update | |
* interval (5 seconds), the Fused Location Provider API returns location updates that are | |
* accurate to within a few feet. | |
* <p/> | |
* These settings are appropriate for mapping applications that show real-time location | |
* updates. | |
*/ | |
protected void createLocationRequest() { | |
mLocationRequest = new LocationRequest(); | |
// 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. | |
mLocationRequest.setInterval(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. | |
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); | |
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); | |
} | |
/** | |
* Uses a {@link com.google.android.gms.location.LocationSettingsRequest.Builder} to build | |
* a {@link com.google.android.gms.location.LocationSettingsRequest} that is used for checking | |
* if a device has the needed location settings. | |
*/ | |
protected void buildLocationSettingsRequest() { | |
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); | |
builder.addLocationRequest(mLocationRequest); | |
mLocationSettingsRequest = builder.build(); | |
} | |
/** | |
* Check if the device's location settings are adequate for the app's needs using the | |
* {@link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient, | |
* LocationSettingsRequest)} method, with the results provided through a {@code PendingResult}. | |
*/ | |
protected void checkLocationSettings() { | |
PendingResult<LocationSettingsResult> result = | |
LocationServices.SettingsApi.checkLocationSettings( | |
mGoogleApiClient, | |
mLocationSettingsRequest | |
); | |
result.setResultCallback(this); | |
} | |
/** | |
* The callback invoked when | |
* {@link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient, | |
* LocationSettingsRequest)} is called. Examines the | |
* {@link 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 | |
public void onResult(LocationSettingsResult locationSettingsResult) { | |
final Status status = locationSettingsResult.getStatus(); | |
switch (status.getStatusCode()) { | |
case LocationSettingsStatusCodes.SUCCESS: | |
Log.i(TAG, "All location settings are satisfied."); | |
startLocationUpdates(); | |
break; | |
case 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(getActivity(), REQUEST_CHECK_SETTINGS); | |
} catch (IntentSender.SendIntentException e) { | |
Log.i(TAG, "PendingIntent unable to execute request."); | |
} | |
break; | |
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: | |
Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog " + | |
"not created."); | |
break; | |
} | |
} | |
@Override | |
public void onActivityResult(int requestCode, int resultCode, Intent data) { | |
switch (requestCode) { | |
// Check for the integer request code originally supplied to startResolutionForResult(). | |
case REQUEST_CHECK_SETTINGS: | |
switch (resultCode) { | |
case Activity.RESULT_OK: | |
Log.i(TAG, "User agreed to make required location settings changes."); | |
startLocationUpdates(); | |
break; | |
case Activity.RESULT_CANCELED: | |
Log.i(TAG, "User chose not to make required location settings changes."); | |
break; | |
} | |
break; | |
} | |
} | |
/** | |
* Handles the Start Updates button and requests start of location updates. Does nothing if | |
* updates have already been requested. | |
*/ | |
public void startUpdatesButtonHandler(View view) { | |
} | |
/** | |
* Handles the Stop Updates button, and requests removal of location updates. | |
*/ | |
public void stopUpdatesButtonHandler(View view) { | |
// 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. | |
stopLocationUpdates(); | |
} | |
/** | |
* Requests location updates from the FusedLocationApi. | |
*/ | |
protected void startLocationUpdates() { | |
LocationServices.FusedLocationApi.requestLocationUpdates( | |
mGoogleApiClient, | |
mLocationRequest, | |
this | |
).setResultCallback(new ResultCallback<Status>() { | |
@Override | |
public void onResult(Status status) { | |
mRequestingLocationUpdates = true; | |
} | |
}); | |
} | |
/** | |
* Removes location updates from the FusedLocationApi. | |
*/ | |
protected void 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 | |
).setResultCallback(new ResultCallback<Status>() { | |
@Override | |
public void onResult(Status status) { | |
mRequestingLocationUpdates = false; | |
} | |
}); | |
} | |
protected void connect(){ | |
if(mGoogleApiClient!=null) | |
mGoogleApiClient.connect(); | |
} | |
protected void startUpdate(){ | |
// Within {@code onPause()}, we pause location updates, but leave the | |
// connection to GoogleApiClient intact. Here, we resume receiving | |
// location updates if the user has requested them. | |
if (mGoogleApiClient!=null && mGoogleApiClient.isConnected() && mRequestingLocationUpdates) { | |
startLocationUpdates(); | |
} | |
} | |
@Override | |
public void onStart() { | |
super.onStart(); | |
connect(); | |
} | |
@Override | |
public void onResume() { | |
super.onResume(); | |
startUpdate(); | |
} | |
@Override | |
public void onPause() { | |
super.onPause(); | |
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object. | |
if (mGoogleApiClient!=null && mGoogleApiClient.isConnected()) { | |
stopLocationUpdates(); | |
} | |
} | |
@Override | |
public void onStop() { | |
super.onStop(); | |
if(mGoogleApiClient!=null) | |
mGoogleApiClient.disconnect(); | |
} | |
/** | |
* Runs when a GoogleApiClient object successfully connects. | |
*/ | |
@Override | |
public void onConnected(Bundle connectionHint) { | |
Log.i(TAG, "Connected to GoogleApiClient"); | |
// If the initial location was never previously requested, we use | |
// FusedLocationApi.getLastLocation() to get it. If it was previously requested, we store | |
// its value in the Bundle and check for it in onCreate(). We | |
// do not request it again unless the user specifically requests location updates by pressing | |
// the Start Updates button. | |
// | |
// Because we cache the value of the initial location in the Bundle, it means that if the | |
// user launches the activity, | |
// moves to a new location, and then changes the device orientation, the original location | |
// is displayed as the activity is re-created. | |
if (mCurrentLocation == null) { | |
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); | |
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); | |
} | |
} | |
/** | |
* Callback that fires when the location changes. | |
*/ | |
@Override | |
public void onLocationChanged(Location location) { | |
mCurrentLocation = location; | |
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); | |
onLocation(location); | |
} | |
@Override | |
public void onConnectionSuspended(int cause) { | |
Log.i(TAG, "Connection suspended"); | |
} | |
@Override | |
public void onConnectionFailed(ConnectionResult result) { | |
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in | |
// onConnectionFailed. | |
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); | |
} | |
/** | |
* Stores activity data in the Bundle. | |
*/ | |
public void onSaveInstanceState(Bundle savedInstanceState) { | |
savedInstanceState.putBoolean(KEY_REQUESTING_LOCATION_UPDATES, mRequestingLocationUpdates); | |
savedInstanceState.putParcelable(KEY_LOCATION, mCurrentLocation); | |
savedInstanceState.putString(KEY_LAST_UPDATED_TIME_STRING, mLastUpdateTime); | |
super.onSaveInstanceState(savedInstanceState); | |
} | |
abstract void onLocation(Location location); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment