/* * Professional Android, 4th Edition * Reto Meier and Ian Lake * Copyright 2018 John Wiley Wiley & Sons, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.professionalandroid.apps.whereami; import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.IntentSender; import android.location.Location; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.CommonStatusCodes; 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.LocationSettingsStates; import com.google.android.gms.location.LocationSettingsStatusCodes; import com.google.android.gms.location.SettingsClient; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; import static android.support.v4.content.PermissionChecker.PERMISSION_GRANTED; public class WhereAmIActivity extends AppCompatActivity { public static final String TAG = "WhereAmIActivity"; private static final String ERROR_MSG = "Google Play services are unavailable."; private static final int LOCATION_PERMISSION_REQUEST = 1; private static final int REQUEST_CHECK_SETTINGS = 2; private TextView mTextView; private LocationRequest mLocationRequest; LocationCallback mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { Location location = locationResult.getLastLocation(); if (location != null) { updateTextView(location); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_where_am_i); mTextView = findViewById(R.id.myLocationText); GoogleApiAvailability availability = GoogleApiAvailability.getInstance(); int result = availability.isGooglePlayServicesAvailable(this); if (result != ConnectionResult.SUCCESS) { if (!availability.isUserResolvableError(result)) { Toast.makeText(this, ERROR_MSG, Toast.LENGTH_LONG).show(); } } mLocationRequest = new LocationRequest() .setInterval(5000) .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); } @Override protected void onStart() { super.onStart(); // Check if we have permission to access high accuracy fine location. int permission = ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION); // If permission is granted, fetch the last location. if (permission == PERMISSION_GRANTED) { getLastLocation(); } else { // If permission has not been granted, request permission. ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST); } // Check of the location settings are compatible with our Location Request. LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(mLocationRequest); SettingsClient client = LocationServices.getSettingsClient(this); Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build()); task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() { @Override public void onSuccess(LocationSettingsResponse locationSettingsResponse) { // Location settings satisfy the requirements of the Location Request. // Request location updates. requestLocationUpdates(); } }); task.addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Extract the status code for the failure from within the Exception. int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case CommonStatusCodes.RESOLUTION_REQUIRED: try { // Display a user dialog to resolve the location settings // issue. ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.startResolutionForResult(WhereAmIActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { Log.e(TAG, "Location Settings resolution failed.", sendEx); } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings issues can't be resolved by user. // Request location updates anyway. Log.d(TAG, "Location Settings can't be resolved."); requestLocationUpdates(); break; } } }); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == LOCATION_PERMISSION_REQUEST) { if (grantResults[0] != PERMISSION_GRANTED) Toast.makeText(this, "Location Permission Denied", Toast.LENGTH_LONG).show(); else getLastLocation(); } } private void getLastLocation() { FusedLocationProviderClient fusedLocationClient; fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED) { fusedLocationClient.getLastLocation() .addOnSuccessListener(this, new OnSuccessListener<Location>() { @Override public void onSuccess(Location location) { updateTextView(location); } }); } } private void updateTextView(Location location) { String latLongString = "No location found"; if (location != null) { double lat = location.getLatitude(); double lng = location.getLongitude(); latLongString = "Lat:" + lat + "\nLong:" + lng; } mTextView.setText(latLongString); } private void requestLocationUpdates() { if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED) { FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); fusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, null); } } @Override protected void onActivityResult(int requestCode, int resultCode,Intent data){ final LocationSettingsStates states = LocationSettingsStates.fromIntent(data); if (requestCode == REQUEST_CHECK_SETTINGS) { switch (resultCode) { case Activity.RESULT_OK: // Requested changes made, request location updates. requestLocationUpdates(); break; case Activity.RESULT_CANCELED: // Requested changes were NOT made. Log.d(TAG, "Requested settings changes declined by user."); // Check if any location services are available, and if so // request location updates. if (states.isLocationUsable()) requestLocationUpdates(); else Log.d(TAG, "No location services available."); break; default: break; } } } }