How To Get Cast List and Cast Video To TV From VideoView?

I am having a difficult time getting my casting app to work. I have Phillips TV that has a Google Chromecast. So this chromecast that is connected to my TV is the receiver. Building the sender app is the challenge for me. I can't even get the "Cast Button" to bring up the dialog window that shows all the receivers. After that obstacle, my next challenge is to cast the video in the VideoView to Chromecast. Here is what I have so far...

My main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <VideoView
        android:id="@+id/video_player"
        android:layout_width="match_parent"
        android:layout_height="500dp"/>

    <View
        android:id="@+id/v0"
        android:layout_width="match_parent"
        android:layout_height="20dp"
        android:layout_below="@id/video_player"/>

    <Button
        android:id="@+id/play_video"
        android:drawableLeft="@drawable/ic_baseline_play_arrow_24"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:drawableTint="@android:color/white"
        android:layout_below="@+id/v0"
        android:text="@string/play_video"
        android:textStyle="bold"
        tools:ignore="RtlHardcoded" />

    <View
        android:id="@+id/v1"
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:layout_below="@id/play_video"/>

    <Button
        android:id="@+id/cast_video"
        android:drawableLeft="@drawable/ic_baseline_cast_24"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/v1"
        android:drawableTint="@android:color/white"
        android:text="@string/cast_video"
        android:textStyle="bold"
        tools:ignore="ContentDescription,RtlHardcoded" />

    <androidx.mediarouter.app.MediaRouteButton
        android:id="@+id/media_route_button"
        app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/cast_video"
        android:layout_centerHorizontal="true"/>


</RelativeLayout>

Strings.xml

<resources>
    <string name="app_name">Cast Media Example</string>
    <string name="app_id">4F8B3483</string>
    <string name="play_video">Play Video</string>
    <string name="cast_video">Cast Video</string>
</resources>

MainActivity.java

package com.example.castmediaexample;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.mediarouter.app.MediaRouteButton;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.Toast;
import android.widget.VideoView;

import com.google.android.gms.cast.framework.CastButtonFactory;
import com.google.android.gms.cast.framework.CastContext;
import com.google.android.gms.cast.framework.CastOptions;
import com.google.android.gms.cast.framework.CastState;
import com.google.android.gms.cast.framework.CastStateListener;
import com.google.android.gms.cast.framework.IntroductoryOverlay;
import com.google.android.gms.cast.framework.OptionsProvider;
import com.google.android.gms.cast.framework.SessionProvider;
import com.google.android.gms.cast.framework.media.CastMediaOptions;
import com.google.android.gms.cast.framework.media.NotificationOptions;
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    public VideoView vw;
    public Button playVideoBtn, castVideoBtn;
    public ProgressDialog pd;
    public MediaRouteButton mediaRouteButton;
    public CastStateListener castStateListener;
    public CastContext castContext;
    public IntroductoryOverlay mIntroductoryOverlay;

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

        vw = findViewById(R.id.video_player);
        playVideoBtn = findViewById(R.id.play_video);
        castVideoBtn = findViewById(R.id.cast_video);

        castStateListener = new CastStateListener() {
            @Override
            public void onCastStateChanged(int newState) {
                if (newState != CastState.NO_DEVICES_AVAILABLE) {
                    showIntroductoryOverlay();
                }
            }
        };

        castContext = CastContext.getSharedInstance(this);


        playVideoBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                pd = new ProgressDialog(MainActivity.this);
                pd.setCancelable(true);
                pd.show();

                String videoPath = "android.resource://com.example.castmediaexample/raw/roxie_sample_video";
                Uri videoUri = Uri.parse(videoPath);
                vw.setVideoURI(videoUri);

                MediaController mc = new MediaController(MainActivity.this);
                vw.setMediaController(mc);
                mc.setAnchorView(vw);

                vw.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        pd.dismiss();
                        vw.requestFocus();
                        vw.start();
                    }
                });

                vw.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                    @Override
                    public boolean onError(MediaPlayer mp, int what, int extra) {
                        pd.dismiss();
                        Toast.makeText(getApplicationContext(), "Error Loading Video!", Toast.LENGTH_SHORT).show();
                        return true;
                    }
                });

                pd.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        pd.dismiss();
                        vw.stopPlayback();
                    }
                });

            }
        });

        castVideoBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mediaRouteButton = v.findViewById(R.id.media_route_button);
                CastButtonFactory.setUpMediaRouteButton(v.getContext(), mediaRouteButton);
            }
        });
    }

    private void showIntroductoryOverlay() {
        if (mIntroductoryOverlay != null) {
            mIntroductoryOverlay.remove();
        }
        if ((mediaRouteButton != null) ) {
            new Handler().post(new Runnable() {
                @Override
                public void run() {
                    mIntroductoryOverlay = new IntroductoryOverlay.Builder(
                            MainActivity.this, mediaRouteButton)
                            .setTitleText("Introducing Cast")
                            .setSingleTime()
                            .setOnOverlayDismissedListener(
                                    new IntroductoryOverlay.OnOverlayDismissedListener() {
                                        @Override
                                        public void onOverlayDismissed() {
                                            mIntroductoryOverlay = null;
                                        }
                                    })
                            .build();
                    mIntroductoryOverlay.show();
                }
            });
        }
    }
}

