Skip to content

Commit

Permalink
Use FusedLocationProvider when available (getodk#1336)
Browse files Browse the repository at this point in the history
  • Loading branch information
heyjamesknight authored and lognaturel committed Sep 8, 2017
1 parent 0e6d944 commit 0304479
Show file tree
Hide file tree
Showing 24 changed files with 2,718 additions and 620 deletions.
1 change: 1 addition & 0 deletions collect_app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ dependencies {
compile group: 'com.google.android.gms', name: 'play-services-analytics', version: '10.0.1'
compile group: 'com.google.android.gms', name: 'play-services-auth', version: '10.0.1'
compile group: 'com.google.android.gms', name: 'play-services-maps', version: '10.0.1'
compile group: 'com.google.android.gms', name: 'play-services-location', version: '10.0.1'
compile (group: 'com.google.code.gson', name: 'gson', version: '2.6.2'){
exclude group: 'org.apache.httpcomponents'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,42 @@
package org.odk.collect.android.activities;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;

import com.google.android.gms.location.LocationListener;

import org.odk.collect.android.R;
import org.odk.collect.android.application.Collect;
import org.odk.collect.android.utilities.InfoLogger;
import org.odk.collect.android.location.LocationClient;
import org.odk.collect.android.location.LocationClients;
import org.odk.collect.android.utilities.ToastUtils;
import org.odk.collect.android.widgets.GeoPointWidget;

import java.text.DecimalFormat;
import java.util.List;

public class GeoPointActivity extends AppCompatActivity implements LocationListener {
import timber.log.Timber;

public class GeoPointActivity extends AppCompatActivity implements LocationListener,
LocationClient.LocationClientListener {

// Default values for requesting Location updates.
private static final long LOCATION_UPDATE_INTERVAL = 100;
private static final long LOCATION_FASTEST_UPDATE_INTERVAL = 50;

private static final String LOCATION_COUNT = "locationCount";

private ProgressDialog locationDialog;
private LocationManager locationManager;

private LocationClient locationClient;
private Location location;
private boolean gpsOn = false;
private boolean networkOn = false;

private double locationAccuracy;
private int locationCount = 0;

Expand All @@ -68,70 +74,38 @@ protected void onCreate(Bundle savedInstanceState) {
}

setTitle(getString(R.string.get_location));
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// make sure we have a good location provider before continuing
List<String> providers = locationManager.getProviders(true);
for (String provider : providers) {
if (provider.equalsIgnoreCase(LocationManager.GPS_PROVIDER)) {
gpsOn = true;
}
if (provider.equalsIgnoreCase(LocationManager.NETWORK_PROVIDER)) {
networkOn = true;
}
}
if (!gpsOn && !networkOn) {
ToastUtils.showShortToast(R.string.provider_disabled_error);
Intent onGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(onGPSIntent);
finish();
}

if (gpsOn) {
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {
InfoLogger.geolog("GeoPointActivity: " + System.currentTimeMillis()
+ " lastKnownLocation(GPS) lat: "
+ loc.getLatitude() + " long: "
+ loc.getLongitude() + " acc: "
+ loc.getAccuracy());
} else {
InfoLogger.geolog("GeoPointActivity: " + System.currentTimeMillis()
+ " lastKnownLocation(GPS) null location");
}
locationClient = LocationClients.clientForContext(this);
if (locationClient.canSetUpdateIntervals()) {
locationClient.setUpdateIntervals(LOCATION_UPDATE_INTERVAL, LOCATION_FASTEST_UPDATE_INTERVAL);
}

if (networkOn) {
Location loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {
InfoLogger.geolog("GeoPointActivity: " + System.currentTimeMillis()
+ " lastKnownLocation(Network) lat: "
+ loc.getLatitude() + " long: "
+ loc.getLongitude() + " acc: "
+ loc.getAccuracy());
} else {
InfoLogger.geolog("GeoPointActivity: " + System.currentTimeMillis()
+ " lastKnownLocation(Network) null location");
}
}
locationClient.setListener(this);

setupLocationDialog();
}


@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(LOCATION_COUNT, locationCount);
protected void onStart() {
super.onStart();
locationClient.start();

Collect.getInstance().getActivityLogger().logOnStart(this);
}

@Override
protected void onPause() {
super.onPause();
protected void onResume() {
super.onResume();

// stops the GPS. Note that this will turn off the GPS if the screen goes to sleep.
if (locationManager != null) {
locationManager.removeUpdates(this);
if (locationDialog != null) {
locationDialog.show();
}
}

@Override
protected void onPause() {
super.onPause();

// We're not using managed dialogs, so we have to dismiss the dialog to prevent it from
// leaking memory.
Expand All @@ -140,39 +114,48 @@ protected void onPause() {
}
}

@Override
protected void onStop() {
locationClient.stop();

Collect.getInstance().getActivityLogger().logOnStop(this);
super.onStop();
}

@Override
protected void onResume() {
super.onResume();
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(LOCATION_COUNT, locationCount);
}

if (locationManager != null) {
if (gpsOn) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
if (networkOn) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
}
}
if (locationDialog != null) {
locationDialog.show();
// LocationClientListener:

@Override
public void onClientStart() {
locationClient.requestLocationUpdates(this);

if (locationClient.isLocationAvailable()) {
logLastLocation();

} else {
finishOnError();
}
}

@Override
protected void onStart() {
super.onStart();
Collect.getInstance().getActivityLogger().logOnStart(this);
public void onClientStartFailure() {
finishOnError();
}

@Override
protected void onStop() {
Collect.getInstance().getActivityLogger().logOnStop(this);
super.onStop();
public void onClientStop() {

}

/**
* Sets up the look and actions for the progress dialog while the GPS is searching.
*/
@SuppressWarnings("deprecation")
private void setupLocationDialog() {
Collect.getInstance().getActivityLogger().logInstanceAction(this, "setupLocationDialog",
"show");
Expand Down Expand Up @@ -211,79 +194,81 @@ public void onClick(DialogInterface dialog, int which) {
geoPointButtonListener);
}

private void logLastLocation() {
Location loc = locationClient.getLastLocation();

if (loc != null) {
Timber.i("lastKnownLocation() lat: %f long: %f acc: %f", loc.getLatitude(), loc.getLongitude(), loc.getAccuracy());

} else {
Timber.i("lastKnownLocation() null location");
}
}

private void returnLocation() {
if (location != null) {
Intent i = new Intent();
i.putExtra(
FormEntryActivity.LOCATION_RESULT,
location.getLatitude() + " " + location.getLongitude() + " "
+ location.getAltitude() + " " + location.getAccuracy());

i.putExtra(FormEntryActivity.LOCATION_RESULT, getResultStringForLocation(location));

setResult(RESULT_OK, i);
}

finish();
}

private void finishOnError() {
ToastUtils.showShortToast(R.string.provider_disabled_error);
Intent onGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);

startActivity(onGPSIntent);
finish();
}

@Override
public void onLocationChanged(Location location) {
this.location = location;
if (this.location != null) {

if (location != null) {
// Bug report: cached GeoPoint is being returned as the first value.
// Wait for the 2nd value to be returned, which is hopefully not cached?
++locationCount;
InfoLogger.geolog("GeoPointActivity: " + System.currentTimeMillis()
+ " onLocationChanged(" + locationCount + ") lat: "
+ this.location.getLatitude() + " long: "
+ this.location.getLongitude() + " acc: "
+ this.location.getAccuracy());
Timber.i("onLocationChanged(%d) location: %s", locationCount, location);

if (locationCount > 1) {
locationDialog.setMessage(getString(R.string.location_provider_accuracy,
this.location.getProvider(), truncateDouble(this.location.getAccuracy())));
locationDialog.setMessage(getProviderAccuracyMessage(location));

if (this.location.getAccuracy() <= locationAccuracy) {
if (location.getAccuracy() <= locationAccuracy) {
returnLocation();
}

} else {
locationDialog.setMessage(getAccuracyMessage(location));
}

} else {
InfoLogger.geolog("GeoPointActivity: " + System.currentTimeMillis()
+ " onLocationChanged(" + locationCount + ") null location");
Timber.i("onLocationChanged(%d)", locationCount);
}
}

private String truncateDouble(float number) {
DecimalFormat df = new DecimalFormat("#.##");
return df.format(number);
public String getAccuracyMessage(@NonNull Location location) {
return getString(R.string.location_accuracy, location.getAccuracy());
}


@Override
public void onProviderDisabled(String provider) {

public String getProviderAccuracyMessage(@NonNull Location location) {
return getString(R.string.location_provider_accuracy, location.getProvider(), truncateDouble(location.getAccuracy()));
}


@Override
public void onProviderEnabled(String provider) {

public String getResultStringForLocation(@NonNull Location location) {
return String.format("%s %s %s %s", location.getLatitude(), location.getLongitude(), location.getAltitude(), location.getAccuracy());
}


@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
switch (status) {
case LocationProvider.AVAILABLE:
if (location != null) {
locationDialog.setMessage(getString(R.string.location_accuracy,
location.getAccuracy()));
}
break;
case LocationProvider.OUT_OF_SERVICE:
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
break;
}
private String truncateDouble(float number) {
DecimalFormat df = new DecimalFormat("#.##");
return df.format(number);
}

public ProgressDialog getLocationDialog() {
return locationDialog;
}
}
Loading

0 comments on commit 0304479

Please sign in to comment.