Jack Vo
Jack Vo

Reputation: 319

Failed to resume, pause, stop ChromeCast on Android sender

I have been able to create ChromeCast iOS sender without any issue but when I start to build the Android sender, I keep getting IllegalStateException (with error current media session is not found) when trying to pause, seek or stop the current video from ChromeCast.

This is how I connect the cast:

 private void launchReceiver(){
    try {
        setupCastClientListener();
        Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions.builder(mSelectedDevice, mCastClientListener);


        // Connect to Google Play services
        mConnectionCallbacks = new ConnectionCallbacks();
        mConnectionFailedListener = new ConnectionFailedListener();

        mApiClient = new GoogleApiClient.Builder(this)
        .addApi(Cast.API, apiOptionsBuilder.build())
        .addConnectionCallbacks(mConnectionCallbacks)
        .addOnConnectionFailedListener(mConnectionFailedListener)
        .build();
        mApiClient.connect();
    }catch(Exception e) {
        Log.e(TAG, "Failed launchReceiver", e);
    }
}

private void attachCustomMediaChannel(){
    if(mCustomChannel==null){
        mCustomChannel = new CustomMediaChannel();
        mCustomChannel.setOnStatusUpdatedListener(
                new RemoteMediaPlayer.OnStatusUpdatedListener() {
                    @Override
                    public void onStatusUpdated() {
                        MediaStatus mediaStatus = mCustomChannel.getMediaStatus();
                        //MediaInfo mediaInfo = mCustomChannel.getMediaInfo();
                        isPlayingContent = mediaStatus.getPlayerState() == MediaStatus.PLAYER_STATE_PLAYING;
                        updateControlsUI();
                    }
                });

        mCustomChannel.setOnMetadataUpdatedListener(
                new RemoteMediaPlayer.OnMetadataUpdatedListener() {

                    @Override
                    public void onMetadataUpdated() {
                        updateControlsUI();
                    }
                });
        try{
            Cast.CastApi.setMessageReceivedCallbacks(
                    mApiClient, 
                    mCustomChannel.getNamespace(), 
                    mCustomChannel);
        }catch(IOException e){
            Log.e(TAG, "Exception while creating channel", e);
        }

        //Request update status
        mCustomChannel.requestStatus(mApiClient).setResultCallback(
                new ResultCallback<RemoteMediaPlayer.MediaChannelResult>() {
                    @Override
                    public void onResult(MediaChannelResult result) {
                        Status status = result.getStatus();
                        if (!status.isSuccess()) {
                            Log.e(TAG, "Failed to request status [" + status.toString() + "]");
                        }
                    }
                });
    }
}


    private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks{
    @Override
    public void onConnected(Bundle connectionHint){
        if(mWaitingForReconnect){
            mWaitingForReconnect = false;
        }else{
            try{
                Cast.CastApi.launchApplication(mApiClient, CHROME_CAST_ID, false)
                .setResultCallback( 
                        new ResultCallback<Cast.ApplicationConnectionResult>() {
                            @Override
                            public void onResult(ApplicationConnectionResult result) {
                                Status status = result.getStatus();
                                String sessionId = result.getSessionId();
                                boolean wasLaunched = result.getWasLaunched();
                                if(status.isSuccess()){
                                    mApplicationStarted = true;
                                    setCastButtonAttribute(getResources().getString(R.string.chrome_cast_stop_casting), stopCastingClickListener);
                                    attachCustomMediaChannel();
                                }else{
                                    teardown();
                                }
                            }
                        });
            }catch(Exception e){
                Log.e(TAG, "Failed to launch application",e);
            }
        }
    }

    @Override
    public void onConnectionSuspended(int cause){
        mWaitingForReconnect = true;
    }
}

private class ConnectionFailedListener implements GoogleApiClient.OnConnectionFailedListener{
    @Override
    public void onConnectionFailed(ConnectionResult result){
        teardown();
    }
}

Below is the code to pause/stop/resume in my Android sender:

private void loadMedia(String url, String imageUrl, String title, long startTime, String customData, Boolean autoPlay){
    try{
        MediaMetadata mediaMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
        mediaMetadata.putString(MediaMetadata.KEY_TITLE, title);
        mediaMetadata.addImage(new WebImage(Uri.parse(imageUrl), 100, 150));
        mediaMetadata.putString("customData", customData);

        MediaInfo mediaInfo = new MediaInfo.Builder(url)
        .setContentType("video/mp4")
        .setStreamType(MediaInfo.STREAM_TYPE_NONE)
        .setMetadata(mediaMetadata)
        .build();

        mCustomChannel.load(mApiClient, mediaInfo, autoPlay, startTime);

        restartTrickplayTimer();
    }catch(IllegalArgumentException e){
        Log.e(TAG, "Load Media failed!");
    }
}

private void watchSelectedVideo(){
    String url = "http://cloudfront.net/testmovie.mp4";
    String imgUrl = "http://cloudfront.net/testmovie-220x330.jpg";
    String title = "Test movie";
    long startTime = 0;
    String customData = getCustomData();
    Boolean autoPlay = true;
    loadMedia(url, imgUrl, title, startTime, customData, autoPlay);
}

private void resumePlaying(){
    try{
        if(mCustomChannel!=null && mApiClient.isConnected()){
            mCustomChannel.play(mApiClient);
        }

    }catch(IOException e){
        Log.e(TAG, "Exception while trying to resume the video", e);
    }catch(IllegalStateException stateEx){
        Log.e(TAG, "Exception while trying to resume the video", stateEx);
    }
}

private void pausePlaying(){
    try{
        if(mCustomChannel!=null && isConnected()){
            mCustomChannel.pause(mApiClient);
        }
    }catch(IOException e){
        Log.e(TAG, "Exception while trying to pause the video", e);
    }catch(IllegalStateException stateEx){
        Log.e(TAG, "Exception while trying to pause the video", stateEx);
    }
}

private void stopPlaying(){
    try{
        if(mCustomChannel!=null && isConnected()){
            mCustomChannel.stop(mApiClient);
            resetUI();
        }

    }catch(IOException e){
        Log.e(TAG, "Exception while trying to stop the video", e);
    }catch(IllegalStateException stateEx){
        Log.e(TAG, "Exception while trying to stop the video", stateEx);
    }
}

Even the setOnMetadataUpdatedListener and setOnMetadataUpdatedListener were not fired even though ChromeCast has started to playback the content and the requestStatus callback kept returned "statusCode=SERVICE_DISABLED, resolution=null". Any help will be greatly appreciated.

Upvotes: 0

Views: 1044

Answers (1)

Ali Naddaf
Ali Naddaf

Reputation: 19094

Your post is missing some critical portions of your application; for example:

  • what does setupCastClientListener() do?
  • what is CustomMediaChannel class? Why do you need a custom media channel anyway? It is very rare that one would need to write a custom media channel.

I suggest you start with one of the samples that we have on the github and make sure that runs and then see what the flow is and how you can adapt that to your needs.

Upvotes: 0

Related Questions