Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chromecast with multiple activity

I'm developing an application supporting both Chromecast and ActionbarSherlock.
In every activity, I create a MediaRouteButton in the ActionBar.

My problem is, I didn't connect to the Chromecast device in the first Activity, and go to the second Activity. In the second one, I connect to the Chromecast device. It runned into the onRouteSelected() of the second Activity, then runned into onDeviceAvailable() -> openSession() of the first Activity.
I don't know why it didn't run into onDeviceAvailable() on the second Activity.
Can anyone help me?

Thanks in advance

Here is my code in both activities:

@Override
protected void onCreate(Bundle savedInstanceState) {   
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_cast_sample);

    mMetaData = new ContentMetadata();    


    mMediaSelectionDialog = new MediaSelectionDialog(this);
    mCastContext = new CastContext( getApplicationContext());
    MediaRouteHelper.registerMinimalMediaRouteProvider( mCastContext, this );
    mMediaRouter = MediaRouter.getInstance( getApplicationContext() );
    mMediaRouteSelector = MediaRouteHelper.buildMediaRouteSelector( MediaRouteHelper.CATEGORY_CAST );
    mMediaRouterCallback = new MyMediaRouterCallback();
}
   @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // TODO Auto-generated method stub
        getSupportMenuInflater().inflate(R.menu.cast_sample, menu);
        com.actionbarsherlock.view.MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
        mMediaRouteButton = (MediaRouteButton) mediaRouteMenuItem.getActionView();
        mMediaRouteButton.setRouteSelector( mMediaRouteSelector );
        return true;
    }


    @Override
    protected void onStart() {
        super.onStart();
        mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
                MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);       
    }



    @Override
    protected void onStop() {
        mMediaRouter.removeCallback(mMediaRouterCallback);
        super.onStop();        
    }

  private class MyMediaRouterCallback extends MediaRouter.Callback {
        @Override
        public void onRouteSelected(MediaRouter router, RouteInfo route) {
            MediaRouteHelper.requestCastDeviceForRoute(route);
        }

        @Override
        public void onRouteUnselected(MediaRouter router, RouteInfo route) {
            try {
                if (mSession != null) {
                    logVIfEnabled(TAG, "Ending session and stopping application");
                    mSession.setStopApplicationWhenEnding(true);
                    mSession.endSession();
                } else {
                    Log.e(TAG, "onRouteUnselected: mSession is null");
                }
            } catch (IllegalStateException e) {
                Log.e(TAG, "onRouteUnselected:");
                e.printStackTrace();
            } catch (IOException e) {
                Log.e(TAG, "onRouteUnselected:");
                e.printStackTrace();
            }
            mMessageStream = null;
            mSelectedDevice = null;
        }
    }


  @Override
  public void onDeviceAvailable(CastDevice device, String myString,
        MediaRouteStateChangeListener listener) {
        mSelectedDevice = device;
        logVIfEnabled(TAG, "Available device found: " + myString);
        openSession();
  }
  private void openSession() {
        mSession = new ApplicationSession(mCastContext, mSelectedDevice);
        .....
  }
like image 412
Huy Duong Tu Avatar asked Dec 20 '22 22:12

Huy Duong Tu


2 Answers

I wrote a separate ChromecastAdapter Singleton class that implements MediaRouteAdapter. I call registerMinimalMediaRouteProvider on creation and never unregister it. The ChromecastAdapter contains all the Chromecast state. All I have to do in each activity is pass in my MediaRouteButton and call setRouteSelector on it.

public class ChromeCastAdapter implements MediaRouteAdapter { 

    ...
    private static ChromeCastAdapter instance = null;

    public static ChromeCastAdapter getInstance(Context activity) {
        if (instance == null) {
            instance = new ChromeCastAdapter(activity);
        }
        return instance;
    }

    private ChromeCastAdapter(Context activity) {
        this.context = activity.getApplicationContext();

        castContext = new CastContext(context);
        mediaRouter = MediaRouter.getInstance(context);

        MediaRouteHelper.registerMinimalMediaRouteProvider(castContext, this);

        mediaRouteSelector = MediaRouteHelper.buildMediaRouteSelector(MediaRouteHelper.CATEGORY_CAST);

        mediaRouterCallback = new MediaRouterCallback();
        mediaRouter.addCallback(mediaRouteSelector, mediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
    }

    public void setMediaRouteButtonSelector(MediaRouteButton mediaRouteButton) {
        mediaRouteButton.setRouteSelector(mediaRouteSelector);
    }
    ...
}
like image 157
ActiveApathy Avatar answered Jan 13 '23 11:01

ActiveApathy


I found the issue here:
MediaRouteHelper.registerMinimalMediaRouteProvider( mCastContext, this ); will return false in the second Activity. Because I already registered it in the first Activity.

I just think a temporary solution that:

  @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        MediaRouteHelper.registerMinimalMediaRouteProvider( mCastContext, this );
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        MediaRouteHelper.unregisterMediaRouteProvider(mCastContext);
    }

But When I unregister, I have to connect to the Chromecast device again. Because It'll release all the state of CastContext.

Does anyone helps anyidea?

like image 24
Huy Duong Tu Avatar answered Jan 13 '23 13:01

Huy Duong Tu