MPMoviePlayerController irreversibly switching to playbackState "paused" - cocoa-touch

I'm using a single instance of MPMoviePlayerController to playback short clips (3-10 Minutes) via HTTP-Download in an iPad-Application. This usually works nicely, but in rare cases the following pattern occurs:
A video starts playing (usually 1 up to 4 seconds of it)
The playbackState switches to MPMoviePlaybackStatePaused. This is unrelated to the loadState. The file keeps coming and loadState indicates "playable" or even "playthroughOK".
Hitting the play-button or calling [controller play] has no effect
Video-Playback is broken from this point on ("broken" meaning any subsequent stream initiated with [controller setContentURL:] will almost certainly result in the same behavior)
Video-Playback keeps being broken even after a restart of the App.
All you can do is reboot the device.
The defect is not tied to any particular video file breaking the app reproducably
I'd suspect my iPad used for development to be broken but some of our users experience this problem too (including temporary fix of the problem by rebooting the iPad), and are - as you might guess - not happy.
Is anyone else experiencing this problem? Any fix out there?

I was facing a similar intermittent problem on the app I am working on. It would only happen sometimes and only on 2 of the ~12 iPads I was testing on - all were on iOS 3.2.2.
My video was local, but the symptoms are the same: after hitting play it would auto-pause itself and I couldn't restart it. This would persist across app restarts and would require a device restart to fix.
What finally fixed it for me was to set MPMoviePlayerController useApplicationAudioSession to NO. In my case, I was starting another audio session for something else and, in these rare instances, they were screwing each other up somehow.
Not sure if this was the same problem the original poster was having, but wanted to record my fix somewhere as the internet wasn't much help on this one and I burned some serious time figuring it out.

Apparently, this was an issue with iPhoneOS 3.2. After an upgrade to iPhoneOS 3.2.1 the problem went away.

Related

Error Domain=NSPOSIXErrorDomain Code=28 “No space left on device” UserInfo={_kCFStreamErrorCodeKey=28, _kCFStreamErrorDomainKey=1}

Lately numerous network requests with Alamofire made from our iOS device fail with the following error:
Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device"
UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask
.<3>,
_kCFStreamErrorDomainKey=1, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask .<3>" ),
_kCFStreamErrorCodeKey=28}
Our app has a mechanism to send a network request if the user has moved +- 10 meters. This is checked every 5 seconds, so in theory every five seconds a call can be made. The network request fails occasionally with this message, returning no status code and the above error.
The message implies the error has to do with available disk/memory space on the device. However, after checking both there is no link to be found since there is plenty of space available. Also, the error occurs on multiple devices, all running iOS 14.4 or higher.
Is there information available regarding error code 28 and what could be the culprit on iOS devices? Even better; how can this error be prevented?
To answer the occurrence of the error itself:
NSPOSIXErrorDomain Code=28 "No space left on device"
With logs in the Xcode terminal:
2021-05-07 15:56:50.873428+0200 MYAPP[21757:7406020] [] nw_path_evaluator_create_flow_inner NECP_CLIENT_ACTION_ADD_FLOW 05CD829A-810D-412F-B86E-7524369359E8 [28: No space left on device]
2021-05-07 15:56:50.877243+0200 MYAPP[21757:7400322] Task <5504BCDF-7DFE-4045-BD4B-E75054636D5B>.<1> finished with error [28] Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalUploadTask <5504BCDF-7DFE-4045-BD4B-E75054636D5B>.<1>, _kCFStreamErrorDomainKey=1, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalUploadTask <5504BCDF-7DFE-4045-BD4B-E75054636D5B>.<1>"
), _kCFStreamErrorCodeKey=28}
It appears to get called when there are too many NSURLSessions created, reaching a limit of (in our tests) 600-700 sessions, which are not maintained or closed properly. The error started to get thrown since iOS 14, so it is interesting to see if there was a limit introduced.
Linked is a github issue raised stating the same issues on the ktor microservices framework by JetBrains, pointing in the same direction, mentioning the invalidation of sessions to prevent this issue:
https://github.com/ktorio/ktor/issues/1341
In our own project the origin of the problem turned out to be our implementation of the StarScream websocket library. This might not be relevant for the issues others are having, but explained anyways to create a complete picture of the problem. It is the cause and fix of our specific situation.
At first we assumed it had something to do with the URLSession created by Alamofire (networking library used) since POST requests started to get cancelled, and a kill of the app seemed the only solution to do requests again.
However, we also make use of websocket connections using the StarScream library, which attempts to connect to an socket, and if failed retry to connect every two seconds for a max time of two hours. This would mean for two hours, every two seconds, we connect to the socket -> receive a failure to connect -> disconnect the socket -> connect again. Using a singleton of the socket it was thought there was no possibility of creating multiple URLSessions, since the socket was only initiated once. However calling the connect to the socket again would create a new nw_connection object every single time, since the library did not handle the disconnect properly.
image of NWConcrete_nw_connection objects generated in socket connection
The way this was validated was using the instruments app to check for the creation of new nw_connection objects. Logged as a "memory leak" there, the creation of the nw_connection objects was getting logged and the solution was to make sure we disconnect the socket (invalidate the session) properly before connecting again.
I hope to answer a big part of the issue here, and I will mark my own question answered since this was the solution to the problem at hand. I think Apple should consider giving accurate reports on the number of objects created being limited, instead of giving an error "No space left on device".
Just wanted to chime in with more info, since we're experiencing the same issue.
Based on our analytics, this issue only started happening since iOS 14. We've verified it happening on 14.2, 14.4 and 14.5. Naturally the most straightforward cause for this error would be low memory or disk storage. We've excluded this option with additional logging, as you seem to have done as well.
A possibly related SO post has attributed the issue to a network inspecting framework that was enabled in their release build. It's worth checking if you use a similar tool.
Another report of this issue, this time on the Github of AFNetworking (predecessor to the Alamofire library you use), says they were able to fix it by limiting the creation of URLSession objects.
For us personally, neither of these did the trick. We created a support ticket with Apple, but this hasn't lead to a solution. They requested a small sample project that reproduces the issue, but the error only manifested after 7 days of continuous use in our app. If you have a faster way to reproduce this, it may be worth it to submit your own support ticket.
Hopefully this helps you find a solution, if you do please add this to your post to help others!

iOS8.1.2 didReceiveRemoteNotification method not called when device is not plugged in

In iOS version is 8.1.2,I found a really strange issue:
I implement below method to handle push info in appDelegate
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
If your device is not plugged in,this method is not called.
If you look around, you'll see that others thought it would be a bug in iOS 7.1 beta, fixed in 7.1 release version, but it has probably nothing to do with any beta, Testflight, specific 8.1.2 version etc, like you say in your answer. I'm pretty sure this is the only correct answer. By the way, I have the same issue, but in 8.1.3, so I guess it will reappear with you too.
Once you delete the app, restart your phone, and install the app, the didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler: is called perfectly fine (which explains the "Use tesflight!", "in 7.1.x it works!", etc), but if you do too much calculations as a result of receiving the remote notification or not calling the completion handler on time, the system will not like you anymore and start calling the method later when it wants to, which will generally be 0-30 minutes after your notification has been received, or veeery long (see update below). With me, sometimes that happened already after the first remote notification. Unless, of course, the device is plugged in, then it will be much more reliable.
Once you reconnect (plug in) the device, the system might then call your method, generally it takes up to 15 minutes before it gets called, or it might just work instantly if you push the same notification an hour later but that also is not sure. It's really a pain, but don't think about it as something that will be fixed or so, it's the way Apple created it.
UPDATE:
It will be called eventually. I sent a remote notification at 18.13h, and didReceiveRemoteNotification:fetchCompletionHandler: was not called until 09.41h the next day. So in my case, it took 15.5 hours until the method was called.
In my case, the reason for that is probably that I use remote notifications to start and stop location tracking in the background, which is heavy stuff.
After fount another answer about this problem,I am confirmed this really is a bug in iOS 8.1.2.
I'm very surprised there isn't much thing about it on the internet.
But through my test,it has nothing to do with provision profile,using Apple's TestFlight does not work.

Google Play Services Multiplayer matching players errors

I developed a game for android with the google play services realtime multiplayer feature. I currently have a problem when matching the players. I dont use any invite feature, so all players just use the automatch functionality.
My game can be played with 4 players, but games with just 3 or 2 players are also possible. For my testing with 2 devices i use:
RoomConfig.createAutoMatchCriteria(minNumberOfOpponents, maxNumberOfOpponents, 0);
If i keep starting, ending and restarting games for a number of times, it often happens that the clients are not connected correctly. In the working cases the games onRoomConnected is called correctly and the game starts. In some cases tho, this is not happening. In theses cases, one device finds the other device and its onPeerJoined() and onRoomConnecting() callback is called. onRoomConnected() is never called tho. Thats because the other device gets no information whatsoever, just the roomCreated callback is called, and thats it.
So one device finds the other, and gets the information that another device joined the room. It also gets informed when this device leaves the room again. But the other device doesnt recognize any of this.
If this helps. i had some issues with losing connection before, and fixed it by restarting the apiClient everytime a room left on any clint. I dont think this is related tho.
I thought that might be a problem with leaving the current room correctly, and somehow joining the old room again, but it also happens ehen starting the app for the first time. Also the apiClient reconnect should avoid this problem
Thx in advance
Edit: It seems like its just my nexus 5 which produces the error. Every other device i tested works fine. The Nexus 5 does too in most cases. If the clients get connected and the game starts, there has never been any problem. The errrr just happens on this one device, and only in maybe 5 out of 6 cases, when searching an online game.
It just stops getting any callbacks called, sometimes right after the onRoomCreated(), sometime after he found another peer and onRoomConnecting(), and sometimes after onRoomConnected() has been called.
The other device gets its appropiate callbacks called tho in these cases.
So if the error device stops at onRoomCreated() the other device finds the client.
If the error device finds the other device and gets onRoomConnecting() called and stops after, the other device gets its onRoomConnected().
And if the error device gets its onRoomConnected() called, it sometimes even stops getting any messages from there on, while the other device is already in the game.
Maybe this helps someone. i'm not 100 % sure i fixed my problem. Haven't tested it in depth, but it seems everything is working fine now.
My problem was, that i have 2 different threads in my application, where the standard activity GUI thread starts the apiClient and handles the callbacks, while the gameengine thread initiates the room creation and sends the reliable messages via the apiClient.
It seems, sometimes things mess up while the peers connect and trade their first data. Currently i avoided directly calling any apiClient actions from the gameengine thread, but use runOnGuiThread to handle these actions on the Activity Gui Thread.

iCloud KeyValue store not recognized on first launch

