CTCallCenter - Call Event Handler - in background state - objective-c

Regarding the Apple documentation there is no way to handle the phone state while the app is suspended:
https://developer.apple.com/documentation/coretelephony/ctcallcenter
"While it is suspended, your application does not receive call events"
Is this also true for the "background" state? (As the background state is not the same with the "suspended" app state regarding the states described in the Apple documentation)
https://web.archive.org/web/20140824215114/https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
I'm handling the phone state using the following code:
CTCallCenter *callCenter = [[CTCallCenter alloc] init];
callCenter.callEventHandler=^(CTCall* call)
{
//call state
};
I have added a local notifications into the callEventHandler block in order to check if a call events will be received while my app is in background state but is seams that the block is not executed ( my app has a background support and all received events (via TCP) are handled correctly while the app is in background )

All tests that I've done I can't receive any using callEventHandler when the application is in background. But, when the application is in foreground, all nicely work.
The socket works, because iOS handles it for you app and deliver the packtes accordingly. But for that, you need to create a voip socket and add voip to UIBackgroundModes to your App-Info.plist.

You will not be able to monitor phone calls in the background using the callEventHandler...
However, according to this thread in apple dev forums, you can check the currentCalls periodically in the background to determine if calls are in progress.
Here is the code you should use (to check every seconds) :
- (void)viewDidLoad {
[super viewDidLoad];
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(phoneDetection) userInfo:nil repeats:YES];
}
- (void)phoneDetection {
_callCenter = [[CTCallCenter alloc] init]; // Here is the important part : instanciating a call center each time you want to check !
[_callCenter setCallEventHandler:^(CTCall *call) {
NSLog(#"Call detected");
}];
NSLog(#"%#", _callCenter.currentCalls);
}

I know some apps run soundless audio files in the background to prevent from being closed after 10 minutes of inactivity.
Bluetooth, location, and audio can prevent the app from being completely killed.
My app is able to detect incoming vs outgoing calls while in background because the app stays alive with location updates. We have used audio/bluetooth in the past.
Without some method of "keepAlive" the OS will suspend your app until some external stimulus reactivates it (push notification, user launch, etc...)

Related

IOS:Call method when local notification is received in background

I know this question looks duplicate but i did not found the exact answer as per my requirement.Doing app related to medical events with Below steps followed
1) connected the app to smart watch.
2) schedule the local notifications i. e when user needs to take
medicine
3) when the schedule time arrives local notification fires and
delegate method is calling (did receive local notification)
4) At the time of firing local notifications i am sending
message(sms) to the user from the app that he has to take certain
medicine
Everything is working fine when the app is in foreground and when the app reaches to background only local notifications are firing no message is received by the user.Because no method is calling when the app is in background.But my whole application use case mostly depends on sending sms.
Is there any solution for this ? Any help will be welcomed !! Thnxx !!
You're going to need to explicitly run your method in a UIBackgroundTask. See example below:
UIApplication * application = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier background_task;
background_task = [application beginBackgroundTaskWithExpirationHandler:^ {
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
}];
// your method call here
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
I'm doing something similar and this works for me. Let me know if thats not working for you.

how to turn off the Camera Light while taking snap programmatically?

I'm developing one app in which i want to capture an image at run time.
It has to work for both MAC PRO & Mac mini (If web cam is connected). When Camera takes picture small light will come at the time of taking snap, that should not come. Its not regarding the flash.
code snippet:
- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection
{
// If we already have an image we should use that instead
if ( currentImage ) return;
// Retain the videoFrame so it won't disappear
// don't forget to release!
CVBufferRetain(videoFrame);
// The Apple docs state that this action must be synchronized
// as this method will be run on another thread
#synchronized (self) {
currentImage = videoFrame;
}
// As stated above, this method will be called on another thread, so
// we perform the selector that handles the image on the main thread
[self performSelectorOnMainThread:#selector(saveImage) withObject:nil waitUntilDone:NO];
}
To capture picture i'm using the above method. Thanks in advance
According to this article, several older MacBooks' camera LEDs could be circumvented by tying into the circuit board logic directly.
To my knowledge, there is no longer this security loophole, nor is there an API available in Objective-C to disable the camera LED.

