iOS 16 FairPlay Changes - ios

Are there any changes in FairPlay logic? My app has FairPlay protected Videos and Audio, they work perfectly until iOS 15.7, but in iOS 16
makeStreamingContentKeyRequestData is throwing me following error :
Error Domain=CoreMediaErrorDomain Code=-19152 "(null)"
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed"
UserInfo={NSLocalizedFailureReason=An unknown error occurred (-19156), NSLocalizedDescription=The operation could not be completed,
NSUnderlyingError=0x280deac10 {Error Domain=NSOSStatusErrorDomain Code=-19156 "(null)"}}
What could be the possible reason for this and solution?
Thanks in Advance

Function streamingContentKeyRequestDataForApp is deprecated on iOS 15 according to documentation. Use function makeStreamingContentKeyRequestData that is specified in new function documentation. Here is an example usage:
func makeStreamingContentKeyRequestData(
forApp appIdentifier: Data,
contentIdentifier: Data?,
options: [String : Any]? = nil,
completionHandler handler: #escaping (Data?, Error?) -> Void
)

We are using AVContentKeySession for downloading, met with the same error, and fixed it. For our case, the issue was as following.
Issue observed:
On iOS16.0.3, 12s later after "license request" was triggered firstly by app during downloading, "license request" would be triggered again by AVFoundation framework
("contentKeySession(_ session: AVContentKeySession, didProvide keyRequest: AVContentKeyRequest)" was called again), and then error “-19152“ wad reported quickly by framework.
Error log:
contentKeySession(_:contentKeyRequest:didFailWithError:), line: XXX,
message: XXX, url: XXX, error is Domain=CoreMediaErrorDomain
Code=-19152 "(null)"
On iOS15.6.1, after "license request" was triggered
by app during downloading, framework would not trigger any "license request" again.
Root cause:
iOS Framework API(AVContentKeySession & AVPersistableContentKeyRequest) behaviors changed on iOS16.
Solution:
Add “keyRequest.processContentKeyResponse(keyResponse)” after CKC has been downloaded on iOS16+.
On iOS11 - iOS15, we didn't call it after downloading, instead we only save persistentKeyData locally, and called processContentKeyResponse when playing. That always worked fine on these iOS versions.
But on iOS16 and above(until iOS16.1 Beta4 by now), the old process would trigger framework error. So we added this fix.

The issue I had was that the keyRequest.options was not getting set as it showed up nil (in iOS 16 for whatever weird reason).
I'm passing the correct options to
processContentKeyRequest(withIdentifer identifier: Any?, initializationData: Data?, options: [String : Any]? = nil).
But in the ContentKeyDelegate functions they are showing otherwise. So, my workaround is just using a global options dictionary for storing the license URL and asset data. You can use any storage method you prefer.

I have solved the issue, the issue was with duplicate EXT tags in m3u8 files which somehow worked for iOS 15 since it picked information from the first tag whereas in iOS 16 it was using all the tags and causing a Error

Related

Display custom error message from iOS broadcasting extension

My application bundle consists of the main app (normal iOS application) and broadcasting extension (ReplayKit 2). My app contains a button (RPSystemBroadcastPickerView), which opens a system popup to select a broadcasting extension and start it.
The one does not have much control over the state of the broadcasting extension inside the extension, however the extension's class which inherits RPBroadcastSampleHandler has one useful method (finishBroadcastWithError), which allows us to trigger a fail from the extension (which will in turn end the extension's process and show a popup window, showing an error and 2 buttons).
The finishBroadcastWithError method accepts an error as an argument. However there is absolutely no information in docs how to customize the error message shown in this system popup window.
I tried to google in order to understand how to set an error message, because I saw some apps (Mobcrush), which somehow were able to set a custom error message when this popup appears. In order to get more info, I watched both videos about ReplayKit 2 from WWDC 2017 and WWDC 2018, the only slide which mentioned something about error handling in Replay Kit 2 was the one, where the following code was demonstrated:
let userInfo = [NSLocalizedFailureReasonErrorKey : "Not Logged In"]
let error = NSError(domain: "RPBroadcastErrorDomain", code: 401, userInfo: userInfo)
finishBroadcastWithError(error)
I tried it immediately, but unfortunately it does not have any effect on the error shown in the error popup. I assume that either it's some bug in Replay Kit 2 or that something has been changed and was not documented properly (for some reason Replay Kit 2 is not that well documented and I had to gather pieces of information from different sources to write an app which works).
I even tried setting multiple different keys in a dictionary, hoping that at least one of them will change the error message in a popup window, but none of them worked.
func stop(message error: String) {
let userInfo = [NSLocalizedDescriptionKey : error,
NSLocalizedRecoverySuggestionErrorKey : error,
NSLocalizedFailureErrorKey : error]
let error = NSError(domain: "RPBroadcastErrorDomain", code: 1, userInfo: userInfo)
finishBroadcastWithError(error)
}
Did I miss something in docs? Is there any "official" way to change the error message?
I'm getting customized error with this set of parameters:
let userInfo = [NSLocalizedFailureReasonErrorKey: "failed to broadcast because...."]
NSError(domain: "ScreenShare", code: -1, userInfo: userInfo)

