Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- String.xml
- <resources>
- <string name="app_name">FusedLocationProviderClientDemo</string>
- <string name="action_settings">Settings</string>
- <string name="latitude_label">Latitude</string>
- <string name="longitude_label">Longitude</string>
- <string name="last_update_time_label">Last location update time</string>
- <string name="start_updates">Start updates</string>
- <string name="stop_updates">Stop updates</string>
- <string name="location_settings_inadequate_warning">The location settings on the device are not
- adequate to run this sample. Fix in Settings.</string>
- <string name="permission_rationale">Location permission is needed for core functionality</string>
- <string name="permission_denied_explanation">Permission was denied, but is needed for core
- functionality.</string>
- <string name="settings">Settings</string>
- </resources>
- -----------------------------------------------
- Manifest permission
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- ---------------------------------------------------------------------------
- build.gradle
- compile 'com.google.android.gms:play-services-location:11.0.0'
- --------------------------------------------------------------------------
- MainActivity.class
- import android.Manifest;
- import android.app.Activity;
- import android.content.Intent;
- import android.content.IntentSender;
- import android.content.pm.PackageManager;
- import android.location.Location;
- import android.net.Uri;
- import android.os.Bundle;
- import android.os.Looper;
- import android.provider.Settings;
- import android.support.annotation.NonNull;
- import android.support.design.widget.Snackbar;
- import android.support.v4.app.ActivityCompat;
- import android.support.v7.app.AppCompatActivity;
- import android.support.v7.widget.Toolbar;
- import android.util.Log;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.View;
- import android.widget.Button;
- import android.widget.TextView;
- import android.widget.Toast;
- import com.google.android.gms.common.api.ApiException;
- import com.google.android.gms.common.api.ResolvableApiException;
- import com.google.android.gms.location.FusedLocationProviderClient;
- import com.google.android.gms.location.LocationCallback;
- import com.google.android.gms.location.LocationRequest;
- import com.google.android.gms.location.LocationResult;
- import com.google.android.gms.location.LocationServices;
- import com.google.android.gms.location.LocationSettingsRequest;
- import com.google.android.gms.location.LocationSettingsResponse;
- import com.google.android.gms.location.LocationSettingsStatusCodes;
- import com.google.android.gms.location.SettingsClient;
- import com.google.android.gms.tasks.OnCompleteListener;
- import com.google.android.gms.tasks.OnFailureListener;
- import com.google.android.gms.tasks.OnSuccessListener;
- import com.google.android.gms.tasks.Task;
- import java.text.DateFormat;
- import java.util.Date;
- import java.util.Locale;
- public class MainActivity extends AppCompatActivity {
- private static final String TAG = MainActivity.class.getSimpleName();
- private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
- private static final int REQUEST_CHECK_SETTINGS = 0x1;
- /**
- * The desired interval for location updates. Inexact. Updates may be more or less frequent.
- */
- private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 5000;
- /**
- * The fastest rate for active location updates. Exact. Updates will never be more frequent than this value.
- */
- private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
- /**
- * Provides access to the Fused Location Provider API.
- */
- private FusedLocationProviderClient mFusedLocationClient;
- /**
- * Provides access to the Location Settings API.
- */
- private SettingsClient mSettingsClient;
- /**
- * Stores parameters for requests to the FusedLocationProviderApi.
- */
- private 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.
- */
- private LocationSettingsRequest mLocationSettingsRequest;
- /**
- * Callback for Location events.
- */
- private LocationCallback mLocationCallback;
- /**
- * Represents a geographical location.
- */
- private Location mCurrentLocation;
- // UI Widgets.
- private Button mStartUpdatesButton;
- private Button mStopUpdatesButton;
- private TextView mLastUpdateTimeTextView;
- private TextView mLatitudeTextView;
- private TextView mLongitudeTextView;
- // Labels.
- private String mLatitudeLabel;
- private String mLongitudeLabel;
- private String mLastUpdateTimeLabel;
- /**
- * Tracks the status of the location updates request. Value changes when the user presses the
- * Start Updates and Stop Updates buttons.
- */
- private Boolean mRequestingLocationUpdates;
- /**
- * Time when the location was updated represented as a String.
- */
- private String mLastUpdateTime;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- // Locate the UI widgets.
- mStartUpdatesButton = (Button) findViewById(R.id.start_updates_button);
- mStopUpdatesButton = (Button) findViewById(R.id.stop_updates_button);
- mLatitudeTextView = (TextView) findViewById(R.id.latitude_text);
- mLongitudeTextView = (TextView) findViewById(R.id.longitude_text);
- mLastUpdateTimeTextView = (TextView) findViewById(R.id.last_update_time_text);
- // 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 = "";
- mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
- mSettingsClient = LocationServices.getSettingsClient(this);
- // Kick off the process of building the LocationCallback, LocationRequest, and
- // LocationSettingsRequest objects.
- createLocationCallback();
- createLocationRequest();
- buildLocationSettingsRequest();
- if (!mRequestingLocationUpdates) {
- mRequestingLocationUpdates = true;
- setButtonsEnabledState();
- startLocationUpdates();
- }
- }
- /**
- * 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.
- */
- private 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);
- }
- /**
- * Creates a callback for receiving location events.
- */
- private void createLocationCallback() {
- mLocationCallback = new LocationCallback() {
- @Override
- public void onLocationResult(LocationResult locationResult) {
- super.onLocationResult(locationResult);
- mCurrentLocation = locationResult.getLastLocation();
- mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
- updateLocationUI();
- }
- };
- }
- /**
- * 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.
- */
- private void buildLocationSettingsRequest() {
- LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
- builder.addLocationRequest(mLocationRequest);
- mLocationSettingsRequest = builder.build();
- }
- /**
- * Handles the Start Updates button and requests start of location updates. Does nothing if
- * updates have already been requested.
- */
- public void startUpdatesButtonHandler(View view) {
- if (!mRequestingLocationUpdates) {
- mRequestingLocationUpdates = true;
- setButtonsEnabledState();
- startLocationUpdates();
- }
- }
- @Override
- protected 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.e(TAG, "User agreed to make required location settings changes.");
- // Nothing to do. startLocationupdates() gets called in onResume again.
- startLocationUpdates();
- break;
- case Activity.RESULT_CANCELED:
- Log.e(TAG, "User chose not to make required location settings changes.");
- startLocationUpdates();
- mRequestingLocationUpdates = false;
- updateUI();
- break;
- }
- break;
- }
- }
- /**
- * Requests location updates from the FusedLocationApi. Note: we don't call this unless location
- * runtime permission has been granted.
- */
- private void startLocationUpdates() {
- // Begin by checking if the device has the necessary location settings.
- mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
- .addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
- @Override
- public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
- Log.e(TAG, "All location settings are satisfied.");
- //noinspection MissingPermission
- mFusedLocationClient.requestLocationUpdates(mLocationRequest,
- mLocationCallback, Looper.myLooper());
- updateUI();
- }
- })
- .addOnFailureListener(this, new OnFailureListener() {
- @Override
- public void onFailure(@NonNull Exception e) {
- int statusCode = ((ApiException) e).getStatusCode();
- switch (statusCode) {
- case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
- Log.e(TAG, "Location settings are not satisfied. Attempting to upgrade " +
- "location settings ");
- try {
- // Show the dialog by calling startResolutionForResult(), and check the
- // result in onActivityResult().
- ResolvableApiException rae = (ResolvableApiException) e;
- rae.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
- } catch (IntentSender.SendIntentException sie) {
- Log.e(TAG, "PendingIntent unable to execute request.");
- }
- break;
- case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
- String errorMessage = "Location settings are inadequate, and cannot be " +
- "fixed here. Fix in Settings.";
- Log.e(TAG, errorMessage);
- Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_LONG).show();
- mRequestingLocationUpdates = false;
- }
- updateUI();
- }
- });
- }
- /**
- * Updates all UI fields.
- */
- private void updateUI() {
- setButtonsEnabledState();
- updateLocationUI();
- }
- /**
- * Disables both buttons when functionality is disabled due to insuffucient location settings.
- * Otherwise ensures that only one button is enabled at any time. The Start Updates button is
- * enabled if the user is not requesting location updates. The Stop Updates button is enabled
- * if the user is requesting location updates.
- */
- private void setButtonsEnabledState() {
- if (mRequestingLocationUpdates) {
- mStartUpdatesButton.setEnabled(false);
- mStopUpdatesButton.setEnabled(true);
- } else {
- mStartUpdatesButton.setEnabled(true);
- mStopUpdatesButton.setEnabled(false);
- }
- }
- /**
- * Sets the value of the UI fields for the location latitude, longitude and last update time.
- */
- private void updateLocationUI() {
- if (mCurrentLocation != null) {
- mLatitudeTextView.setText(String.format(Locale.ENGLISH, "%s: %f", mLatitudeLabel,
- mCurrentLocation.getLatitude()));
- mLongitudeTextView.setText(String.format(Locale.ENGLISH, "%s: %f", mLongitudeLabel,
- mCurrentLocation.getLongitude()));
- mLastUpdateTimeTextView.setText(String.format(Locale.ENGLISH, "%s: %s",
- mLastUpdateTimeLabel, mLastUpdateTime));
- }
- }
- /**
- * Removes location updates from the FusedLocationApi.
- */
- private void stopLocationUpdates() {
- if (!mRequestingLocationUpdates) {
- Log.d(TAG, "stopLocationUpdates: updates never requested, no-op.");
- return;
- }
- // 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.
- mFusedLocationClient.removeLocationUpdates(mLocationCallback)
- .addOnCompleteListener(this, new OnCompleteListener<Void>() {
- @Override
- public void onComplete(@NonNull Task<Void> task) {
- mRequestingLocationUpdates = false;
- setButtonsEnabledState();
- }
- });
- }
- @Override
- public void onResume() {
- super.onResume();
- // Within {@code onPause()}, we remove location updates. Here, we resume receiving
- // location updates if the user has requested them.
- if (mRequestingLocationUpdates && checkPermissions()) {
- startLocationUpdates();
- } else if (!checkPermissions()) {
- requestPermissions();
- }
- updateUI();
- }
- @Override
- protected void onPause() {
- super.onPause();
- // Remove location updates to save battery.
- stopLocationUpdates();
- }
- /**
- * Shows a {@link Snackbar}.
- *
- * @param mainTextStringId The id for the string resource for the Snackbar text.
- * @param actionStringId The text of the action item.
- * @param listener The listener associated with the Snackbar action.
- */
- private void showSnackbar(final int mainTextStringId, final int actionStringId,
- View.OnClickListener listener) {
- Snackbar.make(
- findViewById(android.R.id.content),
- getString(mainTextStringId),
- Snackbar.LENGTH_INDEFINITE)
- .setAction(getString(actionStringId), listener).show();
- }
- /**
- * Return the current state of the permissions needed.
- */
- private boolean checkPermissions() {
- int permissionState = ActivityCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_FINE_LOCATION);
- return permissionState == PackageManager.PERMISSION_GRANTED;
- }
- /**
- * 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();
- }
- private void requestPermissions() {
- boolean shouldProvideRationale =
- ActivityCompat.shouldShowRequestPermissionRationale(this,
- Manifest.permission.ACCESS_FINE_LOCATION);
- // Provide an additional rationale to the user. This would happen if the user denied the
- // request previously, but didn't check the "Don't ask again" checkbox.
- if (shouldProvideRationale) {
- Log.e(TAG, "Displaying permission rationale to provide additional context.");
- showSnackbar(R.string.permission_rationale,
- android.R.string.ok, new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Request permission
- ActivityCompat.requestPermissions(MainActivity.this,
- new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
- REQUEST_PERMISSIONS_REQUEST_CODE);
- }
- });
- } else {
- Log.e(TAG, "Requesting permission");
- // Request permission. It's possible this can be auto answered if device policy
- // sets the permission in a given state or the user denied the permission
- // previously and checked "Never ask again".
- ActivityCompat.requestPermissions(MainActivity.this,
- new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
- REQUEST_PERMISSIONS_REQUEST_CODE);
- }
- }
- /**
- * Callback received when a permissions request has been completed.
- */
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
- @NonNull int[] grantResults) {
- Log.e(TAG, "onRequestPermissionResult");
- if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
- if (grantResults.length <= 0) {
- // If user interaction was interrupted, the permission request is cancelled and you
- // receive empty arrays.
- Log.e(TAG, "User interaction was cancelled.");
- } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- if (mRequestingLocationUpdates) {
- Log.e(TAG, "Permission granted, updates requested, starting location updates");
- startLocationUpdates();
- }
- } else {
- // Permission denied.
- // Notify the user via a SnackBar that they have rejected a core permission for the
- // app, which makes the Activity useless. In a real app, core permissions would
- // typically be best requested during a welcome-screen flow.
- // Additionally, it is important to remember that a permission might have been
- // rejected without asking the user for permission (device policy or "Never ask
- // again" prompts). Therefore, a user interface affordance is typically implemented
- // when permissions are denied. Otherwise, your app could appear unresponsive to
- // touches or interactions which have required permissions.
- showSnackbar(R.string.permission_denied_explanation,
- R.string.settings, new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Build intent that displays the App settings screen.
- Intent intent = new Intent();
- intent.setAction(
- Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- Uri uri = Uri.fromParts("package",
- BuildConfig.APPLICATION_ID, null);
- intent.setData(uri);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- }
- });
- }
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_main, menu);
- return true;
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
- //noinspection SimplifiableIfStatement
- if (id == R.id.action_settings) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
- }
Add Comment
Please, Sign In to add comment