Application session timeOut in cocoa application

Hi friends i'm developing MAC desktop application using cocoa. I want to add session time out for in the app. Example my application running in background user dont touch and do nothing in app. After 20(we need to set) app will return home page(login page) for session time out.
Will help me how to set session in cocoa application
Use a custom NSApplication class and override sendEvent:. Something like this:
- (void)sendEvent:(NSEvent *)event
{
[super sendEvent:event];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(applicationSessionTimeout:) object:nil];
[self performSelector:#selector(applicationSessionTimeout:) withObject:self afterDelay:SESSION_TIMEOUT];
}
Basically all mouse and keyboard events enter your app through this method. You just need to override it to set your timers.

How to properly handle UI refresh after sync

I have an app that syncs data with the server on every launch with a Rails backend. The API fully works, but I'm having an issue with the interface becoming unresponsive when the interface needs to be refreshed.
I'm currently using GCD to start the sync:
Sync *sync = [[Sync alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[sync force_sync:#""];
[appModel updateSyncTime:current_time];
});
Once the sync is completed, I have the Sync object sending a NSNotification to the app so that the interface refreshes:
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"Sync-Completed" object:self];
});
When the notification is received, my other classes just simply reload the data in the UITableView, like so:
- (void)notificationReceived:(NSNotification *)notification {
[dataTable reloadData];
}
Up until the point the notification is received, the UI is completely responsive. Once the notification is received, you can't scroll UITableViews among other UI elements until the refresh is completed. I'm sure there's a better way to do this, but how?
Thanks in advance!
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"Sync-Completed" object:self];
});
Is not Async - you just dumped a huge amount of refresh work on your main queue (the processing of the sync-completed notification)- so your app is going to lock up unless you address the code that updates the UI.
Also, using the global queue for a heavy IO operation is not necessarily a good idea. I have seen cases where just doing that will lock up the UI - so make sure its the notification and not also the sync itself.
If you find it is the sync itself - create your own NSOperation queue and create an NSOperation out of that block.
Your mileage may vary but in general using the global queue has not worked for async IO for me.

Check for waiting notifications

With iOS 5 and the notification center you can have waiting, stacked up notifications each with their own data and message. Is there a way when your program is launched regularly (without tapping on the notification) to discover the waiting notifications and more importantly the data associated with them?
The other question associated with this is when the push notifications come in and your app is in the background does application:didReceiveLocalNotification: still get called or does it just go and wait till the app is launched and then you're expected to manually handle it with the launch data in theapplication:didFinishLaunchingWithOptions:
My scenario is that I need to update some core-data models with the data attached to the push notifications so I want those changes reflected no matter how they launch the app.
From my experience, there is no way to find out about notifications other than launching the app directly through them (on iOS 5, that would be right after receiving the notification or from the queued notifications present at the Notification Center).
An alternate strategy would be to use icon badges.
If you badge your app icon when receiving notifications, you could check for that number every time the app is launched and then perform the required actions.
When a notification pops up you can either view it or cancel. If the user has canceled notification, you can check for them the next time they go in the app:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if( localNotif ) {
// Do some stuff
application.applicationIconBadgeNumber = 0; // Reset num of notifications on app icon
}
}
This method gets fired if you receive a notification while you are in that specific app, or you choose to acknowledge a local notification:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
BOOL inApp = [application applicationState] == UIApplicationStateActive;
if( inApp ) { // they got this in the app
//Do some stuff in the app
}
else {
// They acknowledged the notification out of the app and here they are
// Do some other stuff
}
application.applicationIconBadgeNumber = 0;
}
That gives you good coverage for all scenarios with local notifications which would be:
Notification is received, user cancels. Check later in didFinishLaunchingWithOptions
Notification is acknowledged, the app is not open. Check in didFinishLaunchingWithOptions
Notification is acknowledged, the app is in the background. didReceiveLocalNotification:
Notification is presented while in the app didReceiveLocalNotification: