The other day, Russian users who ordered the Apple TV console on the official website, finally began to receive long-awaited devices.
As you know, in the new generation of consoles debuts the App Store with third-party applications. The first Russian reviews with sadness noted that there
are not so many applications in the domestic market
yet (and this must somehow be corrected!) . However, among them is the Rutube app. In this article we will share a little experience that
igor-petrov and
Juraldinio managed to acquire during its development.
About tvOS platform
The new Apple TV (tvOS) platform is a derivative of iOS and has some unique features. In particular, it is possible for tvOS to port an existing iOS application written in Objective-C / Swift (according to the
recommendations for interface implementation ), and to create an application on a new technology stack - TVML and TVJS, connected using the TVMLKit framework. This new stack is positioned as a good choice for simple and fast development of client-server applications
(ideally for video!) , Which is confirmed in practice. It is about TVML and TVJS that will be discussed below.
TVMLKit
TVMLKit is a framework for Objective-C / Swift. Using it, control of the application is transferred to the JavaScript file and the TVML + TVJS environment. Details are available on the
TVMLKit documentation page .
')
TVML
TVML (Television Markup Language) is a subset of XML that implements tvOS markup and standard interface elements. This interface is used not only for applications - it implements all tvOS pages: home screen, settings screen, and the App Store itself.
For example, the TVML button looks like this:
<button> <text>Hello world!</text> </button>
And so the button looks on the screen:

And this is the device’s home screen, which consists of TVML elements:

tvOS provides a set of ready-made elements, a full list of which is available in
the TVML documentation .
These elements are divided into:
- Simple elements are simple elements consisting of a single tag, for example, text or title;
- Compound elements are composite elements that may include simple elements. For example, the banner element may contain a simple title element;
- Templates - page display templates. Set the overall structure of the display elements and may include composite elements.
In addition, elements can be given attributes and styles, such as
width and
src .
At the same time there are limitations - certain types of constituent elements can contain only certain types of simple elements, the same applies to templates. In general, the structure of the elements seemed rather confusing - each time I had to look in the directory to understand where which element could be used.
From the general list of templates,
divTemplate is worth highlighting, which allows you to construct your own layout, if you are not satisfied with any other proposed one.
There is no opportunity to create your own elements, you can only combine existing ones.
Moreover, you need to make sure that when parsing the lines in the XML, an invalid TVML does not come across.
For example, the response of our API could contain HTML tags, which caused an error.TVML markup can be dynamically added to a page using JavaScript and TVJS.
Tvjs
TVJS is a JavaScript framework that provides an API for working with TVML. Conventionally, it can be divided into two parts:
- Standard DOM Level 3 API for working with DOM elements, for example, the DOMParser constructor for parsing a string into an XML document (TVML);
- Native tvOS methods and constructors, for example, a NavigationDocument object that manages a stack of rendered pages and is used as a navigation through history.
Each of its own methods is described in
the TVJS documentation . The rest is the usual JavaScript. ECMAScript 2015 is partially supported, for example, classes and template strings.
Arrow functions, constants are not supported. In this case, some third-party libraries may be inoperable. For example, I had to search several npm packages to find a working library for AJAX requests
(due to calls to window.XMLHttpRequest, which in tvOS is not implemented as a window property) . Of course, it would be easier to write a few lines of code on your own, but at some point it became a matter of principle - to find a plug-in working from the box, and it exists!
Debugging
You can use Safari to debug JavaScript code. Activate the menu "Develop" (
Preferences -> Advanced -> Show Develop menu ), connect the Apple TV via USB. Go to the browser and, running the application on the console, select the “Apple TV” device in the drop-down menu “Develop”, and then select our application.
Hello world and the launch of the video
Further a small example of how the application for tvOS can look.
First you need to implement the loading of a JavaScript file. The task is to create an object of the TVApplicationController class, providing an interface for using TVML:
Show code func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // window window = UIWindow(frame: UIScreen.mainScreen().bounds) // , TVApplicationController let appContollerContext = TVApplicationControllerContext() #if DEBUG // let tvBaseUrl = "http://192.168.xx.xx/" let tvBootUrl = "\(tvBaseUrl)js/main.js" guard let javaScriptUrl = NSURL(string: tvBootUrl) else { fatalError("Unable create js application url") } // js-, appContollerContext.javaScriptApplicationURL = javaScriptUrl // , BASE appContollerContext.launchOptions["BASEURL"] = tvBaseUrl; #else // js- bundle appContollerContext.javaScriptApplicationURL = NSBundle.mainBundle().URLForResource("application", withExtension:"js")! #endif // js- appController = TVApplicationController(context:appContollerContext, window: window, delegate: self) return true }
After management passed to a JavaScript file, it is possible to start implementation of logic. Content main.js:
App.onLaunch = function (options) { console.log('Hello World!'); }
This demonstrates the TVJS App method. onLauch is the entry point of the application.
Let's try to do something more complicated:
App.onLaunch = function () { var alertString, alertXML, parser;
This example demonstrates the DOMParser constructor, with which the string is converted to an XML document.
Using the TVJS method of
navigationDocument.pushDocument () , you can display the resulting document on the page. At the same time, the new page will be written into the
navigationDocument.documents array, which can be used to navigate the history. In this case, when you start the application, the page will contain the inscription “Hello world” and the “OK” button.
Before inserting an XML document, you can add a custom event handler to the page:
...
In the resulting example, the user-select event is hung on the element of the XML document — a button — and a video player is created and launched in the callback using the TVJS methods. Now when you click on the "OK" button, the video playback will start.
Sample code entirely App.onLaunch = function () { var alertString, alertXML, parser;
Of course, this is a very simple example, but it fully reflects the general principle of working with TVML and TVJS and shows that this solution is not some
Wonderful Beast , but a technology close to the classic frontend.
Finally
In conclusion, a few words about how the Rutube application is currently implemented.
The code is written in CoffeeScript, Browserify is used as a modular loader. XMLHttpRequest and the open-source Rutube API are used to retrieve data. For video delivery, the HLS protocol is used.
Admire the main screen of the application In general, development on TVML and TVJS was pleasant - quickly and efficiently. Although the application is created in a standardized interface, this interface looks very impressive. At the same time, time is saved on layout and creation of visual effects, and there is no need to think about their performance.
Of the minuses I would like to note the limitations in design. Well, the implementation of the search (text input) seemed ambiguous.
We do not even know whether to add it to the app without Siri?The application has been written in a few days, but if you are inspired and start developing your own, put some time into the evaluation of unfamiliar APIs.
In the future, a
plug-in for React is expected to be released, which so far (November 2015) is in the status “very alpha”
In the meantime, it should be noted that over the past week since the release, without straining, “over a cup of tea”, we added to our application a certain amount of nice-looking gadgets and are preparing an update.
useful links
TVMLKit DocumentationTVJS DocumentationTVML documentationBeginning tvOS Development with TVML Tutorial