How to Play AudioServicesPlaySystemSound When iPhone is Silenced - ios

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.

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 prevent iOS11 Built in screen recording feature just like Amazon Prime for protected DRM content?

WideVine iOS CDM Player is playing DRM Protected content.
Now, iOS11 introduce a new built-in feature i.e Screen Recording.
Using this feature a user can easily capture or record DRM Protected content.
I used iOS11 Beta isCaptured and UIScreenCapturedDidChange Property and try to prevent DRM protected content to recorded, But This isCaptured and UIScreenCapturedDidChange working fine when the first time I Launch my Application. Now, when I Kill my running App(Terminate the application) and Launch again then my App doesn't receive any value for isCaptured and UIScreenCapturedDidChange.
Now I try to record Netflix and Amazon Prime content using iOS11 screen recording feature but it will don't allow to record and gives a Black screen.
I want similar Black screen when screen recording is On in iOS11 device, But I don't have the solution. If anyone has then please help.
Netflix and Amazon prime iOS apps are using Apple DRM solution for apple devices - FairPlay (https://developer.apple.com/streaming/fps/). When AVPlayer plays FairPlay encrypted content it can't be captured by Screen Recording in iOS11.
You can use UIScreen.main.isCaptured to tell if the screen is being recording by screen recording or AirPlay etc...then show your black view to cover your screen
You just need to make the following changes in your Appdelegate.swift page.
It will automatically add a blurred view on the top of the app when the user tries to record the screen.
weak var screen : UIView? = nil
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(preventScreenRecording), name: UIScreen.capturedDidChangeNotification, object: nil)
return true
}
#objc func preventScreenRecording() {
let isCaptured = UIScreen.main.isCaptured
print("isCaptured: \(isCaptured)")
if isCaptured {
blurScreen()
}
else {
removeBlurScreen()
}
}
func blurScreen(style: UIBlurEffect.Style = UIBlurEffect.Style.regular) {
screen = UIScreen.main.snapshotView(afterScreenUpdates: false)
let blurEffect = UIBlurEffect(style: style)
let blurBackground = UIVisualEffectView(effect: blurEffect)
screen?.addSubview(blurBackground)
blurBackground.frame = (screen?.frame)!
window?.addSubview(screen!)
}
func removeBlurScreen() {
screen?.removeFromSuperview()
}

How to get incoming/outgoing call event in background state

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.

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)
}

iTunes Music stops when I open my application

I am using AVAudioSession and I am activating in my browser on launch. I have set category AVAudioSessionCategoryPlayback. I have not set any category options. I want audio to be played even in background. If I don't use AVAudioSession then I will not able to play audio even in background. I don't want my app's audio to mix up with iTunes song and play both simultaneously. As its browser application, we don't need audioSession always but when playing audio alone. Similar to how mobile Safari handles audio when iTunes music is on. I saw other category options and modes of AVAudioSession. Kindly give any suggestions for the same.
Here I fixed this,
Xcode 10.x Swift 4
Add the following code in your AppDelegate.swift
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, mode: AVAudioSessionModeDefault, options: [.mixWithOthers, .allowAirPlay])
print("Playback OK")
try AVAudioSession.sharedInstance().setActive(true)
print("Session is Active")
} catch {
print(error)
}
return true
}
Note: - Please configure options as required. E.g to stop a background audio while a video file being played add
options: [.allowAirPlay, .defaultToSpeaker]
And don't forget to enable audio and airplay in Background mode

Resources