How do I keep a ChromeCast route alive when my app is in the background on battery power?

独自空忆成欢 提交于 2019-12-05 21:48:16

I eventually got around this by refusing to disconnect the message streams and tear down the session when the route was disconnected under these conditions, and silently re-select the route when it became available again. The route gets deselected, but it does not affect my casting session.

To do this, I check to see if the route exists when it's unselected.

public void onRouteUnselected(final MediaRouter router, final RouteInfo route) {
    if (!onUiThread()) {
        new Handler(Looper.getMainLooper()).post((new Runnable() {
            @Override
            public void run() {
                onRouteUnselected(router, route);
            }
        }));

        return;
    }

    boolean isThisRouteAvailable = doesRouterContainRoute(router, route);

    mRouteToReconnectTo = null;

    if (isThisRouteAvailable) {
        // Perform code to close the message streams and tear down the session.
    } else {
        // The route was unselected because it's no longer available from the router,
        // so try to just keep playing until the message streams get disconnected.
        mRouteToReconnectTo = route;
        // Short-circuited a disconnect.
    }
}

Later, when the route comes back, we can immediately re-select it.

@Override
public void onRouteAdded(MediaRouter router, RouteInfo route) {
    super.onRouteAdded(router, route);
    // if mRouteToReconnectTo is not null, check to see if this route
    // matches it, and reconnect if it does with router.selectRoute(route)
}

@Override
public void onRouteSelected(final MediaRouter router, final RouteInfo route) {
    if (!onUiThread()) {
        new Handler(Looper.getMainLooper()).post((new Runnable() {
            @Override
            public void run() {
                onRouteSelected(router, route);
            }
        }));

        return;
    }

    if (areRoutesEqual(mRouteToReconnectTo, route)) {
        // Short-circuited a reconnect.
        mRouteToReconnectTo = null;
        return;
    }

    mRouteToReconnectTo = null;

    // Standard post-selection stuff goes here
}

There's no good way to compare two RouteInfo's, so I ended up writing a helper function that compared their description strings.

Rooster's answer is perfectly feasible and actually provides good insight as to how to re-connect to a route once it comes back online....

but....just to give further insight on what's going on....

You're getting...

I/MediaRouter(19970): Choosing a new selected route because the current one is no longer selectable: MediaRouter.RouteInfo{ uniqueId=... }

because when the device goes to sleep and is NOT plugged into a power source, the WIFI hardware is going into a low-power profile mode (and possibly shutting down entirely). This results in packet loss and subsequently causes the MedaRouter to fire the onRouteUnselected callback.

To prevent the Wifi from turning off you could set a WakeLock on the Wifi in the following manner:

WifiLock wifiLock;
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF , "MyWifiLock");
wifiLock.acquire();

Using the flag WifiManager.WIFI_MODE_FULL_HIGH_PERF will keep the WIFI hardware alive and active when the device goes to sleep. Caution, this flag is only available to API 12 and above.

I tried using the WifiManager.WIFI_MODE_FULL flag when creating the WifiLock, but that didn't seem to do the trick.

Obviously anyone using any type of WifiLock or WakeLock should take considerable care in making sure locks released when no longer needed. Also, beware this will cause battery drain when the device screen is off.

If you used the sample code (Android in this case), you're probably doing this...

mSession.setStopApplicationWhenEnding(true);
mSession.endSession();

...when the route is unselected. If you instead do this...

mSession.setStopApplicationWhenEnding(false);
mSession.endSession();

...then you can clean up the session, but the Chromecast will keep the application alive. When the route becomes available again (or possibly when the user picks the device again) you can build a new session. I have yet to explore how to determine if the new session is talking to a "brand new" instance of the application or to the application left running from another session, but I'll update this answer when I do.

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