Apple iOS ARKit: "A sensor failed to deliver the required input" error and stops working

I am developing an application that uses both ARKit and hardware video decoder. As soon as the decoder start to decode, the following error message appears in console and prevent tracking from working properly.
Occasionally, this error do not show up and the app works normally. After some debugging, I found out this error only happens at the "beginning" (shortly after launching the app). Once it passes that point, it works fine for the rest of the time.
Does anyone know what the problem is or how to go around it?
2017-08-11 20:48:02.550228-0700 PortalMetal[4037:893878] [] <<<<
AVCaptureSession >>>> -[AVCaptureSession
_handleServerConnectionDiedNotification]: (0x1c0007eb0)(pthread:0x170387000) ServerConnectionDied 2017-08-11
20:48:02.564053-0700 PortalMetal[4037:893747] [Session] Session did
fail with error: Error Domain=com.apple.arkit.error Code=102 "Required
sensor failed." UserInfo={NSLocalizedFailureReason=A sensor failed to
deliver the required input., NSUnderlyingError=0x1c4c51280 {Error
Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action"
UserInfo={NSLocalizedDescription=Cannot Complete Action,
NSLocalizedRecoverySuggestion=Try again later.}},
NSLocalizedRecoverySuggestion=Make sure that the application has the
required privacy settings., NSLocalizedDescription=Required sensor
failed.}
Update
The solution is to do with compass calibration being set in the phone settings. Credit to this answer.
Go to Settings > Privacy > Location Services > System Services, and set Compass Calibration to ON.
How to prevent Crashing
Declare your config at the top of your class e.g:
var configuration = ARWorldTrackingConfiguration() and make sure you setup and add your config in the viewWillAppear method.
Then add this method to handle the error.
func session(_ session: ARSession, didFailWithError error: Error) {
// Present an error message to the user
print("Session failed. Changing worldAlignment property.")
print(error.localizedDescription)
if let arError = error as? ARError {
switch arError.errorCode {
case 102:
configuration.worldAlignment = .gravity
restartSessionWithoutDelete()
default:
restartSessionWithoutDelete()
}
}
}
It just handles the error that you've noticed.
Next, add this function to reset the session with a new config worldAlignment:
func restartSessionWithoutDelete() {
// Restart session with a different worldAlignment - prevents bug from crashing app
self.sceneView.session.pause()
self.sceneView.session.run(configuration, options: [
.resetTracking,
.removeExistingAnchors])
}
Hope it helps, and I also hope to find an actual fix to this apparent bug.
Setting worldAlignment to gravityAndHeading needs the location service to be enabled:
check if your device has location service turned on.
Check if Info.plist has set Privacy - Photo Library Additions Usage Description
If the compass orientation is crucial for your app, you should consider to guide the user to do turn the location service on and implement a fallback.

XCTests failing to launch app in simulator intermittently

