I have been trying to add google-cast to my Android app that plays videos using Exoplayer. The app has one single activity withTheme.Leanback
theme and the same UI is used for both Phones and Android TV.
To add casting support on phones, I have modified in the player view and I added the cast button as below:
<androidx.mediarouter.app.MediaRouteButton
android:id="@+id/media_route_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:scaleY="0.8"
android:scaleX="0.8"
android:background="@android:color/transparent"
android:mediaRouteTypes="user"
android:visibility="visible" />
When I run the application I get the following error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.EXAMPLE.PACKAGE, PID: 10661
android.view.InflateException: Binary XML file line #76 in com.EXAMPLE.PACKAGE:layout/activity_player: Binary XML file line #76 in com.EXAMPLE.PACKAGE:layout/activity_player: Error inflating class androidx.mediarouter.app.MediaRouteButton
Caused by: android.view.InflateException: Binary XML file line #76 in com.EXAMPLE.PACKAGE:layout/activity_player: Error inflating class androidx.mediarouter.app.MediaRouteButton
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:852)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1124)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1124)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1124)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at com.EXAMPLE.PACKAGE.fragment.PlayerFragment.onCreateView(PlayerFragment.java:162)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.IllegalArgumentException: background can not be translucent: #0
at androidx.core.graphics.ColorUtils.calculateContrast(ColorUtils.java:161)
at androidx.mediarouter.app.MediaRouterThemeHelper.getControllerColor(MediaRouterThemeHelper.java:177)
at androidx.mediarouter.app.MediaRouterThemeHelper.getRouterThemeId(MediaRouterThemeHelper.java:313)
at androidx.mediarouter.app.MediaRouterThemeHelper.createThemedButtonContext(MediaRouterThemeHelper.java:107)
at androidx.mediarouter.app.MediaRouteButton.<init>(MediaRouteButton.java:153)
at androidx.mediarouter.app.MediaRouteButton.<init>(MediaRouteButton.java:149)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:852)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1124)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1124)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1124)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at com.EXAMPLE.PACKAGE.fragment.PlayerFragment.onCreateView(PlayerFragment.java:162)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I have tried setting the background of the castbusston transparent as was suggested in few places online but that did not help.
I can have several other Image Button and Text Buttons that are working fine.
I tried using <MediaRouteButton
instead of <androidx.mediarouter.app.MediaRouteButton
. This way the button will be showed and greyed out in the player layout however, when I try to intitize the cast context as below:
mMediaRouteButton = (MediaRouteButton) mView.findViewById(R.id.media_route_button);
CastButtonFactory.setUpMediaRouteButton(mContext, mMediaRouteButton);
mCastContext = CastContext.getSharedInstance(mContext);
I get the following error:
java.lang.ClassCastException: android.app.MediaRouteButton cannot be cast to androidx.mediarouter.app.MediaRouteButton
I have been puzzled by this issue for couple of days. Thank you very much in advance for your kind comments and suggestion.
The issue was that the primaryColor
of the app theme that I was using had transparency channel, ie, #3d000000
. However MediaRouteButton that is taking the primaryColor
of theme needs a color without transparency channel such as #000000
. So I resolved the issue as follow:
<style name="AppTheme" parent="@style/Theme.Leanback">
<!-- Primary Color -->
<item name="colorPrimary">@color/defaultColor</item>
</style>
where I defined <color name="defaultColor">#000000</color>
Later on I encountered another issue that MediaCastButton can only be used with AppCompat
decedent theme. The solution for me was to change the app theme to an Theme.AppCompat.Light.NoActionBar
theme and modify it to look like Theme.Leanback
as below:
<style name="AppTheme1" parent="@style/Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/blackColor</item>
<item name="android:windowBackground">@color/blackColor</item>
<!-- <item name="mediaRouteButtonTint">@color/whiteColor</item>-->
<item name="baseCardViewStyle">@style/Widget.Leanback.BaseCardViewStyle</item>
<item name="imageCardViewStyle">@style/Widget.Leanback.ImageCardViewStyle</item>
<item name="imageCardViewImageStyle">@style/Widget.Leanback.ImageCardView.ImageStyle</item>
<item name="imageCardViewTitleStyle">@style/Widget.Leanback.ImageCardView.TitleStyle</item>
<item name="imageCardViewContentStyle">@style/Widget.Leanback.ImageCardView.ContentStyle</item>
<item name="imageCardViewBadgeStyle">@style/Widget.Leanback.ImageCardView.BadgeStyle</item>
<item name="imageCardViewInfoAreaStyle">@style/Widget.Leanback.ImageCardView.InfoAreaStyle</item>
<item name="browsePaddingStart">@dimen/lb_browse_padding_start</item>
<item name="browsePaddingEnd">@dimen/lb_browse_padding_end</item>
<item name="browsePaddingTop">@dimen/lb_browse_padding_top</item>
<item name="browsePaddingBottom">@dimen/lb_browse_padding_bottom</item>
<item name="browseRowsMarginStart">@dimen/lb_browse_rows_margin_start</item>
<item name="browseRowsMarginTop">@dimen/lb_browse_rows_margin_top</item>
<item name="browseRowsFadingEdgeLength">@dimen/lb_browse_rows_fading_edge</item>
<!-- <item name="headersVerticalGridStyle">@style/Widget.Leanback.Headers.VerticalGridView</item>-->
<!-- <item name="headerStyle">@style/Widget.Leanback.Header</item>-->
<!-- <item name="sectionHeaderStyle">@style/Widget.Leanback.Header.Section</item>-->
<item name="rowsVerticalGridStyle">@style/Widget.Leanback.Rows.VerticalGridView</item>
<item name="rowHorizontalGridStyle">@style/Widget.Leanback.Row.HorizontalGridView</item>
<item name="itemsVerticalGridStyle">@style/Widget.Leanback.GridItems.VerticalGridView</item>
<item name="browseTitleViewLayout">@layout/lb_browse_title</item>
<item name="browseTitleTextStyle">@style/Widget.Leanback.Title.Text</item>
<item name="browseTitleIconStyle">@style/Widget.Leanback.Title.Icon</item>
<item name="browseTitleViewStyle">@style/Widget.Leanback.TitleView</item>
<item name="rowHeaderStyle">@style/Widget.Leanback.Row.Header</item>
<item name="rowHeaderDescriptionStyle">@style/Widget.Leanback.Row.Header.Description</item>
<item name="rowHoverCardTitleStyle">@style/Widget.Leanback.Row.HoverCardTitle</item>
<item name="rowHoverCardDescriptionStyle">@style/Widget.Leanback.Row.HoverCardDescription</item>
<item name="rowHeaderDockStyle">@style/Widget.Leanback.Row.HeaderDock</item>
<!-- <item name="searchOrbViewStyle">@style/Widget.Leanback.SearchOrbViewStyle</item>-->
<item name="detailsDescriptionTitleStyle">@style/Widget.Leanback.DetailsDescriptionTitleStyle</item>
<item name="detailsDescriptionSubtitleStyle">@style/Widget.Leanback.DetailsDescriptionSubtitleStyle</item>
<item name="detailsDescriptionBodyStyle">@style/Widget.Leanback.DetailsDescriptionBodyStyle</item>
<item name="detailsActionButtonStyle">@style/Widget.Leanback.DetailsActionButtonStyle</item>
<!-- Attributes used for styling of a playback -->
<item name="playbackPaddingStart">@dimen/lb_playback_controls_margin_start</item>
<item name="playbackPaddingEnd">@dimen/lb_playback_controls_margin_end</item>
<item name="playbackMediaItemPaddingStart">@dimen/lb_playback_media_row_horizontal_padding</item>
<item name="playbackMediaListHeaderStyle">@style/Widget.Leanback.PlaybackMediaListHeaderStyle</item>
<item name="playbackMediaItemRowStyle">@style/Widget.Leanback.PlaybackMediaItemRowStyle</item>
<item name="playbackMediaItemSeparatorStyle">@style/Widget.Leanback.PlaybackMediaItemSeparatorStyle</item>
<item name="playbackMediaListHeaderTitleStyle">@style/Widget.Leanback.PlaybackMediaListHeaderTitleStyle</item>
<item name="playbackMediaItemDetailsStyle">@style/Widget.Leanback.PlaybackMediaItemDetailsStyle</item>
<item name="playbackMediaItemNumberViewFlipperStyle">@style/Widget.Leanback.PlaybackMediaItemNumberViewFlipperStyle</item>
<item name="playbackMediaItemNumberViewFlipperLayout">@layout/lb_media_item_number_view_flipper</item>
<item name="playbackMediaItemNumberStyle">@style/Widget.Leanback.PlaybackMediaItemNumberStyle</item>
<item name="playbackMediaItemNameStyle">@style/Widget.Leanback.PlaybackMediaItemNameStyle</item>
<item name="playbackMediaItemDurationStyle">@style/Widget.Leanback.PlaybackMediaItemDurationStyle</item>
<item name="playbackControlsButtonStyle">@style/Widget.Leanback.PlaybackControlsButtonStyle</item>
<item name="playbackControlButtonLabelStyle">@style/Widget.Leanback.PlaybackControlLabelStyle</item>
<item name="playbackControlsTimeStyle">@style/Widget.Leanback.PlaybackControlsTimeStyle</item>
<item name="playbackControlsActionIcons">@style/Widget.Leanback.PlaybackControlsActionIconsStyle</item>
<item name="playbackControlsAutoHideTimeout">@integer/lb_playback_controls_show_time_ms</item>
<item name="playbackControlsAutoHideTickleTimeout">@integer/lb_playback_controls_tickle_timeout_ms</item>
<item name="errorMessageStyle">@style/Widget.Leanback.ErrorMessageStyle</item>
<item name="defaultSearchColor">@color/lb_default_search_color</item>
<item name="defaultSearchIconColor">@color/lb_default_search_icon_color</item>
<item name="defaultSearchBrightColor">?attr/defaultSearchColor</item>
<item name="defaultSearchIcon">@drawable/lb_ic_in_app_search</item>
<item name="defaultSectionHeaderColor">?attr/defaultSearchColor</item>
<item name="overlayDimMaskColor">@color/lb_view_dim_mask_color</item>
<item name="overlayDimActiveLevel">@fraction/lb_view_active_level</item>
<item name="overlayDimDimmedLevel">@fraction/lb_view_dimmed_level</item>
</style>