How to get incoming/outgoing call event in background state - ios

In one of my app it has a feature of playing sound that I achieved successfully. Even though when app is running (foreground state) and we received the incoming call, app music gets stopped and resume again when call gets disconnected.
Now real problem is here. When app enters in the background state, we are not receiving any event for incoming/outgoing call. In the background mode If music is playing inside my app and we get any incoming call, then app music is stopped automatically but not resume again when call disconnected unlike iPhone Music app.
Is it a limitation of the iOS or can we achieve that ?
Note: I'm not looking for any solution for Jailbreak devices or Enterprise apps

Have you tried to create call center and assign handler block in AppDelegate class? The following has to work.
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let callCenter: CTCallCenter = CTCallCenter()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
callCenter.callEventHandler = {
(call: CTCall!) in
switch call.callState {
case CTCallStateConnected:
print("CTCallStateConnected")
case CTCallStateDisconnected:
print("CTCallStateDisconnected")
case CTCallStateIncoming:
print("CTCallStateIncoming")
default:
print("default")
}
}
return true
}
}
Do not forget to switch on Background Modes for this. And perform something in the background as well, smth like receiving location.

Related

Picture-in-picture in iOS fails with saying that the activationState is something other than foregroundActive but it is actually foregroundActive

I am implemeting Picture-in-picture on iOS. I added the background mode capability. When I call isPictureInPicturePossible, it returns false with error:
pictureInPictureController failedToStartPictureInPictureWithError Error Domain=AVKitErrorDomain Code=-1001 "Failed to start picture in picture." UserInfo={NSLocalizedDescription=Failed to start picture in picture., NSLocalizedFailureReason=The UIScene for the content source has an activation state other than UISceneActivationStateForegroundActive, which is not allowed.}
But I when I log the activationState, I can see that it is actually foregroundActive. Any idea what could be the reason?
(before that isPictureInPictureActive returns true, isPictureInPictureSuspended returns false, isPictureInPictureActive returns false.)
It is a little difficult to give an opinion without access to the code and without knowing the versions.
My suggestions:
Check if the app is really in the foreground. You can verify this by looking at the activationState of the UIScene for the content source. If it's not foregroundActive, you can't start the image in the image. If you are using a UISceneDelegate, you can check the activation state of the scene in the sceneWillEnterForeground: method. If using an AppDelegate, you can check the activation state of the scene in the applicationDidBecomeActive: method.
If you use using a UISceneDelegate instead of a AppDelegate. Change it to AppDelegate.
Set the sceneActivationState to foregroundActive in the AppDelegate.swift file:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
let scene = UIApplication.shared.connectedScenes.first
if let sceneDelegate = scene?.delegate as? SceneDelegate {
sceneDelegate.window?.windowScene?.activationState = .foregroundActive
}
}
return true
}
If no option to validate. We will give you more information about the problem.

How to Play AudioServicesPlaySystemSound When iPhone is Silenced

I'm making an iOS game with Swift and trying to play system sounds when the iPhone is silenced so that you can hear sound effects regardless of volume mode. The code to play the sound is:
AudioServicesPlaySystemSound(1000)
This works fine when the iPhone has the volume rocker unmuted; however, if the phone is silenced, nothing plays. If I change this to:
AudioServicesPlayAlarmSound(1000)
I get vibrating on silent mode but not the audio. I've seen examples of how to setup the AppDelegate to change the audio mode like the following:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, options: AVAudioSession.CategoryOptions.mixWithOthers)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
#if DEBUG
print("ERROR: Cannot play music in background: \"\(error)\"")
#endif
}
return true
}
}
However, I'm using iOS 15 and AppDelegate isn't really necessary anymore. What's a modern way I can play system sounds regardless of the volume state in my game? No other answers on the site worked for me.

Terminated App only being restarted one time

