B4A Library Casty - Cast Videos to Google Cast Devices (Chromecast)

This is a wrap for this Github project. I started doing the wrap back in 2017 but did not got it working. A few tries later i now got it working ;-)

Casty
Author:
DonManfred
Version: 1.0

  • Class representing local media metadata.
    • Fields:
      • KEY_CONTENT_TYPE As String
      • KEY_IMAGES As String
      • KEY_STUDIO As String
      • KEY_SUBTITLE As String
      • KEY_TITLE As String
      • KEY_URL As String
    • Functions:
      • addImage (url As String)
      • fromBundle (wrapper As android.os.Bundle) As de.donmanfred.MediaItem
      • getImage (index As Int) As String
      • hasImage As Boolean
      • toBundle As android.os.Bundle
    • Properties:
      • ContentType As String
      • Duration As Int
      • Images As java.util.ArrayList [read only]
      • Studio As String
      • SubTitle As String
      • Title As String
      • Url As String
  • CastSession
    Class representing local media metadata.
    • Functions:
      • CastSessionWrapper (session As com.google.android.gms.cast.framework.Session)
      • Initialize (session As com.google.android.gms.cast.framework.Session)
      • IsInitialized As Boolean
    • Properties:
      • Category As String [read only]
      • Connected As Boolean [read only]
      • Connecting As Boolean [read only]
      • Disconnected As Boolean [read only]
      • Disconnecting As Boolean [read only]
      • Resuming As Boolean [read only]
      • SessionId As String [read only]
      • SessionRemainingTimeMs As Long [read only]
      • Suspended As Boolean [read only]
  • Casty
    • Events:
      • onCastSessionUpdated (session As Object, remoteMediaClient As Object)
      • onCastStateChanged (State As Int)
      • onConnected()
      • onDisConnected()
      • onSessionEnded (session As Object, info As Int)
      • onSessionEnding (session As Object)
      • onSessionResumed (session As Object, info As Boolean)
      • onSessionResumeFailed (session As Object, info As Int)
      • onSessionResuming (session As Object, info As String)
      • onSessionStarted (session As Object, info As String)
      • onSessionStartFailed (session As Object, info As Int)
      • onSessionStarting (session As Object)
      • onSessionSuspended (session As Object, info As Int)
    • Functions:
      • addMediaRouteMenuItem (menu As android.view.Menu)
      • addMinicontroller
      • buildMediaInfo (title As String, studio As String, subTitle As String, duration As Int, url As String, mimeType As String, imgUrl As String, bigImageUrl As String) As de.donmanfred.MediaItem
      • configure (receiverId As String)
        Sets the custom receiver ID. Should be used in the {@link Application} class.
        receiverId: the custom receiver ID, e.g. Styled Media Receiver - with custom logo and background
      • configureReceiver (receiverId As String)
      • Initialize (EventName As String)
      • loadMediaAndPlay (mediaData As pl.droidsonroids.casty.MediaData)
      • loadMediaAndPlay3 (mediaInfo As com.google.android.gms.cast.MediaInfo, autoPlay As Boolean, position As Long)
      • loadMediaAndPlayInBackground (mediaData As pl.droidsonroids.casty.MediaData)
      • loadMediaAndPlayInBackground3 (mediaInfo As com.google.android.gms.cast.MediaInfo, autoPlay As Boolean, position As Long)
      • pause
      • play
      • seek (time As Long)
      • setUpMediaRouteButton (menu As android.view.Menu, item As Int)
      • setUpMediaRouteButton2 (MediaButton As android.support.v7.app.MediaRouteButton)
      • togglePlayPause
    • Properties:
      • Buffering [read only]
      • Connected As Boolean [read only]
      • Paused [read only]
      • Player As pl.droidsonroids.casty.CastyPlayer [read only]
      • Playing [read only]
      • UpMediaRouteButton As android.support.v7.app.MediaRouteButton [write only]
  • IntroductoryOverlay
    • Events:
      • onOverlayDismissed()
    • Functions:
      • Initialize (EventName As String, item As android.view.MenuItem)
      • onPause
      • onResume
      • remove
      • setSingleTime
      • show
    • Properties:
      • ButtonText As String [write only]
      • FocusRadius As Float [write only]
      • OverlayColor As Int [write only]
      • TitleText As String [write only]
  • MediaDataBuilder
    • Functions:
      • addPhotoUrl (photoUrl As String) As MediaDataBuilder
      • build As pl.droidsonroids.casty.MediaData
      • Initialize (EventName As String, url As String) As MediaDataBuilder
      • IsInitialized As Boolean
      • setAutoPlay (autoPlay As Boolean) As MediaDataBuilder
      • setContentType (contentType As String) As MediaDataBuilder
      • setMediaType (mediaType As Int) As MediaDataBuilder
      • setPosition (position As Long) As MediaDataBuilder
      • setStreamDuration (streamDuration As Long) As MediaDataBuilder
      • setStreamType (streamType As Int) As MediaDataBuilder
      • setSubtitle (subtitle As String) As MediaDataBuilder
      • setTitle (title As String) As MediaDataBuilder
  • MediaRouteButton
    • Functions:
      • BringToFront
      • DesignerCreateView (base As Panel, lw As Label, props As Map)
      • Initialize (EventName As String, AppID As String)
      • Invalidate
      • Invalidate2 (arg0 As android.graphics.Rect)
      • Invalidate3 (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
      • IsInitialized As Boolean
      • RemoveView
      • RequestFocus As Boolean
      • SendToBack
      • SetBackgroundImage (arg0 As android.graphics.Bitmap) As BitmapDrawable
      • SetColorAnimated (arg0 As Int, arg1 As Int, arg2 As Int)
      • SetLayout (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
      • SetLayoutAnimated (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int, arg4 As Int)
      • SetVisibleAnimated (arg0 As Int, arg1 As Boolean)
    • Properties:
      • Background As android.graphics.drawable.Drawable
      • Color As Int [write only]
      • DialogFactory As android.support.v7.app.MediaRouteDialogFactory
      • Enabled As Boolean
      • Height As Int
      • Left As Int
      • Padding As Int()
      • Parent As Object [read only]
      • RemoteIndicatorDrawable As android.graphics.drawable.Drawable [write only]
      • RouteSelector As android.support.v7.media.MediaRouteSelector
      • Tag As Object
      • Top As Int
      • Visibility As Int [write only]
      • Visible As Boolean
      • Width As Int

Setup:
- Make your App AppCompat-Compatible. It is mandatory as you need to use the Appcompat Menu creation...
B4X:
Sub Activity_CreateMenu(Menu As ACMenu)
    Menu.Clear
    cast.addMediaRouteMenuItem(Menu)
    Menu.Add(2, 4, "Overflow2", Null)
    Menu.Add(3, 5, "Overflow3", Null)
End Sub
and
B4X:
#If Java
public boolean _onCreateOptionsMenu(android.view.Menu menu) {
    if (processBA.subExists("activity_createmenu")) {
        processBA.raiseEvent2(null, true, "activity_createmenu", false, new de.amberhome.objects.appcompat.ACMenuWrapper(menu));
        return true;
    }
    else
        return false;
}
#End If

- Add the following to your main module
B4X:
#Extends: android.support.v7.app.AppCompatActivity
#AdditionalJar: com.google.android.gms:play-services-cast-framework
#AdditionalJar: casty.aar

Add the following code to your Manifest
B4X:
SetApplicationAttribute(android:theme, "@style/MyAppTheme")

CreateResource(values, theme.xml,
<resources>
    <style name="MyAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">#0098FF</item>
        <item name="colorPrimaryDark">#007CF5</item>
        <item name="colorAccent">#AAAA00</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
    </style>
</resources>
)
AddApplicationText(
<meta-data android:value="" android:name="app_id"></meta-data>
)
AddApplicationText(
<activity
  android:name="pl.droidsonroids.casty.ExpandedControlsActivity"
  android:theme="@style/MyAppTheme" />
<meta-data
  android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
  android:value="de.donmanfred.CastOptionsProvider" />
<receiver android:name="com.google.android.gms.cast.framework.media.MediaIntentReceiver" />

<service android:name="com.google.android.gms.cast.framework.media.MediaNotificationService" />
<service android:name="com.google.android.gms.cast.framework.ReconnectionService" />
)
CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)

Note that the line
<meta-data android:value="" android:name="app_id"></meta-data>
can be used to define YOUR App-ID though it is not needed. If the String is an Empty string then the default Receiverapp will do the Job.

Update Jan 2020:
It is mandatory to use your own app_id which must be registered at the Google Cast Developer console.


Before you begin

There is a one-time, non-refundable $5 registration fee charged for a Google Cast Developer account. Google charge this fee to encourage higher quality applications utilizing Google Cast.



You can see the Example on how to use everything.

In short you can say that you can start Playing Videos when you successfully connected to the Cast device and a Session is opened.

B4X:
Sub Casty_onConnected()
    Log($"Casty_onConnected()"$)
    Dim mb As MediaDataBuilder
    mb.Initialize("","http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4").setAutoPlay(True).setContentType("videos/mp4").setMediaType(1).setStreamType(1).setTitle("DonManfred presents").setSubtitle("B4A Casting Video").addPhotoUrl("https://peach.blender.org/wp-content/uploads/bbb-splash.png?x11217")

    cast.loadMediaAndPlayInBackground(mb.build)
End Sub

chromecast_097.png


 

Attachments

  • CastyV1.0.zip
    60 KB · Views: 229
  • CastyEx.zip
    18.6 KB · Views: 220
  • CastyAddLibs.zip
    65.9 KB · Views: 161
Last edited:

DonManfred

Expert
Licensed User
Some more help and advice would be very much appreciated!
i only can tell that i did my tests using V9.5 for sure. I always use the latest Version.

It can be that you need to use an older SDK using V8.3 but i´m not sure. You better start a new thread in the Questionsforum about this.

Please also test with "26".
I did use targetsdk 26 in my Tests.
gives a "Casty not initialized" error is probably a clue
You did setup a Cast App in the CAST Console?

You did adapt the Manifest entry to match your appid?

B4X:
AddApplicationText(
<meta-data android:value="<your app id>" android:name="app_id"></meta-data> 
)
AddApplicationText(
<activity
  android:name="pl.droidsonroids.casty.ExpandedControlsActivity"
  android:theme="@style/MyAppTheme" />
<meta-data
  android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
  android:value="de.donmanfred.CastOptionsProvider" />
<receiver android:name="com.google.android.gms.cast.framework.media.MediaIntentReceiver" />

<service android:name="com.google.android.gms.cast.framework.media.MediaNotificationService" />
<service android:name="com.google.android.gms.cast.framework.ReconnectionService" />
)
 

Syd Wright

Well-Known Member
Licensed User
You did setup a Cast App in the CAST Console?

No I didn't. I must have overlooked this requirement. Thank you for telling me. You may want to emphasize this requirement in the first thread.
I assume it is not possible to test Casty (in a B4A Debug environment) without this? Also it costs $5.00.

You did adapt the Manifest entry to match your appid?
I used your Casty example, including the contents of the manifest file you created, without changing the Appname.
 
Last edited:

DonManfred

Expert
Licensed User
To add:


There is a one-time, non-refundable $5 registration fee charged for a Google Cast Developer account. We charge this fee to encourage higher quality applications utilizing Google Cast.
 

Syd Wright

Well-Known Member
Licensed User
To add:

Thank you. I have the feeling that so far I am the only one who is trying to use Casty, otherwise the things I keep running into would have already been spotted by others. I find this rather amazing because using a Chromecast is a very popular issue. I have noticed before that I seem to be doing other things than the majority of B4A members. I am not into games, so maybe that is my problem... I am also hoping that once I get Casty working that it will be possible to play radio streams (and maybe also TV streams) via the Chomecast, i.e. to make a complete Chromecast Media Center.
 

DonManfred

Expert
Licensed User
I have the feeling that so far I am the only one who is trying to use Casty
could be
I am also hoping that once I get Casty working that it will be possible to play radio streams (and maybe also TV streams) via the Chomecast, i.e. to make a complete Chromecast Media Center.
I don´t know whether it works playing ANY online stream. The example is using the MediaDataBuilder to setup an Online video and Snapshot
B4X:
    Dim mb As MediaDataBuilder
    mb.Initialize("","http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4").setAutoPlay(True).setContentType("videos(mp4").setMediaType(1).setStreamType(1).setTitle("DonManfred presents").setSubtitle("B4A Casting Video").addPhotoUrl("https://peach.blender.org/wp-content/uploads/bbb-splash.png?x11217")

I don´t know it that works with Radiostreams. You probably need to find out yourself
 
Top