0

I am using a Location listener service to update the current location of the user for every few secs. I have also used a WakeLock to make the listener work in the background. Now everything is working fine but i am unable to stop the Location listener. Even if the app is force closed the listener is updating the user location to the DB.

Location Listener:

 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.location.Location;
 import android.location.LocationManager;
 import android.os.Bundle;
 import android.os.IBinder;
import android.os.PowerManager;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.maps.model.LatLng;

public class MyLocationService extends Service {
private static final String TAG = "MyLocationService";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 3000;
private static final float LOCATION_DISTANCE = 0f;
Context context = this;
PowerManager.WakeLock wakeLock;
public int e=0;

LocationListener[] mLocationListeners = new LocationListener[]{
        new LocationListener(LocationManager.GPS_PROVIDER),
        new LocationListener(LocationManager.NETWORK_PROVIDER)
};

@Override
public IBinder onBind(Intent arg0) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.e(TAG, "onStartCommand");
    super.onStartCommand(intent, flags, startId);
    Toast.makeText(this, "MyService Started.", Toast.LENGTH_SHORT).show();
    return START_STICKY;
}

@Override
public void onCreate() {
    Log.e(TAG, "onCreate");
    initializeLocationManager();
    PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    wakeLock= mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
    wakeLock.acquire();
    try {
        mLocationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                mLocationListeners[1]);
    } catch (java.lang.SecurityException ex) {
        Log.i(TAG, "fail to request location update, ignore", ex);
    } catch (IllegalArgumentException ex) {
        Log.d(TAG, "network provider does not exist, " + ex.getMessage());
    }
    try {
        mLocationManager.requestLocationUpdates(
                LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                mLocationListeners[0]);
    } catch (java.lang.SecurityException ex) {
        Log.i(TAG, "fail to request location update, ignore", ex);
    } catch (IllegalArgumentException ex) {
        Log.d(TAG, "gps provider does not exist " + ex.getMessage());
    }
}

@Override
public void onDestroy() {
    Log.e(TAG, "onDestroy");
    wakeLock.release();
    super.onDestroy();


    if (mLocationManager != null) {
        for (int i = 0; i < mLocationListeners.length; i++) {
            try {
                if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    // TODO: Consider calling
                    //    ActivityCompat#requestPermissions
                    // here to request the missing permissions, and then overriding
                    //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                    //                                          int[] grantResults)
                    // to handle the case where the user grants the permission. See the documentation
                    // for ActivityCompat#requestPermissions for more details.
                    return;
                }
                mLocationManager.removeUpdates(mLocationListeners[i]);
            } catch (Exception ex) {
                Log.i(TAG, "fail to remove location listners, ignore", ex);
            }
        }
    }
}

private void initializeLocationManager() {
    Log.e(TAG, "initializeLocationManager");
    if (mLocationManager == null) {
        mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
    }
}

// create LocationListener class to get location updates
private class LocationListener implements android.location.LocationListener
{
    Location mLastLocation;
    double latitude;
    double longitude;
    LatLng latLngcurrent;


    public LocationListener(String provider)
    {
        Log.e(TAG, "LocationListener " + provider);
        mLastLocation = new Location(provider);
    }

    @Override
    public void onLocationChanged(Location location)
    {
        Log.e(TAG, "onLocationChanged: " + location);
        mLastLocation.set(location);
        latitude = location.getLatitude();
        longitude = location.getLongitude();
        Store.latu=latitude;
        Store.longu=longitude;
        latLngcurrent = new LatLng(location.getLatitude(), location.getLongitude());
        Toast.makeText(context,"Location " + String.valueOf(e), Toast.LENGTH_SHORT).show();
        e++;
        Toast.makeText(MyLocationService.this,Store.latu+" "+Store.longu, Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onProviderDisabled(String provider)
    {
        Log.e(TAG, "onProviderDisabled: " + provider);
    }

    @Override
    public void onProviderEnabled(String provider)
    {
        Log.e(TAG, "onProviderEnabled: " + provider);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras)
    {
        Log.e(TAG, "onStatusChanged: " + provider);
    }
}
}

Starting the service intent:(from mainactivity)

   @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);


    Intent serviceIntent  = new Intent(context , MyLocationService.class);
    context.startService(serviceIntent  );



    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        checkLocationPermission();
    }
    if (!isGooglePlayServicesAvailable()) {
        finish();
    } else {
        Log.d("onCreate", "Google Play Services available.");
    }
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

Stopping the intent:(from mainactivity)

 private class LogOutTimerTask extends TimerTask
{
    @Override
    public void run()
    {
        Intent i = new Intent(MapsActivity.this, Login.class);
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(i);
        Intent intent = new Intent(MapsActivity.this, MyLocationService.class);
        stopService(intent);
        finish();
    }
}

The stop intent is called when the user logout, now the onDestroy() method in the service class is getting called but its is not stopping the process. When the application is force closed the onDestroy() is not even called. In both the cases the process resumes and keep updating the values to DB.Thanks in advance.

Rakesh Polo
  • 431
  • 1
  • 9
  • 27
  • is `removeUpdates()` being called? or the method returns because of the permissions `IF` ? though, why u are checking permission when removing the listeners? this should be somewhere in or around `initializeLocationManager()` – Yazan May 02 '17 at 07:39
  • I haven't checked whether the removeupdates() is being called. I have added permissions because android studio was recommending me. @Yazan – Rakesh Polo May 02 '17 at 07:47
  • 1
    i doubt that this place is good to request a permission (while destroying the service?!) however, it's not so good to place it in the loop, u can ask for it once (before the loop) also try to add a log just before the `removeUpdates()` something like this `Log.i(TAG, "removing listeners ...");` and see if it appears in the logcat – Yazan May 02 '17 at 07:57
  • I have removed the permission check and added the log(), now when i logout, the log value is printing and then the service stops. but when the app is force closed from the background the service is not getting terminated and onDestroy is also not getting called. @Yazan – Rakesh Polo May 02 '17 at 08:20
  • ok, this is another question, i suggest you ask separately, however i think it has something to do with `return START_STICKY;` this topic need some reading so you understand how services behaves when app killed, restarted ... etc – Yazan May 02 '17 at 08:32

1 Answers1

1

Solution: I have finally found the solution for this. As @Yazan said i have removed the permissions from onDestroy() method, which helps the service to stop manually when the user logs out. And to stop the service when the app is force closed, In your manifest while using the tag add this line too.

Snippet:

 <service android:name=".MyLocationService"
 android:stopWithTask="true"></service>

stopWithTask will stop the service when we force close the application and the LocationListener will also stop.

here is the documentation. After adding this my application works fine.

Rakesh Polo
  • 431
  • 1
  • 9
  • 27