0

I am working on my capstone and we are developing an app that gets a user location and plots this on a map. We are trying to get the location every x variable (x being a setting the user inputs from a selection of 5, 10, 15, 30, and 60 minutes) and send the best location to a database for sharing later. The app basic flow is that every time the user opens the app they see a map and it displays their current location ASAP. The location is then sent to a database to share with other people. After they get the location a timer is started that gets their location again every, lets say they want 30 minutes, and then sends that location to the DB and starts the timer again. The timer needs to reset every time the user accesses the application because they will immediately get their location upon starting the app. The problem I am having is creating a timer in the background that will get their location while not in the app to send to the DB. I also want to implement logic that says after we get their location, we stop listening for updates for a small amount of time.

I currently understand the requestLocationUpdates() method and have implemented it so as a user accesses the app, they get a location both from GPS and NETWORK and it has a min time of 60 seconds and a distance of 100ft or 30.48 meters. This also stops when a user pauses the app and starts when a user navigates back to the app. I notice though we keep requesting updates even though we have already received an update. This leaves me to believe that the requestLocationUpdates is continuing to use battery life as it is listening for update changes.

How do I create this logic to stop updating after a location is received but then start listening for a location after a certain time? Reading the current android method of requestLocationUpdates, the minTime and minDistance are just "hints" but it doesn't obey them. I need the locationUpdater to obey set parameters.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /** Session Creation and Checker */
    session = new SessionManagement(getApplicationContext());
    // Check if the user is logged in
    session.checkLogin();

    /** Setup basic session and content view */
    // Set the Content View
    setContentView(R.layout.activity_main);
    /** Start of the MapView Elements */
    // extract MapView from layout
    mapView = (MapView) findViewById(R.id.mapview);
    // Set a mapController
    mapController = mapView.getController();
    // set the map to have built in zoom controls
    mapView.setBuiltInZoomControls(true);

    /** Getting the device location */
    locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    geoCoder = new Geocoder(this);

    isEnabled = locationManager
            .isProviderEnabled(LocationManager.GPS_PROVIDER);
    // Check if the GPS is enabled
    if (!isEnabled) {
        alert.showAlertDialog(MainActivity.this, 12);
    }

    // Retrieve a list of location providers that have fine accuracy, no
    // monetary cost, etc
    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_HIGH);
    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(false);
    criteria.setCostAllowed(true);
    criteria.setPowerRequirement(Criteria.POWER_LOW);
    provider = locationManager.getBestProvider(criteria, true);

    // If no suitable provider is found, null is returned.
    if (provider != null) {
        provider = locationManager.getBestProvider(criteria, false);
        BCT = (session.getBCT() * 60000);
        // Initialize with last known location
        locationManager.requestLocationUpdates(provider, BCT, 31,
                locationListener);

        // Check the map settings
        if (session.isSatellite()) {
            SatelliteChecked = true;
            mapView.setSatellite(true);
        }
        if (session.isTraffic()) {
            TrafficChecked = true;
            mapView.setTraffic(true);
        }
    } else {
        alert.showAlertDialog(getApplicationContext(), 15);
        locationManager.removeUpdates(locationListener);
    }

}

// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
        // Called when a new location is found by the network location
        // provider.

            Toast.makeText(getApplicationContext(), location.toString(),
                    Toast.LENGTH_LONG).show();

    }

    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    public void onProviderEnabled(String provider) {
        Toast.makeText(getApplicationContext(), provider.toUpperCase() + " enabled.", Toast.LENGTH_SHORT).show();
    }

    public void onProviderDisabled(String provider) {
        Toast.makeText(getApplicationContext(), provider.toUpperCase() + " disabled.", Toast.LENGTH_SHORT).show();
    }
};
@Override
protected void onResume() {
    super.onResume();
    BCT = (session.getBCT() * 60000);
    // when our activity resumes, we want to register for location updates
    locationManager.requestLocationUpdates(
            provider, BCT, 31, locationListener);
}

@Override
protected void onPause() {
    super.onPause();
    // when our activity pauses, we want to remove listening for location
    // updates
    locationManager.removeUpdates(locationListener);
}
jdelbs18
  • 13
  • 1
  • 5

2 Answers2

0

what you need is a Background Thread for your timer.

you could try:

  1. using an Alarm Manager to schedule every x minutes. see this question's answers: Android: How to use AlarmManager
  2. use an AsyncTask or Handler with postDelayed by x minutes, as in http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable, long)

since this is your capstone project, i didn't want to give out too much code. but i can explain the background thread in more detail:

your timing right now is all done in the foreground, which means that unless the app is opened, the timer is not ticking. what you need to do is have your timer in a background thread. this is a thread that is managed by the operating system and is still running even though your app is not running. since you're doing this for a project and not for commercial project, i would recommend you go with the Handler approach. like this:

//make instance variable of the time the user chose, say... delayInMinutes
int delayInMinutes;
...
//then whenever you want to start the timer...
final Runnable updateLocation = new Runnable() {
    public void run() {
        //
        ... do your update location here
        //
    }
};

handler.postDelayed(updateLocation, delayInMinutes * 60 * 1000);

and that should work

Community
  • 1
  • 1
David T.
  • 22,301
  • 23
  • 71
  • 123
0

This is a perfect situation for using alarms and an IntentService. Launch the IntentService with a repeating alarm set to the interval desired by the user and have the IntentService handle the location update.

It's all done in the background for you and you don't have anything running when it doesn't need to be.

Khantahr
  • 8,156
  • 4
  • 37
  • 60