CastOptionsProvider.java

package com.example.castmediaexample;

import android.content.Context;

import com.google.android.gms.cast.framework.CastOptions;
import com.google.android.gms.cast.framework.OptionsProvider;
import com.google.android.gms.cast.framework.SessionProvider;
import com.google.android.gms.cast.framework.media.CastMediaOptions;
import com.google.android.gms.cast.framework.media.NotificationOptions;

import java.util.List;

class CastOptionsProvider implements OptionsProvider {

    @Override
    public CastOptions getCastOptions(Context context) {
        return new CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .build();
    }

    @Override
    public List<SessionProvider> getAdditionalSessionProviders(Context context) {
        return null;
    }
}

ExpandControls.java

package com.example.castmediaexample;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.mediarouter.app.MediaRouteButton;

import com.google.android.gms.cast.framework.CastButtonFactory;
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity;

class ExpandControls extends ExpandedControllerActivity {

    MediaRouteButton mediaRouteButton;

    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        mediaRouteButton = findViewById(R.id.media_route_button);
        CastButtonFactory.setUpMediaRouteButton(this, mediaRouteButton);
    }
}

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.castmediaexample">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.CastMediaExample">
        <activity android:name=".MainActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <meta-data
            android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
            android:value="com.example.castmediaexample.CastOptionsProvider" />
    </application>

</manifest>

Logcat Error Message

2021-04-22 09:27:45.684 9363-9363/com.example.castmediaexample E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.castmediaexample, PID: 9363
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.castmediaexample/com.example.castmediaexample.MainActivity}: java.lang.IllegalStateException: Failed to initialize CastContext.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3792)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:246)
        at android.app.ActivityThread.main(ActivityThread.java:8506)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
     Caused by: java.lang.IllegalStateException: Failed to initialize CastContext.
        at com.google.android.gms.cast.framework.CastContext.zzc(Unknown Source:28)
        at com.google.android.gms.cast.framework.CastContext.getSharedInstance(Unknown Source:3)
        at com.example.castmediaexample.MainActivity.onCreate(MainActivity.java:66)
        at android.app.Activity.performCreate(Activity.java:8198)
        at android.app.Activity.performCreate(Activity.java:8182)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3765)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:246) 
        at android.app.ActivityThread.main(ActivityThread.java:8506) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 
     Caused by: java.lang.IllegalAccessException: java.lang.Class<com.example.castmediaexample.CastOptionsProvider> is not accessible from java.lang.Class<com.google.android.gms.cast.framework.CastContext>
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
        at com.google.android.gms.cast.framework.CastContext.zzc(Unknown Source:25)
        at com.google.android.gms.cast.framework.CastContext.getSharedInstance(Unknown Source:3) 
        at com.example.castmediaexample.MainActivity.onCreate(MainActivity.java:66) 
        at android.app.Activity.performCreate(Activity.java:8198) 
        at android.app.Activity.performCreate(Activity.java:8182) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3765) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:246) 
        at android.app.ActivityThread.main(ActivityThread.java:8506) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 

Appreciate the help everyone! Thanks!



Read more here: https://stackoverflow.com/questions/67215532/how-to-get-cast-list-and-cast-video-to-tv-from-videoview

Content Attribution

This content was originally published by lllcoderlll at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: