ChromeCast background video playback support iOS

夙愿已清 提交于 2019-12-04 19:32:34


I have a problem that when I my application goes in background the GCKSocket of chromecast iOS api closes and I get this typr of error from api

-[GCKCastSocket socketDidDisconnect:withError:]  socketDidDisconnect:withError: "(null)"

and then if I bring the application to foreground the api creates the socket automatically and set the playback state to paused. If I now try to play the video again it plays normally.

I am starting the playback of the media on the background thread like this.

                                             0), ^ {
[[CastViewController instance]];      


How to keep playback alive even when the application goes to background?

here is the logging from api

2014-02-25 17:19:01.388 CastVideos[28470:60b] -[GCKCastSocket disconnect] disconnect

2014-02-25 17:19:01.391 CastVideos[28470:60b] -[GCKCastSocket doTeardownWithError:] doTeardownWithError

2014-02-25 17:19:01.395 CastVideos[28470:60b] -[GCKCastSocket doTeardownWithError:] notifying delegate that socket is disconnected

2014-02-25 17:19:01.399 CastVideos[28470:60b] -[GCKHeartbeatChannel didDisconnect] disconnected - stopping heartbeat timer if necessary

2014-02-25 17:19:01.457 CastVideos[28470:60b] -[GCKCastSocket socketDidDisconnect:withError:] socketDidDisconnect:withError: "(null)"


Currently, the Cast iOS SDK closes the socket when you go to background, and that is not a configurable item at this point. However, that doesn't mean that your media playback on the Cast device should stop; in fact the correct behavior is the following:

  • if user has explicitly disconnected herself from the cast device, and if she is the last connected device to the receiver, then the receiver should stop the playback, otherwise receiver should continue playback.

The key here is the "explicit" part; if, for example, the sender goes out of wifi range and gets disconnected, or if the sender goes to sleep and gets disconnected, these are considered "implicit" disconnects and should not cause the receiver to stop.

In other words, it is really the receiver who should have the logic to decide if it has to stop itself or keep playing, and for that to work, it has to be able to decided if a device disconnect was caused implicitly or explicitly. In the current receiver SDK APIs, unfortunately that is not included in the onSenderDisconnected event that the receiver gets; in the next update or so of the receiver, it will change so receiver can see why a disconnect is happening, at least as much as it needs to distinguish an explicit from an implicit one. Then it can implement the logic. Meanwhile, sender needs to have an out-of-band channel to send a message indicating its explicit intention.

Update: Receiver SDK has been updated to have the information that can tell whether the sender was implicitly or explicitly disconnected, see the docs.


There is a hack that helps to keep the connection alive when it goes in background.

You can replace the call for a GCKSessionManager.suspendSession(with:) for a custom that doesn't disconnect.

extension GCKSessionManager {
    static func ignoreAppBackgroundModeChange() {
        let oldMethod = class_getInstanceMethod(GCKSessionManager.self, #selector(GCKSessionManager.suspendSession(with:)))
        let newMethod = class_getInstanceMethod(GCKSessionManager.self, #selector(GCKSessionManager.suspendSessionIgnoringAppBackgrounded(with:)))
        method_exchangeImplementations(oldMethod, newMethod)


    func suspendSessionIgnoringAppBackgrounded(with reason: GCKConnectionSuspendReason) -> Bool {
        guard reason != .appBackgrounded else { return false }
        return suspendSession(with:reason)

Just call the method ignoreAppBackgroundModeChange() once from anywhere before to enter in background.

The problem I've found with this is when you return to the app you are going to have a network error after a few seconds, because Google Cast is trying to reconnect to the device.

I fixed that reconnecting when the error happens, with a flag to identify it entered in background before.

reference: How to keep GCKCastSession alive when app goes to background