This is the first part of a series of posts dedicated to understanding the capabilities of TiShadow by David Bankier, and how it helps accelerate the development of Titanium applications. From the documentation:
“TiShadow provides Titanium developers the ability to deploy apps, run tests or execute code snippets live across all running iOS and Android devices.”
We can already do that without TiShadow, but what makes TiShadow so very useful is how quickly it can build and deploy to the target device(s), thus dramatically reducing the code, build, test cycle. Additionally, TiShadow provides facilities to interactively query/modify objects at runtime for interactive testing as well as run a suite of Jasmine based unit tests.
This is background information that helps explain how TiShadow operates but can be skipped if you just want to learn how to work with TiShadow (see Part 2: Getting Started with TiShadow).
TiShadow is made up of three components as depicted above; the TiShadow server, TiShadow app and the TiShadow CLI. In addition to those three components is the application bundle which runs within the TiShadow app. The application bundle running on top of the TiShadow app implements the complete mobile application while providing additional TiShadow capabilities explained below.
Let’s talk about the function of each of these in turn.
The server is implemented as a Node.js application that acts as the hub of the system and provides a well known central point for connection with one or more TiShadow CLI instances and one or more TiShadow app instances.
Commands from the CLI are conveyed over a Socket.IO connection (web socket or XHR long-polling) to the server to either be executed locally at the server or to be delivered to each server connected TiShadow app instance, depending upon the command. Most commands from the CLI to the server result in a quick task oriented response from the server and then the connection is terminated. Both the repl and the log commands initiate an ongoing connection between the CLI and server until terminated from the CLI.
TiShadow apps also connect with the server using a bi-directional Socket.IO connection. When supported, web sockets are preferred for their low over-head and real-time delivery of data in either direction. The server to TiShadow app direction conveys commands or updated application bundles, while the TiShadow app to server direction conveys mobile application logging, Jasmine test results, status and command responses.
The server implements a partitioning scheme called rooms to allow the single server instance to be shared by multiple distinct application development sessions at both the TiShadow app and TiShadow CLI end points. Multiple developers can use the single server for each of their development sessions and/or a single developer can use the single server for multiple mutually exclusive sessions.
The TiShadow server also provides versioned application caching for each of the rooms. Because of this, the deployment of application bundles to the server and subsequent push to connected TiShadow apps can be decoupled. In a common scenario, one would run the application from the CLI which would deploy the application bundle to the server and immediately push to connected TiShadow apps. In another scenario, a TiShadow appified app (to be discussed later) connects to the server and if a newer version of the application bundle is cached on the server than the one present in the appified app, then the the new bundle is pushed to the TiShadow app to update it to the most current version.
The server also presents a web based interface for submitting code snippets to be sent immediately to connected TiShadow apps and a logger display for viewing log messages from the connected TiShadows apps. This is essentially the same functions available from the CLI repl command to be discussed in another post.
The TiShadow app is a Titanium application which runs on the target mobile device(s) and acts as a runtime for executing the application bundles that are sent to it. Because an application bundle may require arbitrary permissions for the code being executed, the TiShadow app itself requests all permissions through the mobile OS to prepare for that possibility.
The TiShadow app includes all of the base Titanium API functions necessary for the application bundle to function and additionally embeds the Jasmine runtime to enable BDD unit testing. It is necessary to extend the TiShadow app with any additional native modules that are required to execute the intended application bundles, and the process for doing so is the well known process for extending Titanium applications with native modules.
It is essentially a requirement to build and deploy a custom version of the TiShadow app due to the need to extend it with native plugins, the fact that the one available for Android in the Google Play store is very outdated and it is not available at all for iOS through the iTunes app store due to their application restrictions.
Upon startup, the TiShadow app provides a dialog requesting the necessary information for connecting with a TiShadow server, the server URL or IP address, the server’s port number and an optional room as described in the server section above. The TiShadow app uses Socket.io for implementing the bidirectional connection with the TiShadow server. It initially attempts to connect with the server using web sockets but can fall back to XHR long polling if web sockets are not supported.
Once the application bundle’s code is executing, the behavior of the application is nearly identical to the operation of the corresponding fully compiled and packaged mobile application. Some of the differences include the TiShadow app runtime catching exceptions and application logging for delivery to the TiShadow server and the exposure of runtime hooks for executing code snippets, Jasmine based tests and object inspection/modifications sent via the TiShadow server. These will be discussed in further detail in a later post.
A variant to the basic TiShadow app is the TiShadow appified app. This is essentially the basic TiShadow app with the addition of a bootstrap application bundle and embedded meta-data for connecting with a prescribed TiShadow server. Upon startup the stored application bundle is automatically executed and a connection is made with the the prescribed TiShadow server. If the server is running in managed versions mode, a newer version of the application bundle will automatically be sent to the TiShadow appified app to update it.
The TiShadow CLI, also implemented with Node.js, is the multi-function control point for TiShadow. Each command begins with tishadow followed by a sub-command and then required or optional parameters. The CLI is used to:
- launch a TiShadow server
- configure the TiShadow server to be connect to for other commands
- create a new skeletal TiShadow application
- compile the titanium application into an application bundle
- deploy an application bundle to a TiShadow server
- run a deployed application bundle on connected TiShadow apps
- create an appified TiShadow application
- provide a REPL for dynamically interacting with the TiShadow server and the connected TiShadow apps
- execute Jasmine based tests on connected TiShadow apps
- tail the TiShadow app logging
Because the application bundle is extracted to the Application Data Directory, rather than the standard application and resource directories, it is necessary for the TiShadow compilation process to rewrite certain paths in the code so they are accessed properly running within the TiShadow app runtime.
In this post we covered the essential aspects of the TiShadow architecture from the developer’s perspective. In the next post we will get started using TiShadow for some basic TiShadow tasks. Future posts will include more advanced tasks including running the TiShadow server on a hosted service and Jasmine based testing.
- TiShadow blog series: Part I, Part 2, Part 3
- TiShadow on GitHub: https://github.com/dbankier/TiShadow
- TiShadow website: http://tishadow.yydigital.com
- ticaster hosted service: https://www.ticaster.io