Automation/app/src/main/java/com/jens/automation2/PointOfInterest.java

850 lines
28 KiB
Java

package com.jens.automation2;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
import com.jens.automation2.Trigger.Trigger_Enum;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
public class PointOfInterest implements Comparable<PointOfInterest>
{
// The array containing all POIs
private static ArrayList<PointOfInterest> pointOfInterestCollection = new ArrayList<PointOfInterest>();
public static ArrayList<PointOfInterest> getPointOfInterestCollection()
{
Collections.sort(pointOfInterestCollection);
return pointOfInterestCollection;
}
public static void setPointOfInterestCollection(ArrayList<PointOfInterest> pointOfInterestCollection)
{
Collections.sort(pointOfInterestCollection);
PointOfInterest.pointOfInterestCollection = pointOfInterestCollection;
}
// name and location
private String name;
private Location location;
private double radius;
private String oldName;
private boolean activated=false;
private static Location[] locationRingBuffer = new Location[Settings.locationRingBufferSize];
private static int locationRingBufferLastPosition = -1;
private static boolean gpsLocationListenerArmed = false;
private static LocationManager gpsComparisonLocationManager;
private static GpsComparisonLocationListener gpsComparisonLocationListener;
private static TimeoutHandler timeoutHandler = new TimeoutHandler();
private static boolean timeoutHandlerActive = false;
public String getName()
{
return name;
}
public static void stopRoutine()
{
if(gpsLocationListenerArmed)
stopGpsMeasurement();
}
public void setName(String desiredName)
{
this.oldName = this.name;
this.name = desiredName.trim();
}
public Location getLocation()
{
return location;
}
public void setLocation(Location location)
{
this.location = location;
}
public double getRadius()
{
return radius;
}
public void setRadius(double radius, Context context) throws Exception
{
if(radius <= 0)
throw new Exception(context.getResources().getString(R.string.radiusHasToBePositive));
this.radius = radius;
}
public void setActivated(boolean value)
{
this.activated = value;
}
public boolean isActivated()
{
return activated;
}
public static void positionUpdate(Location newLocation, AutomationService parentService, boolean forceApply, boolean skipVerfication)
{
// StackTraceElement[] trace = Thread.currentThread().getStackTrace();
// for(StackTraceElement element : trace)
// {
// Log.i("Trace", Arrays.toString(trace));
// }
// Assumption "active POI = closest POI" is wrong!
if(newLocation != null)
{
String accuracyString = "n./a.";
if(newLocation.hasAccuracy())
accuracyString = String.valueOf(newLocation.getAccuracy() + " m");
Miscellaneous.logEvent("i", "POI", "Got position update (" + String.valueOf(newLocation.getLatitude()) + " / " + String.valueOf(newLocation.getLongitude()) + " / provider: " + newLocation.getProvider() + " / Accuracy: " + accuracyString + "), checking rules.", 2);
PointOfInterest closestPoi = PointOfInterest.getClosestPOI(newLocation);
if(getActivePoi() != null)
Miscellaneous.logEvent("i", "POI", "Active POI: " + getActivePoi().getName() + ", distance : " + String.valueOf(newLocation.distanceTo(getActivePoi().getLocation())), 4);
if(closestPoi == null)
{
// There are no POIs defined. Not much we can do.
// Miscellaneous.logEvent("i", "POI", "Closest POI: n/a, distance : n/a", 4);
Miscellaneous.logEvent("i", "POI", "Got position update, but there are no POIs defined. Can't trigger a rule.", 3);
// return;
}
else
Miscellaneous.logEvent("i", "POI", "Closest POI: " + closestPoi.getName() + ", distance : " + String.valueOf(newLocation.distanceTo(closestPoi.getLocation())), 4);
if(
(getActivePoi() != null && getActivePoi().isActivated() && !getActivePoi().reachedPoiArea(newLocation))
|
(closestPoi != null && !closestPoi.isActivated() && closestPoi.reachedPoiArea(newLocation))
)
{
// only an active POI can be left while only a closestPOI can be entered, hence the complex if/else
if(getActivePoi() != null && getActivePoi().isActivated() && !getActivePoi().reachedPoiArea(newLocation))
Miscellaneous.logEvent("i", "POI", "May have left POI " + getActivePoi().getName() + ", checking location accuracy...", 4);
if(closestPoi != null && !closestPoi.isActivated() && closestPoi.reachedPoiArea(newLocation))
Miscellaneous.logEvent("i", "POI", "May have entered POI " + closestPoi.getName() + ", checking location accuracy...", 4);
if(forceApply)
{
Miscellaneous.logEvent("i", parentService.getResources().getString(R.string.forcedLocationUpdate), parentService.getResources().getString(R.string.forcedLocationUpdateLong), 4);
// only an active POI can be left while only a closestPOI can be entered, hence the complex if/else
if(getActivePoi() != null && getActivePoi().isActivated() && !getActivePoi().reachedPoiArea(newLocation))
{
addPositionToRingBuffer(newLocation);
getActivePoi().deactivate(parentService);
}
if(closestPoi != null && !closestPoi.isActivated() && closestPoi.reachedPoiArea(newLocation))
{
addPositionToRingBuffer(newLocation);
closestPoi.activate(parentService);
}
}
else if(newLocation.hasAccuracy() && newLocation.getAccuracy() > Settings.satisfactoryAccuracyNetwork && !newLocation.getProvider().equals(LocationManager.GPS_PROVIDER))
{
Miscellaneous.logEvent("i", "POI", "Location update with unsatisfactory accuracy: " + String.valueOf(newLocation.getAccuracy()) + ", demanded: " + String.valueOf(Settings.satisfactoryAccuracyNetwork), 4);
if(!skipVerfication)
{
if(PointOfInterest.isPoiInRelevantRange(newLocation))
startGpsMeasurement(parentService);
else
{
Miscellaneous.logEvent("i", "POI", "Applying update with unsatisfactory accuracy because no defined location is in a relevant range.", 4);
positionUpdate(newLocation, parentService, true, false);
}
}
else
{
Miscellaneous.logEvent("i", "POI", "Location update with unsatisfactory accuracy, but skipping verfication as requested. Effectively ignoring this update. It's probably from a passive source. Verifying it would cost battery.", 4);
}
}
else
{
Miscellaneous.logEvent("i", "POI", "Location update with acceptable accuracy.", 4);
/* It may be that a previous location wasn't accurate enough, we now got a better location via network,
* but the GPS listener is still active and trying to find out a precise location. We need to deactivate
* it if we are here
*/
if(gpsLocationListenerArmed)
stopGpsMeasurement();
// only an active POI can be left while only a closestPOI can be entered, hence the complex if/else
if(getActivePoi() != null && getActivePoi().isActivated() && !getActivePoi().reachedPoiArea(newLocation))
{
addPositionToRingBuffer(newLocation);
getActivePoi().deactivate(parentService);
}
if(closestPoi != null && !closestPoi.isActivated() && closestPoi.reachedPoiArea(newLocation))
{
addPositionToRingBuffer(newLocation);
closestPoi.activate(parentService);
}
}
}
}
else
Miscellaneous.logEvent("e", "POI", "Given location is null. Aborting.", 3);
}
public Boolean reachedPoiArea(Location currentLocation)
{
float distance = this.location.distanceTo(currentLocation);
if(distance < this.radius)
{
return true;
}
else
{
return false;
}
}
public void activate(AutomationService parentService)
{
if(!this.isActivated())
{
// Deactivate all others in case nobody deactivated them
for(int i = 0; i < pointOfInterestCollection.size(); i++)
pointOfInterestCollection.get(i).deactivate(parentService);
/*
ConcurrentModificationErrors have been seen when using this method: for(PointOfInterest onePoi : pointOfInterestCollection)
Tue Nov 20 19:21:50 GMT+01:00 2018: e / Automation / java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at com.jens.automation2.PointOfInterest.activate(PointOfInterest.java:227)
at com.jens.automation2.PointOfInterest.positionUpdate(PointOfInterest.java:199)
at com.jens.automation2.location.LocationProvider.setCurrentLocation(LocationProvider.java:126)
at com.jens.automation2.location.LocationProvider$MyPassiveLocationListener.onLocationChanged(LocationProvider.java:289)
at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:291)
at android.location.LocationManager$ListenerTransport.-wrap0(Unknown Source:0)
at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:236)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
*/
this.activated = true;
Settings.lastActivePoi = this;
Settings.writeSettings(parentService);
Miscellaneous.logEvent("i", "POI", "Reached POI " + this.getName() + ". Checking if there's a rule that applies to that.", 2);
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.pointOfInterest);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByPoi(this);
if(ruleCandidates.size()==0)
{
Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " not found in ANY rule.", 2);
}
else
{
Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " found in " + ruleCandidates.size() + " rule(s).", 2);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).haveEnoughPermissions() && ruleCandidates.get(i).getsGreenLight(parentService))
{
Miscellaneous.logEvent("i", "POI", "Rule " + ruleCandidates.get(i).getName() + " applies for entering POI " + this.getName() + ".", 2);
ruleCandidates.get(i).activate(parentService, false);
}
}
}
Miscellaneous.logEvent("i", "POI", "Reached POI " + this.getName() + ". Done checking POI rules.", 2);
parentService.updateNotification();
ActivityMainScreen.updateMainScreen();
}
}
public void deactivate(AutomationService parentService)
{
if(this.isActivated())
{
this.activated=false; //has to stay before Rule.applies()
Settings.lastActivePoi = null;
Settings.writeSettings(parentService);
Miscellaneous.logEvent("i", "POI", "Left POI " + this.getName() + ". Checking if there's a rule that applies to that.", 2);
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.pointOfInterest);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByPoi(this);
if(ruleCandidates.size()==0)
{
Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " not found in ANY rule.", 2);
}
else
{
Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " found in " + ruleCandidates.size() + " rule(s).", 2);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).haveEnoughPermissions() && ruleCandidates.get(i).getsGreenLight(parentService))
{
Miscellaneous.logEvent("i", "POI", "Rule " + ruleCandidates.get(i).getName() + " applies for leaving POI " + this.getName() + ".", 2);
ruleCandidates.get(i).activate(parentService, false);
}
}
}
parentService.updateNotification();
ActivityMainScreen.updateMainScreen();
}
}
public static PointOfInterest getClosestPOI(Location currentLocation)// throws Exception
{
// return the currently closed one of all saved points of interest
if(pointOfInterestCollection.size() == 0)
{
//throw new Exception("No points of interest defined.");
//Toast.makeText(context, "No points of interest defined.", Toast.LENGTH_LONG).show();
return null;
}
else if(pointOfInterestCollection.size() == 1)
return pointOfInterestCollection.get(0);
else
{
double distance = pointOfInterestCollection.get(0).location.distanceTo(currentLocation);
PointOfInterest closestPoi = pointOfInterestCollection.get(0);
distance = (int) currentLocation.distanceTo(pointOfInterestCollection.get(0).location);
for(int i=1; i<pointOfInterestCollection.size(); i++)
{
if(currentLocation.distanceTo(pointOfInterestCollection.get(i).location) < distance)
{
distance = currentLocation.distanceTo(pointOfInterestCollection.get(i).location);
closestPoi = pointOfInterestCollection.get(i);
}
}
return closestPoi;
}
}
/** Determines if a POI is in any relevant range. Doesn't say if one is
* reached, but can help decide if it's worth activating GPS to be sure.
* @param currentLocation
* @return
*/
public static boolean isPoiInRelevantRange(Location currentLocation)
{
/*
* Radius
* + Precision
* + Self defined value
*/
double distance;
double minimumDistance;
for(PointOfInterest poi : PointOfInterest.getPointOfInterestCollection())
{
distance = poi.getLocation().distanceTo(currentLocation);
if(currentLocation.hasAccuracy())
minimumDistance = currentLocation.getAccuracy();
else
minimumDistance = 0;
minimumDistance += poi.getRadius();
if(distance < minimumDistance)
{
Miscellaneous.logEvent("i", "POI", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.poiCouldBeInRange), poi.getName()), 4);
return true;
}
}
return false;
}
public static void loadPoisFromFile()
{
try
{
if(XmlFileInterface.settingsFile.exists())
{
Miscellaneous.logEvent("i", "POI", "SettingsFile " + XmlFileInterface.settingsFile.getPath() + " exists. Loading POIs from File.", 4);
XmlFileInterface.readFile();
}
else
{
Miscellaneous.logEvent("w", "POI", "SettingsFile " + XmlFileInterface.settingsFile.getPath() + " doesn't exist.", 4);
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
public static boolean writePoisToFile()
{
return XmlFileInterface.writeFile();
}
@Override
public String toString()
{
return this.getName();
}
public String toStringLong()
{
return this.name + ": " + String.valueOf(this.radius) + " meters around " + String.valueOf(this.location.getLatitude() + " / " + String.valueOf(this.location.getLongitude()));
}
public boolean create(Context context)
{
for(PointOfInterest poi : PointOfInterest.pointOfInterestCollection)
{
if (poi.getName().equals(this.getName()))
{
Toast.makeText(context, context.getResources().getString(R.string.anotherPoiByThatName), Toast.LENGTH_LONG).show();
return false;
}
}
if(plausibilityCheck())
{
Miscellaneous.logEvent("i", "Creating POI", this.toStringLong(), 3);
PointOfInterest.pointOfInterestCollection.add(this);
PointOfInterest.writePoisToFile();
AutomationService service = AutomationService.getInstance();
if(service != null)
{
service.applySettingsAndRules();
//Easiest way to check for changes in location, reset the last known location.
service.getLocationProvider().setCurrentLocation(service.getLocationProvider().getCurrentLocation(), true);
}
return true;
}
return false;
}
public boolean change(Context context)
{
try
{
/*
Check for change of rule name START
*/
if (this.oldName != null && !this.oldName.equals(this.name)) // catch oldName being null
{
//Name has changed. We need to look for rules that reference it by its name and update those references
// Check if the name is still available
int counter = 0; // this method should only be a temporary workaround, directly editing the referenced object may cause problems until reloading the config file
for (PointOfInterest poi : PointOfInterest.pointOfInterestCollection)
if (poi.getName().equals(this.getName()))
{
counter++;
}
if (counter > 1)
{
Toast.makeText(context, context.getResources().getString(R.string.anotherPoiByThatName), Toast.LENGTH_LONG).show();
return false;
}
// Check if rules reference this poi
ArrayList<Rule> rulesThatReferenceMe = Rule.findRuleCandidatesByPoi(this);
if (rulesThatReferenceMe.size() > 0)
{
for (Rule oneRule : rulesThatReferenceMe)
{
for (Trigger oneTrigger : oneRule.getTriggerSet())
{
if (oneTrigger.getTriggerType() == Trigger_Enum.pointOfInterest)
{
oneTrigger.setPointOfInterest(this);
// We don't need to save the file. This will happen anyway in PointOfInterest.writePoisToFile() below.
}
}
}
}
}
/*
Check for change of rule name END
*/
if(plausibilityCheck())
{
Miscellaneous.logEvent("i", "Changing POI", "Old name: " + this.oldName + ", new data: " + this.toStringLong(), 3);
if(PointOfInterest.writePoisToFile())
{
AutomationService service = AutomationService.getInstance();
if (service != null)
{
try
{
service.applySettingsAndRules();
//Easiest way to check for changes in location, reset the last known location.
service.getLocationProvider().setCurrentLocation(service.getLocationProvider().getCurrentLocation(), true);
}
catch(Exception e)
{
// Just log the event. This should not cause an interruption in the program flow.
Miscellaneous.logEvent("e", "save POI", "Error when trying to apply settings and rules: " + Log.getStackTraceString(e), 2);
}
}
return true;
}
else
return false;
}
}
catch(Exception e)
{
Toast.makeText(context, context.getResources().getString(R.string.unknownError), Toast.LENGTH_LONG).show();
}
return false;
}
public boolean delete(Context context)
{
//Check if there's a rule that contains this poi
ArrayList<Rule> rulesThatReferenceMe = Rule.findRuleCandidatesByPoi(this);
if(rulesThatReferenceMe.size() > 0)
{
String rulesString = "";
for(Rule rule : rulesThatReferenceMe)
rulesString += rule.getName() + "; ";
rulesString = rulesString.substring(0, rulesString.length()-2);
Toast.makeText(context, String.format(context.getResources().getString(R.string.poiStillReferenced), rulesString), Toast.LENGTH_LONG).show();
return false;
}
else
{
PointOfInterest.pointOfInterestCollection.remove(this);
PointOfInterest.writePoisToFile();
AutomationService service = AutomationService.getInstance();
try
{
service.applySettingsAndRules();
//Easiest way to check for changes in location, reset the last known location.
service.getLocationProvider().setCurrentLocation(service.getLocationProvider().getCurrentLocation(), true);
}
catch(Exception e)
{
// Just log the event. This should not cause an interruption in the program flow.
Miscellaneous.logEvent("e", "save POI", "Error when trying to apply settings and rules: " + Log.getStackTraceString(e), 2);
}
return true;
}
}
public static PointOfInterest getByName(String searchName) throws Exception
{
for(PointOfInterest poi : pointOfInterestCollection)
{
if(poi.name.equals(searchName))
return poi;
}
throw new Exception("PointOfInterest with name " + searchName + " not found.");
}
public static String[] getNamesInArray()
{
ArrayList<String> nameList = new ArrayList<String>();
for(PointOfInterest poi : pointOfInterestCollection)
{
nameList.add(poi.name);
}
return (String[])nameList.toArray(new String[pointOfInterestCollection.size()]);
}
public static PointOfInterest getActivePoi()
{
for(PointOfInterest poi : PointOfInterest.pointOfInterestCollection)
{
if(poi.isActivated())
return poi;
}
return null;
}
@Override
public int compareTo(PointOfInterest another)
{
return this.getName().compareTo(another.getName());
}
private static boolean addPositionToRingBuffer(Location newLocation)
{
/*
* This method's purpose is to record the last n positions and check if they are different.
* In reality you will never get the exact same position twice. If you do the location engine
* seems to have hung up.
*/
try
{
if(++locationRingBufferLastPosition > locationRingBuffer.length-1)
locationRingBufferLastPosition = 0;
Miscellaneous.logEvent("i", "Ringbuffer.", "Adding location " + String.valueOf(newLocation.getLatitude()) + " / " + String.valueOf(newLocation.getLongitude()) + " to ringbuffer at index " + String.valueOf(locationRingBufferLastPosition), 5);
locationRingBuffer[locationRingBufferLastPosition] = newLocation;
/*
* Return values:
* true if the new location is different to the last one
* false if we get repeated values, comparing all values
*
* false indicates problems with hangups in getting locations.
*/
int counter = locationRingBufferLastPosition+1-1; // make a copy, not a reference
int previousIndex;
do
{
if(counter>0)
previousIndex = counter-1;
else
previousIndex = Settings.locationRingBufferSize-1;
try
{
if(locationRingBuffer[counter].getLatitude() != locationRingBuffer[previousIndex].getLatitude() | locationRingBuffer[counter].getLongitude() != locationRingBuffer[previousIndex].getLongitude())
{
// If location different from last one we're fine.
Miscellaneous.logEvent("w", "Ringbuffer.", "Location has changed from the last one. We\'re fine.", 5);
return true;
}
}
catch(NullPointerException ne)
{
/*
* Just null pointer exception. Ringbuffer isn't filled to its maximum, yet.
*/
return true;
}
if(counter>0)
counter--;
else
counter = Settings.locationRingBufferSize-1;
} while(counter != locationRingBufferLastPosition);
Miscellaneous.logEvent("w", "Ringbuffer", "Location has not changed from the last one. Something\'s odd. Maybe the location engine kind of hung up.", 2);
return false;
}
catch(ArrayIndexOutOfBoundsException e)
{
Miscellaneous.logEvent("e", "Ringbuffer", "Probably not enough values, yet.", 5);
return true;
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Ringbuffer", "Error in ringbuffer: " + Log.getStackTraceString(e), 4);
return true;
}
}
public static class GpsComparisonLocationListener implements LocationListener
{
public AutomationService parent = null;
@Override
public void onLocationChanged(Location up2DateLocation)
{
stopGpsMeasurement();
PointOfInterest.positionUpdate(up2DateLocation, parent, true, false);
Miscellaneous.logEvent("i", "LocationListener", "Disarmed location listener, accuracy reached", 4);
}
@Override
public void onProviderDisabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
// TODO Auto-generated method stub
}
}
private static void startGpsMeasurement(AutomationService parentService)
{
// Arm location updates
if(!gpsLocationListenerArmed)
{
Miscellaneous.logEvent("i", "PointOfInterest", "Unsatisfactory accuracy of network location. Performing comparison measurement via GPS.", 3);
String myGpsComparisonProviderName;
if(Settings.privacyLocationing)
{
Miscellaneous.logEvent("i", "PointOfInterest", parentService.getResources().getString(R.string.enforcingGps), 4);
myGpsComparisonProviderName = LocationManager.GPS_PROVIDER;
}
else
{
// Miscellaneous.logEvent("i", "PointOfInterest", parentService.getResources().getString(R.string.notEnforcingGps), 4);
Criteria crit = new Criteria();
// crit.setPowerRequirement(Criteria.POWER_LOW);
// crit.setAltitudeRequired(false);
// crit.setSpeedRequired(false);
// crit.setBearingRequired(false);
crit.setCostAllowed(true);
crit.setAccuracy(Criteria.ACCURACY_FINE);
gpsComparisonLocationManager = (LocationManager)parentService.getSystemService(parentService.LOCATION_SERVICE);
myGpsComparisonProviderName = gpsComparisonLocationManager.getBestProvider(crit, true);
}
Miscellaneous.logEvent("i", "LocationListener", "Arming location listener, Provider: " + myGpsComparisonProviderName, 4);
gpsComparisonLocationListener = new GpsComparisonLocationListener();
gpsComparisonLocationListener.parent = parentService;
gpsComparisonLocationManager.requestLocationUpdates(myGpsComparisonProviderName, Settings.minimumTimeBetweenUpdate, Settings.minimumDistanceChangeForNetworkUpdate, gpsComparisonLocationListener);
gpsLocationListenerArmed = true;
// set timeout
Message message = new Message();
message.what = 1;
Miscellaneous.logEvent("i", parentService.getResources().getString(R.string.gpsComparison), parentService.getResources().getString(R.string.startingGpsTimeout), 4);
if(timeoutHandler.parentService == null)
timeoutHandler.parentService = parentService;
timeoutHandler.sendMessageDelayed(message, Settings.gpsTimeout * 1000);
timeoutHandlerActive = true;
}
else
Miscellaneous.logEvent("i", "PointOfInterest", "Comparison measurement via GPS requested, but already active.", 3);
}
private static void stopGpsMeasurement()
{
if(gpsLocationListenerArmed)
{
gpsComparisonLocationManager.removeUpdates(gpsComparisonLocationListener);
gpsLocationListenerArmed = false;
}
if(timeoutHandlerActive)
{
timeoutHandler.removeMessages(1);
timeoutHandlerActive = false;
}
}
private static class TimeoutHandler extends Handler
{
public AutomationService parentService = null;
public Location locationToApplyIfGpsFails = null;
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
if(msg.what == 1)
{
Miscellaneous.logEvent("i", parentService.getResources().getString(R.string.gpsComparison), parentService.getResources().getString(R.string.gpsComparisonTimeoutStop), 4);
stopGpsMeasurement();
}
}
}
private boolean plausibilityCheck()
{
double distance, minimumDistance, overlap;
if(this.getName().equals("null"))
{
// Invalid name
String text = Miscellaneous.getAnyContext().getResources().getString(R.string.invalidPoiName);
Miscellaneous.logEvent("w", "POI", text, 2);
Toast.makeText(Miscellaneous.getAnyContext(), text, Toast.LENGTH_LONG).show();
return false;
}
for(PointOfInterest otherPoi : this.getPointOfInterestCollection())
{
distance = otherPoi.getLocation().distanceTo(this.getLocation());
minimumDistance = otherPoi.getRadius()/2 + this.getRadius()/2;
overlap = Math.round(Math.abs(distance - minimumDistance));
if(distance <= minimumDistance && !otherPoi.getName().equals(this.getName()))
{
String text = String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.overlapBetweenPois), otherPoi.getName(), String.valueOf(overlap));
Miscellaneous.logEvent("w", "POI", text, 2);
// Miscellaneous.messageBox("POI", text, Miscellaneous.getAnyContext()).show();
Toast.makeText(Miscellaneous.getAnyContext(), text, Toast.LENGTH_LONG).show();
return false;
}
}
Miscellaneous.logEvent("w", "POI", Miscellaneous.getAnyContext().getResources().getString(R.string.noOverLap), 2);
return true;
}
public static boolean reachedPoiWithActivateWifiRule()
{
PointOfInterest activePoi = PointOfInterest.getActivePoi();
if(activePoi != null)
{
for(Rule rule : Rule.findRuleCandidatesByPoi(activePoi, true))
{
for(Action action : rule.getActionSet())
{
if(action.getAction().equals(Action.Action_Enum.setWifi) && action.getParameter1())
{
// We are at a POI that specifies to enable wifi.
return true;
}
}
}
}
return false;
}
}