My app uses iCloud (key-value store) to sync an unique id between multiple devices. This works accept at the point were it really has to work, at the first launch of the app. It looks like the device isn't yet familiar with the values from iCloud at first launch, only after the app is installed and has been running for a while.
I check for the iCloud value in the viewDidLoad function on main view of the app.
So, my questions:
Is this the expected behavior?
If yes, is there another solution?
Could it be the case this is only a problem when running from Xcode, not the shipping version? If so, how to test?
Thanks!
Jasper
I had a similar issue where the NSUbiquitousKeyValueStoreDidChangeExternallyNotification wasn't triggering on the first launch after install, no matter how long I waited. Setting an initial key in the NSUBiquitousKeyValueStore seemed to solve this.
Immediately after adding the observer to the default store, I call:
[[NSUbiquitousKeyValueStore defaultStore] setString:#"testValue" forKey:#"testKey"];
[[NSUbiquitousKeyValueStore defaultStore] synchronize];
I use different keys (i.e. not testKey) for the actual data I want to sync.
When you first run an iCloud enabled App it has to pull all the data from Apple servers. The time it takes to do so depends on many things like what kind of network you're currently on (Edge, 3G, GPRS, WLAN). It also depends on how much traffic the iCloud server currently has to handle so the request to the iCloud server may take a few more seconds, no matter what type of network connectivity you have.
To sum it up: Yes, it sounds absolutely normal.
If running your App depends on those settings consider implementing a "Wait" or "Loading" view that stays on the screen as long as it takes for the App to perform a initial synch and load all needed data from the cloud. To not block the UI forever also implement a timeout for this view (if iCloud data not loaded within X seconds, dismiss the view and notify user).
You have no guarantee NSUbiquitousKeyValueStore would have finished its first synchronization as your app is launched for the first time. (In fact, on iOS 5, it's often starting to sync as you launch your app for the first time).
There is no way to know if the first initial sync has already happened, is ongoing or has finished. You can (in fact should) subscribe to NSUbiquitousKeyValueStoreDidChangeExternallyNotification. The trick is that if your store is empty on the iCloud server, you won't get any notification after the initial sync (since your local store is empty and the cloud store is empty as well, nothing really changed "externally" after the initial sync…)
Normally, you should not rely on the initial sync being done.
Be optimist at launch, even if your store is empty, push your values (e.g. your unique id) right away. If the initial sync happens concurrently or after and there is already some value on the server, your local values will be reset to the server values and you will get the NSUbiquitousKeyValueStoreDidChangeExternallyNotification notification with the NSUbiquitousKeyValueStoreInitialSyncChange reason.
Finally, if you really think knowing about the initial sync being completed or not, please file a bug to bugreport.apple.com and explain why you really need that.

Need iOS reference for what happens in sleep, standby and/or idle modes

I'm a new ObjC dev and after searching the Web and Apple's developer docs, I can't find a good succinct explanation of the various iOS device modes, and what goes on in these modes. I see a lot of little discussions, but nothing overarching about the big picture.
For example, I see that some Alarm applications for iPhone/iPad claim to be able to execute alarms (presumably not just system alerts) in the morning. I'm struggling to understand how that happens, even if the user lets the app just keep running overnight, assuming the device goes into sleep mode after no use.
So I don't know what happens when the device goes into sleep or standby mode. Is it just the screen dimming? Does the application in the foreground continue to execute code, go into some interim state like background mode in a saved state, or does it completely (even if temporarily) shut down?
I'd just like to be pointed to a website, a book or the portion of the Apple documentation that explains the various device states, what's going on under iOS 3 & 4 with the application in each state, and how to manage that if you'd like to build an app similar to a simulated bedside alarm clock that's "always on," etc.
Thanks in advance.
Those 'alarms' are Local Notifications, and are very handy. They're fired even when an application is closed, and even when the device is asleep.
The concept of asleep is not too tricky; when the user 'quits' your application (pressing the home button), your application will either be halted and placed into a frozen state (4.x), or quit entirely (3.x). Nonetheless, you are given the opportunity to do a few cleanup operations before the latter happens with the - (void)applicationWillTerminate:(UIApplication *)application method, and before the former happens with the - (void)applicationDidEnterBackground:(UIApplication *)application method (both are called upon your delegate class).
The concept of 'sleep' means that in both iPhone OS 3 and iOS 4 you'll receive the following method when your app loses focus (and also when an SMS comes in, or an alert, etc):
- (void)applicationWillResignActive:(UIApplication *)application
Really, most applications (with the exceptions of applications that are designed to work in the background, like voip, audio streaming, etc) simply quit on close. But if you need to, you can also suspend the freezing of your app and ask for more time to complete a task.
This was a lot easier to grasp in the 3.x days, but now with 4.x's 'multitasking' it becomes a bit harder. It's not too daunting though, and a read of this will help a bit.
This may be of help:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIApplication_Class/Reference/Reference.html
see the applicationState for UIApplicationState.