/*******************************************************************************
* Created by Carlos Yaconi
* Copyright 2015 Prey Inc. All rights reserved.
* License: GPLv3
* Full license at "/LICENSE"
******************************************************************************/
package com.prey.services;
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ActivityCompat;
import com.prey.PreyConfig;
import com.prey.PreyLogger;
import com.prey.actions.location.PreyLocation;
import com.prey.actions.location.PreyLocationManager;
/**
* This service is intented to be running while Prey is active. While
* running, it will be updating the last location available in PreyConfig
* persitent storage
*/
public class LocationService extends Service {
private Location lastRegisteredLocation;
//private LocationManager networkLocationManager;
private LocationManager androidLocationManager;
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
/**
* Class for clients to access. Because we know this service always runs in
* the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocationService getService() {
return LocationService.this;
}
}
@Override
public void onCreate() {
PreyLogger.d("LocationService is going to be started...");
androidLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|| (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
LocationProvider gpsLocationProvider = androidLocationManager.getProvider(LocationManager.GPS_PROVIDER);
LocationProvider networkProvider = androidLocationManager.getProvider(LocationManager.NETWORK_PROVIDER);
if (gpsLocationProvider != null && androidLocationManager.isProviderEnabled(gpsLocationProvider.getName())) {
androidLocationManager.requestLocationUpdates(gpsLocationProvider.getName(), PreyConfig.UPDATE_INTERVAL, PreyConfig.LOCATION_PROVIDERS_MIN_REFRESH_DISTANCE,
gpsLocationListener);
PreyLogger.d("GPS Location provider has been started.");
}
if (networkProvider != null && androidLocationManager.isProviderEnabled(networkProvider.getName())) {
androidLocationManager.requestLocationUpdates(networkProvider.getName(), PreyConfig.UPDATE_INTERVAL / 4, PreyConfig.LOCATION_PROVIDERS_MIN_REFRESH_DISTANCE,
networkLocationListener);
PreyLogger.d("NETWORK Location provider has been started.");
}
} else {
PreyLogger.i("___________ask for permission LocationService ACCESS_FINE_LOCATION");
}
PreyLogger.d("LocationService has been started...");
}
@Override
public void onDestroy() {
if (androidLocationManager != null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|| (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
androidLocationManager.removeUpdates(gpsLocationListener);
androidLocationManager.removeUpdates(networkLocationListener);
}
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public Location getLastRegisteredLocation() {
return lastRegisteredLocation;
}
private void setNewLocation(Location newLocation) {
PreyLogger.d("[" + newLocation.getProvider() + "] Fix found!. Accuracy: [" + newLocation.getAccuracy() + "]");
if (lastRegisteredLocation == null) {
//PreyLogger.d("-----> First fix. Set as last location!");
lastRegisteredLocation = newLocation;
} else {
if (newLocation.getTime() - lastRegisteredLocation.getTime() > PreyConfig.LAST_LOCATION_MAX_AGE) {
//Last registered fix was set more that 2 minutes ago. It's older so must be updated!
//PreyLogger.d("-----> Old fix has expired (older than 2 minutes). Setting new fix as last location!");
lastRegisteredLocation = newLocation;
} else if (newLocation.hasAccuracy() && (newLocation.getAccuracy() < lastRegisteredLocation.getAccuracy())) {
//New location is more accurate than the previous one. Win!
//PreyLogger.d("-------> Newer and more accurate fix. Set as last location!");
lastRegisteredLocation = newLocation;
}
}
PreyLocationManager.getInstance(getApplicationContext()).setLastLocation(new PreyLocation(lastRegisteredLocation));
}
private LocationListener gpsLocationListener = new LocationListener() {
public void onStatusChanged(String provider, int status, Bundle extras) {
String statusAsString = "Available";
if (status == LocationProvider.OUT_OF_SERVICE)
statusAsString = "Out of service";
else if (status == LocationProvider.TEMPORARILY_UNAVAILABLE)
statusAsString = "Temporarily Unavailable";
PreyLogger.d("[LocationService] GPS Location provider status has changed: [" + statusAsString + "].");
}
public void onProviderEnabled(String provider) {
PreyLogger.d("[LocationService] GPS Location Provider has been enabled: " + provider);
//androidLocationManager.removeUpdates(gpsLocationListener);
//androidLocationManager.requestLocationUpdates(provider, PreyConfig.LOCATION_PROVIDERS_MIN_REFRESH_INTERVAL, PreyConfig.LOCATION_PROVIDERS_MIN_REFRESH_DISTANCE, gpsLocationListener);
}
public void onProviderDisabled(String provider) {
PreyLogger.d("[LocationService] GPS Location Provider has been disabled: " + provider);
}
public void onLocationChanged(Location location) {
setNewLocation(location);
}
};
private LocationListener networkLocationListener = new LocationListener() {
public void onStatusChanged(String provider, int status, Bundle extras) {
String statusAsString = "Available";
if (status == LocationProvider.OUT_OF_SERVICE)
statusAsString = "Out of service";
else if (status == LocationProvider.TEMPORARILY_UNAVAILABLE)
statusAsString = "Temporarily Unavailable";
PreyLogger.d("[LocationService] Network Location provider status has changed: [" + statusAsString + "].");
}
public void onProviderEnabled(String provider) {
PreyLogger.d("[LocationService] Network Location Provider has been enabled: " + provider);
}
public void onProviderDisabled(String provider) {
PreyLogger.d("[LocationService] Network Location Provider has been disabled: " + provider);
}
public void onLocationChanged(Location location) {
setNewLocation(location);
}
};
}