A brief introduction to Toro

27 August 2018

0. Toro, since then

So, in previous blog post (which is 1 year ago :surprised:), I had a quick introduction for Toro 3, which was still in beta. And in that post, I also promised some later posts regarding how to do what and why, etc. All of those promises are not fulfilled yet ... And today, 1 year since the library out of beta, I would like to make it.

1. Toro, the version name

Toro, by default, doesn't vow to be dedicated to any 3rd party library. But it comes with an extension that support ExoPlayer out of the box. ExoPlayer, in its nature, doesn't guarantee to be 'backward compatible' in new release.

Though, it is important for me to always support latest feature/patches/bug fixes, but still keep your App works well with a certain dependency version. So, from 3.6.0, I add the 4th part to its version name, which indicates the version of ExoPlayer it supports. So from now on, you may expect to have,, and so on. It may be complicated at first, but I will always try to publish new release to support latest ExoPlayer available release (at the time I publish it), and consider to support lower version of ExoPlayer if there is request from developers.

2. 'What else?'

This is the main part of the introduction, which I plan to be in more than one posts. In this post, I will go through some why and what about this update. And in upcoming posts, I will fulfill my promise to talk about why and how to create a specific UX using Toro and its extensions.

3. What's new in Toro

Let's go one by one following the CHANGELOG.md

3.1 Supported ExoPlayer version now included in version name

Why: please go back to '1. Toro, the version name' for the answer.

3.2 Container' savePlaybackInfo() accepts Nullable PlaybackInfo

Why: There are reports about NPE in this method. In fact, this method is accessible from public, so it is error prone itself. But hiding it will break the compatibility. In my debug, the NPE never happended, but somehow it happened. To make it easier to control, I allow Nullable parameters being passed to it, the method will just ignore the Null value and do nothing instead.

3.3 ToroExo Config no longer uses array of DrmSessionManager

The history of this class Config is to help Toro to cache a pool of ExoPlayer instances those share the same configurations. One of the configuration is the DrmSessionManager. Also, I would like to be honest about that I'm not fully understand this class, and just merely adopt from ExoPlayer demo app. And it is even worse when I try to support multiple DrmSessionManager using as least resource as possible. This produces the array of DrmSessionManager in the Config.

From, I remove this option and just use a single DrmSessionManager. I will investigate more time learning about this, and have more elegant support in the future.

3.4 ToroExo' createDrmSessionManager() no longer requires Handler

3.5 New ToroPlayer.OnErrorListener

Toro and its components lack of this interface for quite a long time. So here it is. Client can set it from Playable, ToroPlayerHelper and variants.

3.6 ToroControlView: a custom UI to support volume control

One of the most common request to Toro is the ability to control a playback's volume. I take this request quite seriously, and thought about many scenarios where it can be used. Toro has already supported this via Playable#setVolumeInfo(VolumeInfo) and its callback ToroPlayer.OnVolumeChangeListener. ToroControlView, on the other hand, is an extension of PlayerControlView plus the Volume button. This button allows user to [1] Mute/UnMute and [2] Drag to change the volume.

With the release of ToroControlView, Toro gives a better way to interact with playback volume from the View. To use this, client just simply use normal PlayerView, and apply @layout/toro_exo_player_view as its player_layout_id. This is a custom layout that uses ToroControlView internally.

3.7 PressablePlayerSelector beta

This class is a PlayerSelector and an View.OnLongClickListener at the same time. Using this with Container allows client to implement the following scenario: Regardless of how the playback is going, when User press to a PlayerView (long click), that PlayerView will be set to higher priority in Player candidates. Once scrolled, it that player will be selected for playback.

3.8 ExoPlayerDispatcher beta

This class is a ControlDispatcher of ExoPlayer's PlayerControlView. Use this with PlayerView will allow user to control the playback using the UI. ExoPlayerDispatcher internally use a PressablePlayerSelector to connect to the Container to correctly update the playback position.

3.9 AdsExoPlayerViewHelper and AdsPlayable (beta)

Developers who use Toro may be familiar with ExoPlayerViewHelper and ExoPlayable. They wraps necessary implementation of ExoPlayer and ToroPlayer to allow easy integration of Toro into the App. These newly introduced classes are their extensions, allow the App to also work with Ads. This update internally uses ExoPlayer extension for IMA, therefore one should be aware of this.

3.10 New demo: demo-ads

In this update, I also aware of that mopub for Android SDK also updates to use ExoPlayer 2.8.2 internally. It is not that I officially support mopub, but it is important to support mostly used Ads SDK. So in this update, I also add new demo app: demo-ads. This app shows simple use case that integrate Toro with well-known Ads SDK like mopub and IMA.

4. In next articles

In this post, I quickly summary latest update of Toro library, with the why and what. In next articles, I would like to go in detail about how to implement a specific scenario. Hope it will fix more and more problem with media playback once may have.

Happy coding!