/*******************************************************************************
* Created by Orlando Aliaga
* Copyright 2015 Prey Inc. All rights reserved.
* License: GPLv3
* Full license at "/LICENSE"
******************************************************************************/
package com.prey.actions.location;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.prey.PreyConfig;
import com.prey.PreyLogger;
import com.prey.PreyPhone;
import com.prey.PreyPhone.Wifi;
import com.prey.actions.HttpDataService;
import com.prey.json.UtilJson;
import com.prey.managers.PreyWifiManager;
import com.prey.net.PreyWebServices;
import com.prey.services.LocationService;
public class LocationUtil {
public static final String LAT = "lat";
public static final String LNG = "lng";
public static final String ACC = "accuracy";
public static final String METHOD = "method";
public static HttpDataService dataLocation(Context ctx, String messageId, boolean asynchronous) {
HttpDataService data = null;
try {
PreyLocation preyLocation = getLocation(ctx,messageId,asynchronous);
if (!asynchronous) {
if (preyLocation != null) {
PreyLogger.d("locationData:" + preyLocation.getLat() + " " + preyLocation.getLng() + " " + preyLocation.getAccuracy());
data = convertData(preyLocation);
} else {
sendNotify(ctx, "Error", "failed");
}
}else{
return null;
}
} catch (Exception e) {
sendNotify(ctx, "Error", messageId);
}
return data;
}
public static PreyLocation getLocation(Context ctx, String messageId, boolean asynchronous) throws Exception{
PreyLocation preyLocation = null;
boolean isGpsEnabled = PreyLocationManager.getInstance(ctx).isGpsLocationServiceActive();
boolean isNetworkEnabled = PreyLocationManager.getInstance(ctx).isNetworkLocationServiceActive();
boolean isWifiEnabled = PreyWifiManager.getInstance(ctx).isWifiEnabled();
boolean isGooglePlayServicesAvailable=isGooglePlayServicesAvailable(ctx);
PreyLogger.d("status gps:" + isGpsEnabled + " net:" + isNetworkEnabled + " wifi:" + isWifiEnabled+" play:"+isGooglePlayServicesAvailable);
String method = getMethod(isGpsEnabled, isNetworkEnabled);
try {
if (isWifiEnabled) {
preyLocation = getDataLocationWifi(ctx,method,asynchronous,preyLocation);
}
} catch (Exception e) {
}
try {
if(!isGooglePlayServicesAvailable||(isGpsEnabled&&!isNetworkEnabled)) {
preyLocation = getPreyLocationAppService(ctx,method,asynchronous,preyLocation);
}else{
preyLocation = getPreyLocationPlayService(ctx, method, asynchronous,preyLocation);
}
} catch (Exception e) {
throw e;
}
return preyLocation;
}
private static boolean isGooglePlayServicesAvailable(Context ctx){
boolean isGooglePlayServicesAvailable=false;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|| (ActivityCompat.checkSelfPermission(ctx, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(ctx, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(ctx);
if (ConnectionResult.SUCCESS == resultCode) {
isGooglePlayServicesAvailable=true;
}
}
return isGooglePlayServicesAvailable;
}
private static String getMethod(boolean isGpsEnabled, boolean isNetworkEnabled) {
if (isGpsEnabled && isNetworkEnabled) {
return "native";
}
if (isGpsEnabled) {
return "gps";
}
if (isNetworkEnabled) {
return "network";
}
return "";
}
private static void sendNotify(Context ctx, String message) {
Map<String, String> parms = UtilJson.makeMapParam("get", "location", "failed", message);
PreyWebServices.getInstance().sendNotifyActionResultPreyHttp(ctx, parms);
}
private static void sendNotify(Context ctx, String message, String status) {
Map<String, String> parms = UtilJson.makeMapParam("get", "location", status, message);
PreyWebServices.getInstance().sendNotifyActionResultPreyHttp(ctx, parms);
}
private static PreyLocation getDataLocationWifi(Context ctx, String method, boolean asynchronous, PreyLocation preyLocationOld) throws Exception {
PreyLocation preyLocation = null;
List<Wifi> listWifi = null;
PreyPhone preyPhone = new PreyPhone(ctx);
if (PreyWifiManager.getInstance(ctx).isWifiEnabled()) {
listWifi = preyPhone.getListWifi();
}
if (listWifi == null || listWifi.size() == 0) {
throw new Exception();
}
preyLocation = PreyWebServices.getInstance().getLocation(ctx, listWifi);
preyLocation.setMethod("wifi");
sendLocation(ctx, asynchronous, null, preyLocation);
return preyLocation;
}
private final static int MAXIMUM_OF_ATTEMPTS=9;
private final static int []SLEEP_OF_ATTEMPTS=new int[]{2,2,2,3,3,3,4,4,4};
private static PreyLocation getPreyLocationPlayService(final Context ctx, String method, boolean asynchronous, PreyLocation preyLocationOld) throws Exception {
PreyLocation preyLocation = null;
final PreyGooglePlayServiceLocation play = new PreyGooglePlayServiceLocation();
try {
new Thread(new Runnable() {
@Override
public void run() {
play.init(ctx);
}
}).start();
Location currentLocation = null;
PreyLocationManager manager =PreyLocationManager.getInstance(ctx);
int i = 0;
while (i < MAXIMUM_OF_ATTEMPTS) {
try {
Thread.sleep(SLEEP_OF_ATTEMPTS[i]*1000);
} catch (InterruptedException e) {
}
currentLocation = play.getLastLocation(ctx);
if (currentLocation != null) {
PreyLogger.d("getPreyLocationPlayService["+i+"]:"+currentLocation.toString());
preyLocation = new PreyLocation(currentLocation, method);
preyLocationOld = sendLocation(ctx, asynchronous, preyLocationOld, preyLocation);
if(!asynchronous)
i=MAXIMUM_OF_ATTEMPTS;
}
i++;
}
} catch (Exception e) {
PreyLogger.d("Error getPreyLocationPlayService:"+e.getMessage());
throw e;
} finally {
play.stopLocationUpdates();
}
return preyLocation;
}
private static PreyLocation getPreyLocationAppService(final Context ctx, String method, boolean asynchronous, PreyLocation preyLocationOld) throws Exception {
PreyLocation preyLocation = null;
Intent intent = new Intent(ctx, LocationService.class);
try {
ctx.startService(intent);
int i = 0;
while (i < MAXIMUM_OF_ATTEMPTS) {
try {
Thread.sleep(SLEEP_OF_ATTEMPTS[i]*1000);
} catch (InterruptedException e) {
}
PreyLocation location = PreyLocationManager.getInstance(ctx).getLastLocation();
if (location.isValid()) {
preyLocation=location;
preyLocation.setMethod(method);
PreyLogger.d("getPreyLocationAppService["+i+"]:"+preyLocation.toString());
preyLocationOld = sendLocation(ctx, asynchronous, preyLocationOld, preyLocation);
if(!asynchronous)
i=MAXIMUM_OF_ATTEMPTS;
}
i++;
}
} catch (Exception e) {
PreyLogger.d("Error getPreyLocationAppService:"+e.getMessage());
throw e;
} finally {
ctx.stopService(intent);
}
return preyLocation;
}
private static PreyLocation sendLocation(Context ctx,boolean asynchronous, PreyLocation locationOld, PreyLocation locationNew){
double distance = distance(locationOld,locationNew);
double distanceLocation = PreyConfig.getPreyConfig(ctx).getDistanceLocation();
if(locationNew!=null) {
if(locationOld==null||distance>distanceLocation||locationOld.getAccuracy()>locationNew.getAccuracy()){
if (asynchronous) {
HttpDataService data = convertData(locationNew);
ArrayList<HttpDataService> dataToBeSent = new ArrayList<HttpDataService>();
dataToBeSent.add(data);
PreyWebServices.getInstance().sendPreyHttpData(ctx, dataToBeSent);
}
}
return locationNew;
}else {
return locationOld;
}
}
private static double distance(PreyLocation locationOld, PreyLocation locationNew){
if(locationOld!=null&&locationNew!=null) {
Location locStart = new Location("");
locStart.setLatitude(locationNew.getLat());
locStart.setLongitude(locationNew.getLng());
Location locEnd = new Location("");
locEnd.setLatitude(locationOld.getLat());
locEnd.setLongitude(locationOld.getLng());
return Math.round(locStart.distanceTo(locEnd));
}else{
return 0d;
}
}
public static HttpDataService convertData(PreyLocation lastLocation) {
if(lastLocation==null)
return null;
HttpDataService data = new HttpDataService("location");
data.setList(true);
HashMap<String, String> parametersMap = new HashMap<String, String>();
parametersMap.put(LAT, Double.toString(lastLocation.getLat()));
parametersMap.put(LNG, Double.toString(lastLocation.getLng()));
parametersMap.put(ACC, Float.toString(Math.round(lastLocation.getAccuracy())));
parametersMap.put(METHOD, lastLocation.getMethod() );
data.addDataListAll(parametersMap);
PreyLogger.i("lat:"+lastLocation.getLat()+" lng:"+lastLocation.getLng()+" acc:"+lastLocation.getAccuracy()+" met:"+lastLocation.getMethod());
return data;
}
public static PreyLocation dataPreyLocation(Context ctx,String messageId) {
HttpDataService data=dataLocation(ctx,messageId,false);
PreyLocation location=new PreyLocation();
location.setLat(Double.parseDouble(data.getDataList().get(LAT)));
location.setLng(Double.parseDouble(data.getDataList().get(LNG)));
location.setAccuracy(Float.parseFloat(data.getDataList().get(ACC)));
return location;
}
}