Location

2017/08/07

Building Apps with Location & Maps

1 Making Your app Location-Aware

  1. location awareness
  2. Google Play services location APIs
  3. automate location tracking, geofencing, and activity recognition, get the current location, get periodic location updates, and look up address

1.1 Getting the Last Known Location

  1. use Google Play services location APIs
  2. use fused location provider
  3. getLastLocation()

1.1.1 Set up Google Play services

1.1.2 Specify App Permissions

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.google.android.gms.location.sample.locationupdates" >
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
</manifest>

1.1.3 Create Location Services Client

FuesdLocationProviderClient fusedClient = LocationServices.getFusedLoationProviderClient(this);

1.1.4 Get the Last Known Location

  1. getLastLocation() retures a Task
  2. retrieve the latitude and longitude coordinates from a Location Object
fusedClient.getLastLocation().addOnSuccessLitener(this, new OnSuccessListener<Location>() {
	@Override
	public void onSuccess(Location location) {
		//Got last known location. In some rare situations this can be null.
		if (location != null) {}
	}
});

1.2 Changing Location Settings

  1. GPS or Wi-Fi scanning
  2. the required level of accuracy/power consumption and desired update interval, and the device automatically makes the appropriate changes to system settings
  3. LocationRequest data object defined these settings

1.2.1 Configure Location Services

  1. SettingClient
  2. coarse location detection is sufficient
  3. Android 6.0+ or API 23+, request those permissions at run time

1.2.2 Set up a Location Request

  1. create a LocationRequest to store parametres for requests
  2. LocationRequest
  3. set the update interval, receive location updates
  4. set fastest update interval, handle location updates
  5. set priority, the priority of the request,
protected void createLocationRequest() {
	LocationRequest locationRequest = new LocationRequest();
	locationRequest.setInterval(1000);
	locationRequest.setFastestInterval(5000);
	locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}

1.2.3 Get current Location Settings

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(request);

SettingsClient client = LocationService.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());

1.2.4 Prompt the User to Change Location Settings

1.3 Receiving Location Updates

  1. getLastLocation()
  2. requestLocationUpdates()

1.3.1 Get the Last Known Location

  1. currentLocation
  2. request access_fine_location
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

1.3.2 Request Location Updates

  1. invoke LocationCallback.onLocationChanged()
  2. issue a PendingIntent that contains the location in its extended data
if (requestingLocationUpdates) {
	fusedClient.requestLocationUpdates(locationRequest, locationCallback, null/*Looper*/);
}

1.3.3 Define the Location Update Callback

  1. define LocationCallback
  2. implement LocationCallback interface, and invoke LocationCallback.onLocationChanged()
LocationCallback locationCallback = new LocationCallback() {
	@Override
	public void onLocationResult(LocationResult result) {
		for (Location location : result.getLocations()) {
		}
	}
});

1.3.4 Stop Location Updates

  1. reduce power consumption, and don’t collect information in bg
  2. at onPause(), call fusedClient.removeLocationUpdates(locationCallback)
  3. at onResume(), call fusedClient.requestLocationUpdates()

1.3.5 Save the State of the Activity

  1. onSaveInstanceState() to save the instance state

     @Override
     protected void onSaveInstanceState(Bundle outState) {
         outState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, requestingLocationUpdates);
     }
    
  2. at onCreate() update Values From Bundle of savedInstanceState

     if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
         requestingLocationUpdates = savedInstanceState.getBoolean(REQUESTING_LOCATION_UPDATES_KEY);
     }
     updateUI();
    

1.4 Displaying a Location Address

  1. the latitude and longitude coordinates
  2. use Geocoder to inter convert an address and coordinates

1.4.1 Get a geographic location

  1. request ACCESS_FINE_LOCATION permission
  2. getLastLocation()
  3. create a instance of FusedLocationProviderClient

1.4.2 Define an intent service to fetch the address

  1. Geocoder provides getFromLocation(), can’t call it from the main(UI) thread
  2. IntentService provides a structure for running a task on a bg thread
    • handle a long-running operation without affecting ui responsiveness
    • AsynTask is designed for short operations
    • AsynTask should not keep UI’s reference
    • IntentService need not be cancelled when the activity is rebuilt
  3. define a FetchAddressIntentService extends IntentService
  4. ResultReceiver
1.4.2.1 Define the intent Service in manifest

<service android:name=".FetchAddressIntentService" android:exported="false" />

1.4.2.2 Create a Geocoder
@Override
protected void onHandleIntent(Intent intent) {
	Geocoder geocoder = new Geocoder(this, Locale.getDefault());
}
1.4.2.3 Retrieve the street address data
  1. define a Constants to contain many values
  2. call getFromLocation() to get a street address
  3. filter some error cases
  4. Address provides getAddressLine()
  5. deliveResultToReceiver() to send the result back to the requesting activity
1.4.2.4 Reture the address to the requestor
public class FetchAddressIntentService extends IntentService {
	protected ResultReceiver receiver;
	private void deliverResultToReceiver(int resultCode, String msg) {
		Bundle bundle = new Bundle();
		bundle.putString(Contants.RESULT_DATA_KEY, msg);
		receiver.send(resultCode, bundle);

1.4.3 Start the intent Service

Intent intent = new Intent(this, FetchAddressIntentService.class);
intent.putExtra(Constants.RECEIVER, mResultReceiver);
intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
startService(intent);

1.4.4 Receive the geocoding results

class AddressResultReceiver extends ResultReceiver {
        public AddressResultReceiver(Handler handler) {
            super(handler);
        }

        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {

            // Display the address string
            // or an error message sent from the intent service.
            mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
            displayAddressOutput();

            // Show a toast message if an address was found.
            if (resultCode == Constants.SUCCESS_RESULT) {
                showToast(getString(R.string.address_found));
            }

        }
    }

1.5 Creating and Monitoring Geofences

文内导航