Unable to perform a WiFi scan in the background - xamarin.android

I'm attempting to rewrite an old app that gathers WiFi signal data and uses it for internal positioning. To be actually usable, it has to be able to do this while it is not the active app and/or while the screen is off.
Getting the WiFi scanning working was very straightforward, and as long as my app is active in the foreground I consistently get scan results every 4 seconds, indefinitely. But I'm running into problems with getting it to continue doing this in the background.
The moment my app is not active or I turn off the screen:
WifiManager.StartScan begins returning false.
My BroadcastReceiver's OnReceive method is no longer triggered.
WifiManager.ScanResults is empty - it doesn't even have old results in it.
These all resume working as expected once I switch back to the app or unlock my device, which is a Pixel 6a running Android 12.
From half a day of searching, I have already tried the following:
Running this as a Foreground Service with a persistent notification.
Acquiring a wake lock and wifi lock.
All adaptive battery features are disabled on the device.
Battery usage for the app is set to Unrestricted.
Wi-Fi scan throttling is disabled on the device.
adb has been used to disable doze on the device.
All the necessary permissions (as documented) are in the manifest, requested by the app, and have been allowed.
Confirmed the Foreground Service I start is still executing.
It's not clear if I am doing something incorrectly/missing something, or if I'm simply hitting an insurmountable restriction that Android is putting on WiFi scanning.

According to your description, the only casue I can think about is that you didn't get the Background Location Permission for your application.
At first, please check if the target version in your App is Android 10.0 or heigher or not. If so, you not only need to add the ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions but also the ACCESS_BACKGROUND_LOCATION permission and make sure you can access location in the background.
If the target verison is lower than Android 10.0, please check if you added the permission ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION in the AndroidManifest.xml or not. Then make sure the device show the dialog and you choose the selection which is accessing the location all the time.
For more information, please check the official document about accessing location in the background

Related

React Native iOS app restart on reboot

I want to create an iOS app using React Native. One of the primary features of the app is that it runs constantly in the background. It also requires using GPS btw (in case that is important).
I have had a number of devs tell me its not possible to do this for iOS, however I have read that it is do-able.
Is this possible to do in the iOS environment? Mainly, if the app is running when the phone is powered off, can you make it open when the device is restarted without the user opening it?
I should say that I am a RN novice and any help is much appreciated.
If your app gets permission to get location while it's not in the foreground, then you will get periodic updates and some time to process it.
For example, if you are giving driving directions.
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW10
If there is no good user benefit for you to get the location in the background constantly, you might be rejected. Apple suggests region monitoring instead
iOS supports the delivery of location events to apps that are suspended or no longer running. The delivery of location events in the background supports apps whose functionality would be impaired without them, so configure your app to receive background events only when doing so provides a tangible benefit to the user. For example, a turn-by-turn navigation app needs to track the user’s position at all times and notify the user when it’s time to make the next turn. If your app can make do with alternate means, such as region monitoring, it should do so.
I have no idea how RN wraps this behavior, but no matter what it does (or what a plugin might do), the core iOS behavior is how it is described in that URL.
I verified yesterday (at least on iOS 11.2 simulator) that automatically restarting the app (and the location tracking) after phone reboot works.
The key point is that startMonitoringSignificantLocationChanges needs to be on to wake up the app after reboot. For me the difficult part was figuring out when to turn it on, because I couldn't find a reliable way to detect when the phone is being rebooted or run any code at that point. However, based on initial testing it looks like startMonitoringSignificantLocationChanges is independent and doesn't negatively impact the usual location updates, so now I just leave it on all the time and toggle startUpdatingLocation / stopUpdatingLocation on top of it based on Core Motion-detected activity.
Otherwise requirements are the same as for any location tracking on the background, i.e. handle permissions and don't process too much. Apple documentation explains how to detect that the app was relaunched by a location event.
Here's a react native module which basically helps you achieve what you're describing: https://github.com/transistorsoft/react-native-background-geolocation

Sometimes no updates from location-service ios

Our app is fitness-related. It uses location services in the background. The user clicks a button when the app is in foreground and then we trigger startUpdatingLocation. We initially set the accuracy to kCLLocationAccuracyNearestTenMeters (force GPS) and distance filter to 1500. After that the user locks the screen and put the mobile in a pocket.
The problem is that this doesn't work for 5-10% of our ios users (it works perfectly for the rest). We have logged when the location update event occur and we can see that it doesn't trigger. When the user clicks the button in the foreground we also setup a timer to trigger x minutes later and the timer does not trigger either (for the users it doesn't work for).
We have not been able to reproduce the issue in-house, so it's hard to do good troubleshooting.
I know that the OS can terminate the app if the user is using other apps in the foreground, but from what I understand it may call applicationWillTerminate and we have not seen any logs from that event being called. However it still might be the case that the OS decides to terminate our app. If that is the case, what can we do about it? Our app is wanted by the user and starting another app (for example taking a photo) does not mean that the user want our app to stop working. So the question now is if it's related to that OS terminates our app, is there anything we can do?
Notes:
pausesLocationUpdatesAutomatically is to NO
Background App Refresh is enabled
We have not enabled gps or location-services in UIRequiredDeviceCapabilities (plist) since our app can be used in two ways. With or without GPS.
We require "always on"-setting to be enabled when the user clicks the button in the foreground.
We have confirmed that backgroundTimeRemaining property returns the max value (indicating that the app is allowed to run in the background indefinitely)
The problem occur for a variety of ios versions both 8.x and 9.x.

iBeacon background monitoring stops working

I have an app that monitors iBeacons entry/exit events. When it receives an event it forwards the event off to a server. The app continues to work (e.g., the server continues to receive updates) after the user minimizes and/or force closes it (so it works correctly in the background).
However, after a phone has been away from any iBeacons for a sufficient amount of time (e.g., overnight) and is brought near iBeacons again, the app stops receiving enter/exit updates until the user opens it up again (brings it into the foreground). If the user minimizes/closes the app at that point, updates continue to work correctly in the background.
Is anything that I need to do to allow long running monitoring updates in the background? After a while does iOS stop background monitoring?
Note: I am running iOS 9.3.1
iOS Apps are supposed to be able to detect beacons indefinitely in the background when they have been granted "always" location access.
This is the second report I have heard like this, so I wonder if it is a bug or a change in a new iOS version. Reporting your iOS version would be helpful.
One possibility: the network calls may be being blocked and not the beacon detections. You could test this hypothesis by adding NSLog statements to :
Log on beacon detection
Log on successful and unsuccessful connection to the server.
Once you add the above, reproduce the issue where you don't see events on your server. Then connect your phone to XCode and go to Devices, and look at the recent NSLog output to see:
Is there a line indicating the beacon was detected?
Was the server connection successful or not?
If you find it is the network connection that is failing, you may be able to correct the situation by requesting additional background network permissions.
EDIT: One other thing you might try when a detection is not made is launching a different beacon scanner app in the foreground like Locate. This will force an OS bluetooth scan and it might kick off your app's detection. If this works, it would tell you that bluetooth scanning had been suspended across the phone.

How does the Navita TEM app get call log information?

How does Navita https://itunes.apple.com/us/app/navita-t.e.m.-personal/id590228620?mt=8
manage to display a call log?
If I swipe the app out of the task manager then it misses the calls, this indicates that it must presumably be using CTCallCenter's callEventHandler and is creating its own call log by saving the time/duration in response to the callEventHandler callbacks.
However if that is the case then how does it manage to do this in the background? I was under the impression that callEventHandler can only be used by apps in the foreground and not in the background?
The app is using location services, however even after disabling this it was still able to get information about the calls (provided the app isn't suspended). I though it might be using background location updates to keep itself primed to receive callEventHandler callbacks but apparently not.
The Navita app is additionally able to display call time and call duration.
The bounty will be awarded to an answer which contains sufficient, accurate and detailed information that enables me to emulate the behavior of the Navita app, specifically I must be able to write an app that can obtain the time and duration of a phone call that occurred while the app was not in the foreground, while the device's location services was turned off, and after the app had been in the background longer than the ~3 minutes granted by using beginBackgroundTaskWithExpirationHandler:
Here is what I observe with the Navita app that I want to be able to reproduce:
1) Run app
2) Task away from app
3) Go to device settings, privacy, and turn off Location Services.
4) Go to device settings, privacy, background app refresh and turn off for the app
5) Wait > 10 minutes to make sure the app is not still in the background as a consequence of using beginBackgroundTaskWithExpirationHandler:
6) Call the device from another phone, answer the phone call, then hang up.
7) Launch the app again and display the call time and duration
(This is iOS7 and unjailbroken)
Here is what I've found from Navita TEM disassembly and it's resources.
Application uses two background modes - location and audio. You can see it in the Info.plist file. When you enable phone calls logging application will also enable "alerts" and "Real-time" switches. When "alerts" enabled application infinitely loops in background "bg-sound.mp3" file which has no sound, it's just silence. Because of that it doesn't use hacks like this one How to get a call event using CTCallCenter:setCallEventHandler: that occurred while the app was suspended? . It's similar trick to location used in order to keep the app running in background and receive phone call events. Somehow this was not rejected from the AppStore.
If you are observing the call center while the app is in the background you get a set of updates when the app is brought back to the foreground. This set of data may not be as accurate as if the app had been mostly in the foreground but it does include quite a bit of info.

Launch my app from bluetooth iBeacon connection (Private API)

I am creating a private distribution app and I am wondering if it is possible, using any methods or private API's, to open my app when a bluetooth connection has been made.
What I have discovered so far is that with iOS 7 and the ability to use iBeacons you can enter into bluetooth proximity and you can have your app send a notification to allow the user to then open the app.
What I am hoping to do then is have the app running in the background and listen for an iBeacon connection and, if one has been made, actually launch the app without the users control instead of just sending a notification.
I realize this would never be allowed publically, however is there anything private I can look at to achieve this without jailbreaking? I know to launch some apps you can do [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]]; however I want my app to listen for an iBeacon and then open itself up.
Is there any way or work around to achieve this?
Moving app from background to foreground without user interaction is pain in the ass. Sorry, don't have a solution, just want to share some information:
I asked the same question here and posted a bounty on it and got no good response:
Show some UI from background in audio player or VOIP app on iOS
At some moment I found a solution with the help of another person. It was based on usage of GSEvent (sending clicks to UI). You can look following questions. However, as I know, in iOS 7 these API became protected by entitlement. So, this method is dead (most likely).
Using GraphicsServices.h/GSEvent as well as compiling CLI iPhone tools with Xcode
Use GSEvent to send touch event,but it's invalid.
Simulating System Wide Touch Events on iOS
iPhone, how to fire a button event in programmatically
Apps can use region monitoring to be notified when the user crosses geographic boundaries or when the user enters or exits the vicinity of a beacon. While a beacon is in range of the user’s device, apps can also monitor for the relative distance to the beacon.
In iOS, regions associated with your app are tracked at all times, including when your app is not running. If a region boundary is crossed while an app is not running, that app is relaunched into the background to handle the event. Similarly, if the app is suspended when the event occurs, it is woken up and given a short amount of time (around 10 seconds) to handle the event. When necessary, an app can request more background execution time.
For detailed info:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html#//apple_ref/doc/uid/TP40009497-CH9-SW1
There are two scenarios: you either want users to be able to do something with your device other then use your app, or you want them to always be locked into your app.
In the former case you should trust user. Just show the push, timer or location notification and let them decide to launch the app or not.
In the latter case just lock the device using guided access mode.

Resources