From a6edab75ce89d53a819fdfb2e576f230c4d3782e Mon Sep 17 00:00:00 2001 From: jens Date: Tue, 7 Sep 2021 17:30:45 +0200 Subject: [PATCH] Location without Cell Radio --- .../jens/automation2/ActivityMainScreen.java | 1 + .../jens/automation2/ActivityManagePoi.java | 4 +- .../jens/automation2/AutomationService.java | 7 +- .../jens/automation2/ReceiverCoordinator.java | 4 +- .../location/CellLocationChangedReceiver.java | 31 ++- .../location/LocationProvider.java | 218 ++++++++++-------- 6 files changed, 156 insertions(+), 109 deletions(-) diff --git a/app/src/main/java/com/jens/automation2/ActivityMainScreen.java b/app/src/main/java/com/jens/automation2/ActivityMainScreen.java index 30b24ed..ca9ecaf 100644 --- a/app/src/main/java/com/jens/automation2/ActivityMainScreen.java +++ b/app/src/main/java/com/jens/automation2/ActivityMainScreen.java @@ -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; diff --git a/app/src/main/java/com/jens/automation2/ActivityManagePoi.java b/app/src/main/java/com/jens/automation2/ActivityManagePoi.java index fe69a38..fe80fa9 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManagePoi.java +++ b/app/src/main/java/com/jens/automation2/ActivityManagePoi.java @@ -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); diff --git a/app/src/main/java/com/jens/automation2/AutomationService.java b/app/src/main/java/com/jens/automation2/AutomationService.java index 1137e78..4096d26 100644 --- a/app/src/main/java/com/jens/automation2/AutomationService.java +++ b/app/src/main/java/com/jens/automation2/AutomationService.java @@ -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)); diff --git a/app/src/main/java/com/jens/automation2/ReceiverCoordinator.java b/app/src/main/java/com/jens/automation2/ReceiverCoordinator.java index 4984e48..9921ba1 100644 --- a/app/src/main/java/com/jens/automation2/ReceiverCoordinator.java +++ b/app/src/main/java/com/jens/automation2/ReceiverCoordinator.java @@ -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 diff --git a/app/src/main/java/com/jens/automation2/location/CellLocationChangedReceiver.java b/app/src/main/java/com/jens/automation2/location/CellLocationChangedReceiver.java index 9ac60fd..a738d67 100644 --- a/app/src/main/java/com/jens/automation2/location/CellLocationChangedReceiver.java +++ b/app/src/main/java/com/jens/automation2/location/CellLocationChangedReceiver.java @@ -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()); } -} - +} \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/location/LocationProvider.java b/app/src/main/java/com/jens/automation2/location/LocationProvider.java index 0d7578e..8a2956e 100644 --- a/app/src/main/java/com/jens/automation2/location/LocationProvider.java +++ b/app/src/main/java/com/jens/automation2/location/LocationProvider.java @@ -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 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 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 {