I have an application that by design should be activated by the OS after a location event is delivered from the system even if the app has been terminated. Terminated can mean terminated by the system or by the user in the multitasking switcher. My app delegate code is below and the location delegate is an extension of the app delegate class. The first event that is generated by the system after the app is terminated is delivered to my app and processed properly, but I am not receiving any subsequent events. Is there some code I need to run after the event is received to reregister my application for future updates?
var window: UIWindow?
var locationManager: CLLocationManager!
var notificationCenter: UNUserNotificationCenter?
var today:String? //Today's date format: YYYY-MM-DD
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil {
self.locationManager = CLLocationManager()
self.locationManager.delegate = self
self.locationManager.requestAlwaysAuthorization()
self.locationManager.startMonitoringVisits()
self.locationManager.allowsBackgroundLocationUpdates = true
sendTestNotification()
} else {
print("normal launch")
}
You say your app has been "terminated". This suggests that you kill your app intentionally as a way of testing. But if an app has been forcibly terminated, the system deliberately stops background location monitoring, so naturally you won't get any more visit monitoring events. It is as if you had called stopMonitoringVisits yourself.
app terminate is not allow by apple as i know.
exit(0)
you can use that code line to app terminate

CLCircularRegion and wake up app

In application we have mechanism like native Reminder app in iOS with firing notifications when user enter or exit in some region.
But two devices behave differently (5 and 5s) in same time. All devices have enable notifications, and allow use locations.
Two devices have a some "travel" and in the route created 10 points. First device (5) when came to finish received only 6 notifications, (5s) don't receive any notification.
But my question is how I can know when my app is restart in background or continue working. Because, all log in app I redirect into a file, and after download container and analyze what happened in app in travel time.
I noticed app restart in same times when device is enter to region and my log marks fired in the file but notifications don't receive. This is happended when app try to get some information from web service in didFinishLaunchingWithOptions
And maybe this is problem. How to know distinguish restart app or continue working. Thx.
Are you checking UIApplicationLaunchOptionsLocationKey in didFinishLaunchingWithOptions similar to (sorry, Swift is what I have now):
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsLocationKey] != nil {
// app was launched in response to incoming location event
}
}
Additionally, if you're not already doing this you may need to create notifications differently if app is in background:
// Show an alert if application is active
if UIApplication.sharedApplication().applicationState == .Active {
if let message = notefromRegionIdentifier(region.identifier) {
if let viewController = window?.rootViewController {
showSimpleAlertWithTitle(nil, message: message, viewController: viewController)
}
}
}
else {
// Otherwise present a local notification:
let notification = UILocalNotification()
notification.alertBody = notefromRegionIdentifier(region.identifier)
notification.soundName = "Default";
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}

How to get notification additionaldata(payloadData) that was at AppDelegate' didFinishLunchingWithOptions if the user didn't open the notification

I am currently using OneSignal for notification service to my app.I really need a help with accessing notification additionaldata(payload data) from AppDelegate inside didFinishLunchingWithOption where OneSignal API can give me like this.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var data : [NSObject : AnyObject]!
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let oneSignal = OneSignal(launchOptions: launchOptions, appId: "48755d3d-abc0-4bac-8f71-095729bb3a65") { (message, additionalData, isActive) in
NSLog("OneSignal Notification opened:\nMessage: %#", message)
if additionalData != nil {
NSLog("additionalData: %#", additionalData)
self.data = additionalData
print(self.data)
}
}
oneSignal.enableInAppAlertNotification(true)
return true
}
}
but,I can only get the data if user click notification when appear or open it from notification center.So,if user neglect that notification without tapping when appear or without swiping or tapping from notification center,how do i get the additional data?
Actually,I want to store all payload data every time it comes into my device at realm database and fetch the data from my server according to that payload data.
You should use application(_:didReceiveRemoteNotification:fetchCompletionHandler:).
If you have enabled remote notifications background mode most of your notifications will be delivered even if the app is not running in the foreground. The only caveat being that the app must have been launched (since notifications are being pushed the user has done this) and it mustn't have been force-quit by the user.
More info in Apple's docs about that specific method.
Or in the "Local and Remote Notification Programming Guide's" notification handling chapter
You can extract all the payload in did finishLaunching by following method..
Let data = launchOptions.objectForKey(UIApplicationLaunchOptionsUIApplicationLaunchOptionsRemoteNotificationUIApplicationLaunchOptionsUIApplicationLaunchOptionsRemoteNotificationKey)

Resources