Location without Cell Radio

This commit is contained in:
jens 2021-09-07 17:30:45 +02:00
parent cb430b957f
commit a6edab75ce
6 changed files with 156 additions and 109 deletions

View File

@ -29,6 +29,7 @@ import androidx.core.text.HtmlCompat;
import com.jens.automation2.AutomationService.serviceCommands;
import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.CellLocationChangedReceiver;
import com.jens.automation2.location.LocationProvider;
import java.io.File;

View File

@ -22,6 +22,8 @@ import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import com.jens.automation2.receivers.ConnectivityReceiver;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
@ -163,7 +165,7 @@ public class ActivityManagePoi extends Activity
locationSearchStart = Calendar.getInstance();
startTimeout();
if(!Settings.privacyLocationing)
if(!Settings.privacyLocationing || !ConnectivityReceiver.isDataConnectionAvailable(AutomationService.getInstance()))
{
Miscellaneous.logEvent("i", "POI Manager", getResources().getString(R.string.logGettingPositionWithProvider) + " " + provider1, 3);
myLocationManager.requestLocationUpdates(provider1, 500, Settings.satisfactoryAccuracyNetwork, myLocationListenerNetwork);

View File

@ -333,7 +333,7 @@ public class AutomationService extends Service implements OnInitListener
protected void startLocationProvider()
{
if(ActivityPermissions.havePermission("android.permission.ACCESS_COARSE_LOCATION", AutomationService.this))
if(ActivityPermissions.havePermission(Manifest.permission.ACCESS_COARSE_LOCATION, AutomationService.this))
myLocationProvider = new LocationProvider(this); //autostart with this (only) constructor
}
@ -631,7 +631,10 @@ public class AutomationService extends Service implements OnInitListener
// myNotification.setLatestEventInfo(instance, "Automation", textToDisplay, myPendingIntent);
// }
// else
// {
// {
if(notificationBuilder == null)
notificationBuilder = createDefaultNotificationBuilder();
notificationBuilder.setContentText(textToDisplay);
notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));

View File

@ -144,14 +144,14 @@ public class ReceiverCoordinator
ConnectivityReceiver.startConnectivityReceiver(AutomationService.getInstance());
// startCellLocationChangedReceiver
if(!ConnectivityReceiver.isAirplaneMode(AutomationService.getInstance()) && WifiBroadcastReceiver.mayCellLocationReceiverBeActivated() && (Rule.isAnyRuleUsing(Trigger.Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.speed)))
if(!ConnectivityReceiver.isAirplaneMode(AutomationService.getInstance()) && WifiBroadcastReceiver.mayCellLocationReceiverBeActivated() && (Rule.isAnyRuleUsing(Trigger.Trigger_Enum.pointOfInterest) || Rule.isAnyRuleUsing(Trigger.Trigger_Enum.speed)))
{
if(!Miscellaneous.googleToBlameForLocation(true))
CellLocationChangedReceiver.startCellLocationChangedReceiver();
}
// startBatteryReceiver
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.charging) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.usb_host_connection) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.batteryLevel))
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.charging) || Rule.isAnyRuleUsing(Trigger.Trigger_Enum.usb_host_connection) || Rule.isAnyRuleUsing(Trigger.Trigger_Enum.batteryLevel))
BatteryReceiver.startBatteryReceiver(AutomationService.getInstance());
// startAlarmListener

View File