Has anyone experienced and fixed:
XCTests are failing intermittently to launch app in the simulator for UI testing (XCUI).
I am running through fastlane, different tests appear to fail each test run.
OSX: 10.12.3
iOS simulator: 10.0
Xcode 8.2.1
Fastlane 2.11.0
Attempted to fix it by adding a 3 second sleep between setup and launch in my tests, but it still appears, maybe not as often but still...
UI Testing Failure - Failure attempting to launch
<XCUIApplicationImpl: 0x600000231b20 no.something.bb.debug at
/Users/server/Library/Developer/Xcode/DerivedData/ex-gmtcdujyggxwfrarizpgaromjfxj/Build/Products/Debug-iphonesimulator/BB.app>:
Error Domain=FBSOpenApplicationServiceErrorDomain Code=1 "The request
to open "no.something.bb.debug" failed."
UserInfo={NSLocalizedDescription=The request to open
"no.something.bb.debug" failed., NSLocalizedFailureReason=The request
was denied by service delegate (SBMainWorkspace) for reason: Busy
("Application "no.something.bb.debug" is installing or uninstalling,
and cannot be launched")., BSErrorCodeDescription=RequestDenied,
NSUnderlyingError=0x6080002598f0 {Error
Domain=FBSOpenApplicationErrorDomain Code=6 "Application
"no.something.bb.debug" is installing or uninstalling, and cannot be
launched." UserInfo={BSErrorCodeDescription=Busy,
NSLocalizedFailureReason=Application "no.something.bb.debug" is
installing or uninstalling, and cannot be launched.}}}
I experienced the same issue. I found out that there is a rader open for this. In the comments I found a tip that I implemented in a function that does a retry.
The arguments array is an array of enum values where the base type is String. I use that for the app arguments.
Unfortunately this is still not full prove. In my case the number of failures went down considerably, but did not go away.
var app: XCUIApplication = XCUIApplication()
public func tryLaunch<T>(_ arguments: [T], _ counter: Int = 10) where T: RawRepresentable {
sleep(3)
XCUIApplication().terminate()
sleep(3)
app = XCUIApplication()
app.launchArguments = arguments.map { $0.rawValue as! String }
app.launch()
sleep(3)
if !app.exists && counter > 0 {
tryLaunch(arguments, counter - 1)
}
}
The function above is included in https://github.com/evermeer/UITestHelper
After playing around we were observed that if we run limited test cases, this error went down considerably. You can find more details at https://blog.talentica.com/2017/04/04/use-xcode-8-with-jenkins/

iOS 7: Strange AVAssetExportSession bug

