How does the Navita TEM app get call log information? - ios

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.

Related

is iOS background mode needed if app works when suspended?

I need my iPhone app to do some tasks in the background when it's suspended, but I don't need to do any tasks after it's turned off. Do I need to settle UIBackgroundMode?
Yes, to execute code continuously in the background state, you need to register for a given UIBackgroundMode.
See here or here for a good source on this.
However if you just wish to perform a single background task (task completion), you don't need a background mode.
In response to your comment below, I will try to be clear:
In iOS, even in iOS 7, it's not possible to run arbitrary code when your application is in a background state indefinitely.
In simple English, - you can't just run any code you like in the background for as long as you like.
There are rules.
These rules have been relaxed somewhat in iOS 7, but it's still not totally unrestricted.
Consider your situation: You have a timer that wants to call a method on a continuous basis.
Now consider the UIBackgroundModes available (which allow you to run in the background in various situations):
audio - Only for audio based apps.
location - Only if you app is location aware, does specific location tasks
voip - VOIP (Skype etc)
fetch (Background fetch - a new iOS 7 API where the system gives you application moments to grab new content when it sees fit.
remote-notification - new in iOS 7, when the device receives a remote push notification with a certain payload, it will resume and execute a certain block of code.
newsstand-content - Only for newsstand apps
external-accessory - Only for external accessories to communicate with the device
bluetooth-peripheral Only for external BT accessories to communicate with the device (fitbit)
As you can see if you don't fall into one of these categories you can't use these modes.
If you misuse the modes Apple won't approve your application.
Finally we have 'Background task completion'
This is a way to use a UIBackgroundTask to execute any code you want in the background! Including timers that call methods! - One problem though...
This is supposed to be for 'task completion' (Facebook uploads that aren't complete, saving or processing data that should be done before the app suspends even though the user pressed the home button).
Sounds good, but you can only run in the background using this method for a maximum of 10 minutes. If you go over this time limit iOS will immediately kill your application.
So as you can see, there is no way for your application to be approved on the store and constantly run in the background with a timer that calls your method.
Sorry about that.
If you want to learn more check this out.
Use the location service and set NO location manager "pausesLocationUpdatesAutomatically" property.

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.

performFetchWithCompletionHandler never gets fired

1) My plist configuration to provide backgroundmode:
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
2) In didFinishLaunchingWithOptions I have:
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:1.0];
3) I declared the protocol UIApplicationDelegate in the delegate.
4) I implemented the following method, but it never gets fired. (It only works if I simulate the fetch with "XCode->Debug->Simulate Background Fetch".)
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
Why? Is this a DP5 beta error? Should I radar this?
Running your app in the iOS Simulator, in Xcode Debug mode, you can force a background fetch from the Xcode menu:
Debug > Simulate Background Fetch
May work for a tethered device, I haven't tried it recently.
I'm afraid this is hard to debug on a device because you're not guaranteed it is called in the amount of time you specify.
setMinimumBackgroundFetchInterval means that it is not called in an interval which is smaller than the value you specified. But there's no setMaximumBackgroundFetchInterval.
So if iOS decides to call your app just once a day or even just once a week than it won't be called more often regardless your minimumBackgroundFetchInterval. AFAIK iOS decides when to call performFetchWithCompletionHandler measured by the pattern when and how often the users start the app.
There are many considerations:
Make sure the background fetch capability was set in the plist.
Make sure the background fetch capability hasn't been disabled for this particular app, or in general, in the device's Settings app.
Make sure to set the minimum fetch interval.
Make sure you gracefully leave the app (e.g. just hit the home button and fire up another app and/or just lock the device). But if you kill the app (by “force quitting” by double tapping on the home button and swiping up or, for those devices without home button, swiping up from the bottom to pull up the task manager and then swiping up on the app in question) that will prevent the OS from offering your app a chance to fire off subsequent background fetch requests (at least until the user runs the app again).
Make sure you are testing this on physical device and not running the app via the Xcode debugger. Being attached to the debugger changes the behavior of background operations.
Make sure the app is actually doing some network requests. If you have app that performs no network requests at all, it won't participate in background fetch. If you do, for example, a little test app with "background fetch" and don't issue any network requests, you won't participate in background fetch.
Likewise, if the OS starts up your app in background mode so it can perform a background fetch, if you don't actually perform a network request, the OS may stop offering your app the ability to perform background fetches in the future.
Make sure to call the completion handler, and do so within the allotted time, or your app may not participate in background fetch in the future.
The timing of when the OS performs background fetch is dictated by poorly documented rules that may change in the future. But the relevant factors include:
Whether the device is connected to power and/or is sufficiently charged;
Whether connected to WiFi or not;
How often the user actually fires up the app;
Whether the device is doing other network related tasks (e.g. whether background fetch can be coalesced with other network operations);
How frequently past background fetch requests resulted in there being data available.
In my experience, after the app is run the first time, if connected to wifi and power, if you wake the device about 5 minutes later, the app will perform background fetch. This isn't a hard and fast rule, but just what we've experienced in the past.
But many new developers post on Stack Overflow with questions like “how can I have app request data ever x minutes (or hours)”, “how can I request data every day at 2 am time”, etc. The short answer is that you can't. The OS decides the timing of background at its own discretion. You cannot control this (other than the minimum request interval; but you cannot control the maximum interval, as the OS controls that).
This may seem obvious to many, but make sure you've got a reliable way of knowing whether background fetch process is running correctly or not. User Notifications framework can be used to present some alert so you know if the background request resulted in something. Alternatively, os_log or Logger “Unified Logging” (see WWDC 2016 Unified Logging and Activity Tracing or 2020’s Explore logging in Swift) can be used to post messages on device that can be monitored on macOS Console app. But more than once, I've seen users do something like waiting for message to show up in Xcode or waiting for UIAlertController. You need some mechanism that works when not connected to Xcode and when the app never enters foreground.
Using your device you can fire application:performFetchWithCompletionHandler with the following steps:
Put your app in the Background state
Lock your device and wait 5 minutes.
Unlock your device, this will fire the method
(It only works if I simulate the fetch with "Xcode->Debug->Simulate
Background Fetch".)
It's because you're in Debug mode. Please try launch app without Xcode.
Another thing to check is your plist file. Make sure the UIApplicationExitsOnSuspend key is not present.
Many people here on Stack Overflow have recommended using that setting as a way to force your app to start fresh each time it's launched. That does work, but the side effect is that it prevents the new iOS 7 background fetch feature from being triggered.
If application: performFetchWithCompletionHandler: never gets fired (unless you simulate it using Xcode), check also if "Background App Refresh" preference is "On" for your app. (Settings app -> General -> Background App Refresh)
Also, background fetch is disabled if the iPhone is in Low Power Mode.
Apple provides an algorithm which defines how often the background fetch should trigger, based on your own usage of the app. If you use it a lot, then it will fetch as often as possible, but if you use like at 4pm every day, the background fetch should trigger just before, so your data is updated when you launch it.

Implementing Long-Running Background Tasks in iOS

my client asks me to develop some app that periodically retrieves the user location & the phone battery status, and then send them to our backend server for data analysis, then feed back by push notification.
But through the app doc, I get to know that from apple ios dev doc:
For tasks that require more execution time to implement, you must
request specific permissions to run them in the background without
their being suspended. In iOS, only specific app types are allowed to
run in the background:
Apps that play audible content to the user while in the background,
such as a music player app
Apps that keep users informed of their
location at all times, such as a navigation app
Apps that support
Voice over Internet Protocol (VoIP)
Newsstand apps that need to
download and process new content
Apps that receive regular updates
from external accessories
I'm wonder if this would be feasible if we wrap this app as some navigation app so we can have long-running background tasks? Does appstore will reject on our app?
BTW, what is the definition of navigation app by Apple?
You might consider using:
[CLLocationManager startMonitoringSignificantLocationChanges];
This will cause your app to be restarted if it has been killed whenever the location changes significantly, allowing you to update the details on the server at fairly regular intervals, assuming the user is moving. This does not require any special background permission. From the docs:
If you start this service and your application is subsequently terminated, the system automatically relaunches the application into the background if a new event arrives. In such a case, the options dictionary passed to the locationManager:didUpdateLocations: method of your application delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your application was launched because of a location event.
Your other option is to configure the app as requiring continuous location updates in the background, but without knowing the primary function of the app it is hard to know if this will pass store submission or not.
https://github.com/yarodevuci/backgroundTask Check my code here I am using audio player that plays blank wav file Works perfectly on IOS 8 Battery usage around 10% in 24 hour period How to use:
var backgroundTask = BackgroundTask()
backgroundTask.startBackgroundTask() //Starts playing blank audio file. You can run NSTimer() or whatever you need and it will continue executing in the background.
backgroundTask.stopBackgroundTask() //Stops the task

Running IOS App with Screen Locked

I am working on a sports app that uses GPS and OpenEars text-to-speech. The app delivers speed and other GPS info to the user audibly (via earphones) so the user (skier, cyclist, etc) can get the GPS info without looking at the screen. In order to save battery life, I would like the app to run in the background with the screen off. Is this possible with IOS? I tried setting "Required backgrund modes" for both GPS and audio, but my app quits working when the screen is off.
thanks..
One one to get around it is to have a silent audio file playing, when there is no audio, it might get your app rejected in the app store though... here is a question that talks about the silent audio file playing to keep in the background... It might get through app store approval in your situation since it is an app that relays on audio as one of its main functionalities..
You can subscribe to GPS info change notifications and your app will run when something needs to be updated. Check this.
Please note this sentence:
"If you leave this service running and your application is subsequently suspended or terminated, the service automatically wakes up your application when new location data arrives. At wake-up time, your application is put into the background and given a small amount of time to process the location data. Because your application is in the background, it should do minimal work and avoid any tasks (such as querying the network) that might prevent it from returning before the allocated time expires. If it does not, your application may be terminated."
There's no way to do it as service except some special cases provided by ios. But you can simulate it. This post answer how to:
https://stackoverflow.com/a/19121250/2835520
I hope it's gonna help!

Resources