3

ChromeCast への音​​楽の送信をサポートする Android アプリに取り組んでいます。アプリがバックグラウンドで実行されている間、ユーザーが音楽プレイリスト全体をキャストできるようにしたいと考えています。

Nexus 7 が USB 電源に接続されておらず、設定で画面非アクティブ タイムアウトを 15 秒にすると、デバイスが画面の電源をオフにしてから約 90 秒後にアプリが ChromeCast から切断されます。

MediaRouter.Callbackへの呼び出しを取得していることを確認しました。これはonRouteUnselected、ユーザーがルートから切断したときに取得するコールバックであるため、ApplicationSession.

再度接続して logcat を確認すると、ほぼ同時に次のメッセージが表示されます。

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

アプリがバックグラウンドにあるときにルートが選択されないようにするために何かできることはありますか?それとも、必要な動作を得るために他にできることはありますか?

4

3 に答える 3

3

おんどりの答えは完全に実現可能であり、実際にルートがオンラインに戻ったときにルートに再接続する方法について良い洞察を提供します....

しかし....何が起こっているのかについてさらに洞察を与えるために....

あなたは得ています...

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

これは、デバイスがスリープ状態になり、電源に接続されていない場合、WIFI ハードウェアが低電力プロファイル モードになる (場合によっては完全にシャットダウンする) ためです。これによりパケット損失が発生し、その後 MedaRouter が onRouteUnselected コールバックを起動します。

Wifi がオフにならないようにするには、次の方法で Wifi に WakeLock を設定できます。

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

フラグ WifiManager.WIFI_MODE_FULL_HIGH_PERF を使用すると、デバイスがスリープ状態になったときに WIFI ハードウェアがアクティブなままになります。注意: このフラグは API 12 以降でのみ使用できます。

WifiLock を作成するときに WifiManager.WIFI_MODE_FULL フラグを使用してみましたが、うまくいかなかったようです。

明らかに、あらゆる種類の WifiLock または WakeLock を使用している人は、ロックが不要になったときに確実にロックが解除されるように、かなりの注意を払う必要があります。また、デバイスの画面がオフの場合、これによりバッテリーが消耗することに注意してください。

于 2013-10-19T20:50:17.357 に答える
3

私は最終的に、メッセージ ストリームを切断することを拒否し、これらの条件下でルートが切断されたときにセッションを破棄し、ルートが再び利用可能になったときに静かに再選択することで、これを回避しました。ルートは選択解除されますが、キャスト セッションには影響しません。

これを行うには、ルートが選択されていないときにルートが存在するかどうかを確認します。

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.
    }
}

後でルートが戻ってきたら、すぐに再選択できます。

@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
}

2 つの RouteInfo を比較する良い方法はないので、それらの説明文字列を比較するヘルパー関数を作成することになりました。

于 2013-10-16T19:30:13.320 に答える
0

サンプル コード (この場合は Android) を使用した場合は、おそらくこれを行っています...

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

...ルートが選択されていない場合。代わりにこれを行うと...

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

...その後、セッションをクリーンアップできますが、Chromecast はアプリケーションを存続させます。ルートが再び利用可能になったとき (または、ユーザーがデバイスを再度選択したとき) に、新しいセッションを構築できます。新しいセッションがアプリケーションの「真新しい」インスタンスと通信しているか、別のセッションから実行されているアプリケーションと通信しているかを判断する方法をまだ検討していませんが、そうするときにこの回答を更新します。

于 2014-01-26T21:27:17.610 に答える