@ -130,6 +130,21 @@ public class CellLocationChangedReceiver extends PhoneStateListener
}
}
public static boolean isCellLocationChangedReceiverPossible()
{
if(telephonyManager == null)
telephonyManager = (TelephonyManager) AutomationService.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
if(
ConnectivityReceiver.isAirplaneMode(AutomationService.getInstance())
||
telephonyManager.getSimState() != TelephonyManager.SIM_STATE_READY
)
return false;
else
return true;
}
public Location getLocation(String accuracy)
{
Criteria crit = new Criteria();
@ -137,7 +152,7 @@ public class CellLocationChangedReceiver extends PhoneStateListener
String myProviderName;
// If privacy mode or no data connection available
if(Settings.privacyLocationing | !ConnectivityReceiver.isDataConnectionAvailable(AutomationService.getInstance()))
if(Settings.privacyLocationing || !ConnectivityReceiver.isDataConnectionAvailable(AutomationService.getInstance()))
{
Miscellaneous.logEvent("i", "CellLocation", Miscellaneous.getAnyContext().getResources().getString(R.string.enforcingGps), 4);
myProviderName = LocationManager.GPS_PROVIDER;
@ -175,6 +190,9 @@ public class CellLocationChangedReceiver extends PhoneStateListener
}
else
{
if(myLocationManager == null)
myLocationManager = (LocationManager) AutomationService.getInstance().getSystemService(Context.LOCATION_SERVICE);
if(!myLocationManager.isProviderEnabled(myProviderName))
{
if(myProviderName.equals(LocationManager.NETWORK_PROVIDER))
@ -226,13 +244,11 @@ public class CellLocationChangedReceiver extends PhoneStateListener
return currentLocation;
}
public void setCurrentLocation(Location currentLocation)
{
this.currentLocation = currentLocation;
}
public class MyLocationListener implements LocationListener
{
@Override
@ -322,12 +338,12 @@ public class CellLocationChangedReceiver extends PhoneStateListener
{
if(telephonyManager == null)
telephonyManager = (TelephonyManager) AutomationService.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
try
{
if(!cellLocationListenerActive)
{
if(!ConnectivityReceiver.isAirplaneMode(AutomationService.getInstance()))
if(!ConnectivityReceiver.isAirplaneMode(AutomationService.getInstance()) && telephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY)
{
if(WifiBroadcastReceiver.mayCellLocationReceiverBeActivated())
{
@ -356,7 +372,7 @@ public class CellLocationChangedReceiver extends PhoneStateListener
Miscellaneous.logEvent("w", "cellReceiver", "Wanted to activate CellLocationChangedReceiver, but Wifi-Receiver says not to.", 4);
}
else
Miscellaneous.logEvent("i", "cellReceiver", "Not starting cellLocationListener because Airplane mode is active.", 4);
Miscellaneous.logEvent("i", "cellReceiver", "Not starting cellLocationListener because Airplane mode is active or SIM_STATE is not ready.", 4);
}
}
catch(Exception ex)
@ -409,5 +425,4 @@ public class CellLocationChangedReceiver extends PhoneStateListener
&&
ActivityPermissions.havePermission("android.permission.ACCESS_WIFI_STATE", Miscellaneous.getAnyContext());
}
}
}

View File

@ -7,6 +7,7 @@ import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.jens.automation2.ActivityMainScreen;
@ -26,13 +27,9 @@ import java.util.Calendar;
public class LocationProvider
{
protected static boolean passiveLocationListenerActive = false;
protected static LocationListener passiveLocationListener;
protected static LocationProvider locationProviderInstance = null;
protected AutomationService parentService;
public AutomationService getParentService()
{
@ -109,123 +106,128 @@ public class LocationProvider
public void setCurrentLocation(Location newLocation, boolean skipVerification)
{
Miscellaneous.logEvent("i", "Location", "Setting location.", 4);
currentLocation = newLocation;
currentLocationStaticCopy = newLocation;
Miscellaneous.logEvent("i", "LocationListener", "Giving update to POI class", 4);
PointOfInterest.positionUpdate(newLocation, parentService, false, skipVerification);
try
if(newLocation != null)
{
if(
locationList.size() >= 1
&&
locationList.get(locationList.size()-1).getTime() == newLocation.getTime()
&&
locationList.get(locationList.size()-1).getProvider().equals(newLocation.getProvider())
Miscellaneous.logEvent("i", "Location", "Setting location.", 4);
currentLocation = newLocation;
currentLocationStaticCopy = newLocation;
Miscellaneous.logEvent("i", "LocationListener", "Giving update to POI class", 4);
PointOfInterest.positionUpdate(newLocation, parentService, false, skipVerification);
try
{
if (
locationList.size() >= 1
&&
locationList.get(locationList.size() - 1).getTime() == newLocation.getTime()
&&
locationList.get(locationList.size() - 1).getProvider().equals(newLocation.getProvider())
)
{
// This is a duplicate update, do not store it
Miscellaneous.logEvent("i", "LocationListener", "Duplicate location, ignoring.", 4);
}
else
{
Miscellaneous.logEvent("i", "Speed", "Commencing speed calculation.", 4);
// This part keeps the last two location entries to determine the current speed.
locationList.add(newLocation);
if(newLocation.hasSpeed())
{
Miscellaneous.logEvent("i", "Speed", "Location has speed, taking that: " + String.valueOf(newLocation.getSpeed()) + " km/h", 4);
setSpeed(newLocation.getSpeed()); // Take the value that came with the location, that should be more precise
// This is a duplicate update, do not store it
Miscellaneous.logEvent("i", "LocationListener", "Duplicate location, ignoring.", 4);
}
else
{
speedCalculation:
if (locationList.size() >= 2)
Miscellaneous.logEvent("i", "Speed", "Commencing speed calculation.", 4);
// This part keeps the last two location entries to determine the current speed.
locationList.add(newLocation);
if (newLocation.hasSpeed())
{
while (locationList.size() > 2)
Miscellaneous.logEvent("i", "Speed", "Location has speed, taking that: " + String.valueOf(newLocation.getSpeed()) + " km/h", 4);
setSpeed(newLocation.getSpeed()); // Take the value that came with the location, that should be more precise
}
else
{
speedCalculation:
if (locationList.size() >= 2)
{
// Remove all entries except for the last 2
Miscellaneous.logEvent("i", "Speed", "About to delete oldest position record until only 2 left. Currently have " + String.valueOf(locationList.size()) + " records.", 4);
locationList.remove(0);
}
while (locationList.size() > 2)
{
// Remove all entries except for the last 2
Miscellaneous.logEvent("i", "Speed", "About to delete oldest position record until only 2 left. Currently have " + String.valueOf(locationList.size()) + " records.", 4);
locationList.remove(0);
}
/*
The two most recent locations in the list must have a usable accuracy.
*/
for(int i = 0; i < 2; i++)
{
if
for (int i = 0; i < 2; i++)
{
if
(
(locationList.get(i).getProvider().equals(LocationManager.GPS_PROVIDER) && locationList.get(i).getAccuracy() > Settings.satisfactoryAccuracyGps)
||
(locationList.get(i).getProvider().equals(LocationManager.NETWORK_PROVIDER) && locationList.get(i).getAccuracy() > Settings.satisfactoryAccuracyNetwork)
(locationList.get(i).getProvider().equals(LocationManager.GPS_PROVIDER) && locationList.get(i).getAccuracy() > Settings.satisfactoryAccuracyGps)
||
(locationList.get(i).getProvider().equals(LocationManager.NETWORK_PROVIDER) && locationList.get(i).getAccuracy() > Settings.satisfactoryAccuracyNetwork)
)
{
Miscellaneous.logEvent("i", "Speed", "Not using 2 most recent locations for speed calculation because at least one does not have a satisfactory accuracy: " + locationList.get(i).toString(), 4);
break speedCalculation;
}
}
Miscellaneous.logEvent("i", "Speed", "Trying to calculate speed based on the last locations.", 4);
double currentSpeed;
long timeDifferenceInSeconds = (Math.abs(locationList.get(locationList.size() - 2).getTime() - locationList.get(locationList.size() - 1).getTime())) / 1000; //milliseconds
if (timeDifferenceInSeconds <= Settings.speedMaximumTimeBetweenLocations * 60)
{
double distanceTraveled = locationList.get(locationList.size() - 2).distanceTo(locationList.get(locationList.size() - 1)); //results in meters
if (timeDifferenceInSeconds == 0)
{
Miscellaneous.logEvent("w", "Speed", "No time passed since last position. Can't calculate speed here.", 4);
return;
{
Miscellaneous.logEvent("i", "Speed", "Not using 2 most recent locations for speed calculation because at least one does not have a satisfactory accuracy: " + locationList.get(i).toString(), 4);
break speedCalculation;
}
}
currentSpeed = distanceTraveled / timeDifferenceInSeconds * 3.6; // convert m/s --> km/h
Miscellaneous.logEvent("i", "Speed", "Trying to calculate speed based on the last locations.", 4);
double currentSpeed;
long timeDifferenceInSeconds = (Math.abs(locationList.get(locationList.size() - 2).getTime() - locationList.get(locationList.size() - 1).getTime())) / 1000; //milliseconds
if (timeDifferenceInSeconds <= Settings.speedMaximumTimeBetweenLocations * 60)
{
double distanceTraveled = locationList.get(locationList.size() - 2).distanceTo(locationList.get(locationList.size() - 1)); //results in meters
if (timeDifferenceInSeconds == 0)
{
Miscellaneous.logEvent("w", "Speed", "No time passed since last position. Can't calculate speed here.", 4);
return;
}
currentSpeed = distanceTraveled / timeDifferenceInSeconds * 3.6; // convert m/s --> km/h
/*
Due to strange factors the time difference might be 0 resulting in mathematical error.
*/
if (Double.isInfinite(currentSpeed) | Double.isNaN(currentSpeed))
Miscellaneous.logEvent("i", "Speed", "Error while calculating speed.", 4);
else
{
Miscellaneous.logEvent("i", "Speed", "Current speed: " + String.valueOf(currentSpeed) + " km/h", 2);
setSpeed(currentSpeed);
// execute matching rules containing speed
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesBySpeed();
for (Rule oneRule : ruleCandidates)
if (Double.isInfinite(currentSpeed) | Double.isNaN(currentSpeed))
Miscellaneous.logEvent("i", "Speed", "Error while calculating speed.", 4);
else
{
if (oneRule.applies(this.getParentService()))
oneRule.activate(getParentService(), false);
Miscellaneous.logEvent("i", "Speed", "Current speed: " + String.valueOf(currentSpeed) + " km/h", 2);
setSpeed(currentSpeed);
// execute matching rules containing speed
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesBySpeed();
for (Rule oneRule : ruleCandidates)
{
if (oneRule.applies(this.getParentService()))
oneRule.activate(getParentService(), false);
}
}
}
else
Miscellaneous.logEvent("i", "Speed", "Last two locations are too far apart in terms of time. Cannot use them for speed calculation.", 4);
}
else
Miscellaneous.logEvent("i", "Speed", "Last two locations are too far apart in terms of time. Cannot use them for speed calculation.", 4);
}
else
{
Miscellaneous.logEvent("w", "Speed", "Don't have enough values for speed calculation, yet.", 3);
{
Miscellaneous.logEvent("w", "Speed", "Don't have enough values for speed calculation, yet.", 3);
}
}
}
}
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Speed", "Error during speed calculation: " + Log.getStackTraceString(e), 3);
}
catch (Exception e)
{
Miscellaneous.logEvent("e", "Speed", "Error during speed calculation: " + Log.getStackTraceString(e), 3);
}
AutomationService.updateNotification();
AutomationService.updateNotification();
if(AutomationService.isMainActivityRunning(parentService))
ActivityMainScreen.updateMainScreen();
if (AutomationService.isMainActivityRunning(parentService))
ActivityMainScreen.updateMainScreen();
}
else
Miscellaneous.logEvent("w", "Location", "New location given is null. Ignoring.", 5);
}
public void startLocationService()
@ -244,13 +246,37 @@ public class LocationProvider
if(Settings.positioningEngine == 0)
{
// startCellLocationChangedReceiver
if (!ConnectivityReceiver.isAirplaneMode(this.parentService) && WifiBroadcastReceiver.mayCellLocationReceiverBeActivated() && (Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger_Enum.speed)))
CellLocationChangedReceiver.startCellLocationChangedReceiver();
// startPassiveLocationListener
if(Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger_Enum.speed))
{
// TelephonyManager telephonyManager = (TelephonyManager) AutomationService.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
// startCellLocationChangedReceiver
if (CellLocationChangedReceiver.isCellLocationChangedReceiverPossible())
{
if (WifiBroadcastReceiver.mayCellLocationReceiverBeActivated())
CellLocationChangedReceiver.startCellLocationChangedReceiver();
}
else
{
/*
Reasons why we may end up here:
- Airplane mode is active
- No phone module present (pure wifi device)
- No SIM card is inserted or it's not unlocked
We'd have to try GPS now to get an initial position.
For permanent use there is no way we could know when it
would make sense to check the position again.
*/
// Trigger a one-time-position-search
Location loc = CellLocationChangedReceiver.getInstance().getLocation("fine");
LocationProvider.getInstance().setCurrentLocation(loc, true);
}
// startPassiveLocationListener
startPassiveLocationListener();
}
}
else
{