I have used AVAssetExportSession to join 2 video files. It works fine in iOS 6 but has very strange bug in iOS 7.
Let me explain this bug. I have 2 video files, the first video is 8 seconds duration and the second is 81 seconds duration. In iOS7, it will be fine if I do the second + the first. But if I do the first + the second, it will be error:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x176cb5c0 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x176ca000 "The operation couldn’t be completed. (OSStatus error -12633.)", NSLocalizedFailureReason=An unknown error occurred (-12633)}
I have checked exportPresetsCompatibleWithAsset and supportedFileTypes. There is no problem with it. Could anyone tell how to fix this? Any help would be appreciated.
Does anyone know this bug :(. I provide 2mp4 files which cause the bug: test 1, test 2. Do join "test 2" + "test 1" is fine, but do "test 1" + "test 2" will cause an error. It only happens in iOS7
I found that you can replace AVAssetExportSession with SDAVAssetExportSession. You can then specify settings instead of using presets which provide different results across different devices.
I had to change __weak typeof(self) wself = self; to
__weak SDAVAssetExportSession * wself = self; on line 172 of SDAVAssetExportSession.m.
I had an "unknown error occurred (-12633)" message.
Found the answer to be adding two samples with same timestamp.
Apparently error -12633 is an InvalidTimestamp.
See this SO post -> AVAssetWriter unknown error
If you are using methods insertTimeRanges or insertTimeRange, you need to ensure that the input time ranges are valid. To be more specific, you should not use the asset's duration for this, you need to get the accurate time ranges from individual asset tracks.
Use command ffprobe -show_frames path_to_file to inspect your video files, which sometimes may be very helpful.

How to fix "NSURLErrorDomain error code -999" in iOS

I've been trying to use Corona SDK's Facebook API to post the score on the game I'm developing on facebook. However, I'm having a problem with it. During the first time I try to post to facebook, I get this error after login and user authentication:
NSURLErrorDomain error code -999
Then, it won't post on facebook. What are possible causes of this error and how can I address it?
By the way, I am not using webview on my app. Just the widget api and a show_dialog listener in my Facebook class.
The error has been documented on the Mac Developer Library(iOS docs)
The concerned segment from the documentation will be:
URL Loading System Error Codes
These values are returned as the error code property of an NSError
object with the domain “NSURLErrorDomain”.
enum
{
NSURLErrorUnknown = -1,
NSURLErrorCancelled = -999,
NSURLErrorBadURL = -1000,
NSURLErrorTimedOut = -1001,
As you can see; -999 is caused by ErrorCancelled. This means: another request is made before the previous request is completed.
Just wanted to add here, when receiving a -999 "cancelled" the problem usually is one of two things:
You're executing the exact same request again.
You're maintaining a weak reference to your manager object that gets deallocated prematurely. (Create strong reference)
hjpotter92 is absolutely right, I just want to provide solution for my case. Hopefully it is useful for you as well. Here is my situation:
On log in page > press log in > pop up loading dialog > call log in service > dismiss dialog > push another screen > call another service --> cause error -999
To fix it, I put a delay between dismissing dialog and pushing new screen:
[indicatorAlert dismissWithClickedButtonIndex:0 animated:YES];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"HomeSegue" sender:nil];
});
It is strange that this issue happens on iOS 7 only.
I have faced the same error with Alamofire and it was because the certificate pinning.
The certificate wasn't valid anymore, so I had to remove it and add the new one.
Hope it helps.
In addition to what Ramon wrote, there is a third possible reason when receiving a NSURLErrorDomain -999 cancelled:
You cancelled the task while it was executing either by calling .cancel() on the datatask object or because you used .invalidateAndCancel() on the session object. If you are creating a custom session with a delegate, you should call .invalidateAndCancel() or .finishTasksAndInvalidate() to resolve the strong reference between the session and its delegate, as mentioned in the Apple Developer Documentation:
The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you don’t invalidate the session, your app leaks memory until it exits.
If you are wondering about this logging behaviour, I found the following explanation in the Apple Developer forums:
By way of explanation, back in iOS 10 we introduced a new logging system-wide logging architecture (watch WWDC 2016 Session 721 Unified Logging and Activity Tracing for the details) and lots of subsystem, including CFNetwork, are in the process of moving over to that. Until that move is fully finished you’re going to encounter some weird edge cases like this one.
I didn't use Corona SDK's Facebook API but I encountered this problem when using Alamofire, the secondRequest always cancel in execution with the error -999, according to the posts I found on internet, the reason is that session property is deinit before completion of async work since it is out of the scope, I finally solved this problem by deinit the session property manually so the compiler won't deinit it at wrong position:
class SessionManager {
var session:SessionManager?
init() {
self.session = SessionManager(configuration:URLSessionConfiguration.ephemeral)
}
private func firstRequest() {
guard let session = self.session else {return}
session.request(request_url).responseData {response in
if let data=response.data {
self.secondRequest()
}
}
private func secondRequest() {
guard let session = self.session else {return}
session.request(request_url).responseData {response in
if let data=response.data {
self.secondRequest()
}
//session will no longer be needed, deinit it
self.session = nil
}
}
Our company's app has many -999 error in iOS. I have searched around, find the reason has two, like the network task has been dealloc or the certificate isn't valid. But I have checked our code, these two aren't possible. I am using Alamofire
which is using URLSession. Luckily, our company's android app's network is normal. So we check the difference. We found the http request from iOS is Http2.0, while android is Http1.1. So we force the backend http support version down to http1.1, then -999 error count descends!!!
I think there maybe some bug in Apple's URLSession. Check the link New NSURLSession for every DataTask overkill? for some detail thoughts
Please check If you call cancel() on URLSessionDataTask to fix
NSURLErrorDomain Code=-999 "cancelled"
I was getting this error in iOS specific version of Xamarin app. Not sure the underlying cause, but in my case was able to work around it by using post method instead of get for anything passing the server context in the request body -- which makes more sense anyway. Android / Windows / the service all handle the GET with content, but in iOS app will become partially unresponsive then spit out the 999 NSUrlErrorDomain stuff in the log. Hopefully, that helps someone else running into this. I assume the net code is getting stuck in a loop, but could not see the code in question.
For my Cordova project (or similar), turns out it was a plugin issue. Make sure you're not missing any plugins and make sure they're installed properly without issue.
Easiest way to verify this is simply to start fresh by recreating the Cordova project (cordova create <path>) along with the required platforms (cordova platform add <platform name>) and add each plugin with the verbose flag (--verbose) so that you can see if anything went wrong in the console log while the plugin is being downloaded, added to project and installed for each platform (cordova plugin add cordova-plugin-device --verbose)
Recap:
cordova create <path>
cordova platform add <platform name>
cordova plugin add cordova-plugin-device --verbose
For my case, I used an upload task post that did not need body contents:
// The `from: nil` induces error "cancelled" code -999
let task = session.uploadTask(with: urlRequest, from: nil, completionHandler: handler)
The fix is to use zero byte data instead of nil,
let task = session.uploadTask(with: urlRequest, from: Data(), completionHandler: handler)
The framework documentation doesn't specify why the from bodyData is an optional type, or what happens when it is nil.
We solved this problem by reloading the web view when it failed loading.
extension WebViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
webView.reload()
}
}

Resources