Google Cast custom receiver timing out

浪尽此生 提交于 2019-12-04 06:23:59

I figured out an alternative way to stop this which is more efficient than periodically sending a silent clip, but it feels dirty. Basically we have to stop Chromecast's setTimeout from firing and closing the connection due to no media. The quickest solution is to simply re-declare setTimeout as a dummy no-op function before loading the Chromecast receiver script. It does not seem to break anything Chromecast-related in this scenario because it looks like Chromecast's timeouts are all related to video which aren't relevant to this use case.

window._setTimeout = window.setTimeout;
window.setTimeout = function(a, b) {
    // disable setTimeout so chromecast won't kill us after 5 minutes...
};

Then in our own app if we need to use a timeout we call _setTimeout instead.

I would be interested if anyone has discovered a better way to achieve this, aside from manually hosting cast_receiver_framework.js with the offending line commented out (which is inside the Wn(a, b) function) or sending a silent clip every few minutes. But self-hosting isn't recommended by Google.

A better solution may be to dig deep in the minified code to work out how Xn(a) is called as that disables the timeout whenever media is playing, and then find a way to call that from within the Chromecast app.

JRP

I ran into the same problem while developing a custom receiver app that does not play media. Here is the solution I implemented:

var idleTime = 0;

const context = cast.framework.CastReceiverContext.getInstance();

const CUSTOM_CHANNEL = '[MY CHANNEL HERE]';

context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
    var eventData = customEvent.data;
    parseCommand(eventData);
    idleTime = 0;
});


const options = new cast.framework.CastReceiverOptions();

options.disableIdleTimeout = true;

context.start(options);

var idleInterval = setInterval(timerIncrement, 60000); // 1 minute

function timerIncrement() {
    idleTime = idleTime + 1;
    if (idleTime > 4) { // 5 minutes
        context.stop();
    }
}

With CastReveiverOptions I disable idle timeout, which according to the documentation: "If true, the receiver will not set an idle timeout to close receiver if there is no activity. Should only be used for non media apps." https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.CastReceiverOptions#constructor_1

Since mine is a "non media app," I believe this is correct usage. I then set my own time out based on 5 minutes of inactivity in my custom channel.

Loading a short inaudible audio clip from the sender to the receiver every 4 minutes seems to do the trick. This should not impact performance much if the file is small. Here is some android code.

    MediaMetadata metadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MUSIC_TRACK);

    MediaInfo mediaInfo = new MediaInfo.Builder("https://some-inaudible-clip.mp3")
            .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
            .setContentType("audio/mpeg")
            .setMetadata(metadata)
            .build();

    RemoteMediaClient remoteMediaClient = castSession.getRemoteMediaClient();

    remoteMediaClient.load(mediaInfo, true);

It is possible to send a custom namespace message from the receiver to the sender. That should keep the heartbeat live. However, your use case is not directly supported by the Cast SDK, so you would have to experiment on a solution.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!