Titanium JIRA Archive
Alloy (ALOY)

[ALOY-1118] Allow theming of tiapp.xml e.g. through Alloy themes

GitHub Issuen/a
TypeNew Feature
ResolutionWon't Fix
Resolution Date2015-02-04T14:39:51.000+0000
Affected Version/sn/a
Fix Version/sAlloy 1.7.0
Labelsthemes, tiapp.xml
ReporterFokke Zandbergen
AssigneeTim Poulsen


Now Alloy supports theming of app/config.json and i18n and platforms on their way, the last thing to tackle for easily building branded apps of a white label codebase is "theming" tiapp.xml. This might me the most challenging one, since I guess the CLI already reads some information from tiapp.xml before the first hook that Alloy uses is triggered. Also, it will require some serious smarts to know when to overwrite and when to append XML tags and attributes.


  1. Mauro Parra-Miranda 2014-08-26

    Thanks for your report [~fokke]! [~tlukasavage]: can you please set [~fokke] as the reporter? The system still switches it to mover.
  2. Tim Poulsen 2015-01-27

    This should be easily possible through the use of an Alloy JMK file. First-attempt resolution of this ticket should be the creation of a demonstration project using a JMK file to "theme" the tiapp.xml. Values to be changed per theme could be appid, guid, android map keys, and custom properties. (Incidentally, a grunt or gulp script could also easily accomplish the sorts of tiapp.xml customizations requested. As would https://github.com/jasonkneen/tich)
  3. Tim Poulsen 2015-02-03

    After playing with this for a bit, I've determined that neither the Alloy JMK or CLI hook is the solution to this. Alloy JMK files hook into the build process too late. By the time they run, the CLI has read and cached the tiapp.xml. Swapping out the file at that point has no effect on the resulting build process. The CLI hooks don't have access to the necessary Alloy configuration information. (Such as the active theme.) While I could probably create a hook that reads in the config.json file, parses it, determines the theme, environment, etc. I think the resulting script would be a bit fragile. A reasonably simple solution is to use a grunt script.

    Step 1: Install grunt-cli

    npm install -g grunt-cli

    Step 2: In your project's directory, create a package.json file with contents like this:

         "name": "YourAppName",
         "version": "1.0.0",
         "devDependencies": {
           "grunt": "~0.4.5"

    Step 3: In your project's directory, run:

    npm install

    Step 4: Create a file named Gruntfile.js in your project's directory. Copy the code below into it.

    Step 5: Use the grunt script:

    First, put a copy of tiapp.xml into the app/themes/yourtheme folder and customize that copy as necessary. Then: {noformat} > grunt theme:active_theme_name // to swap in the theme's tiapp.xml > ti build -p ios ... // as needed to build your app > grunt reset // to restore the original tiapp.xml {noformat} An exercise left to the reader is to implement the grunt-titanium plug-in to automate the building of the app.
       var fs = require('fs'),
         path = require('path');
       module.exports = function(grunt) {
         grunt.registerTask('theme', 'Swaps in a theme tiapp.xml', function(arg1) {
           if (arguments.length === 0) {
             grunt.log.writeln("You must pass the name of the theme in the form:");
             grunt.log.writeln("   grunt theme:foo")
           } else {
             grunt.log.writeln("Applying theme " + arg1);
             var projectDir = path.resolve('.');
             var themedir = path.join(projectDir, 'app', 'themes', arg1);
             if(fs.existsSync(path.join(themedir, 'tiapp.xml'))) {
               // And the active theme has a tiapp.xml, so we'll back up the original
               // and copy the theme's tiapp.xml over the original
               var tiappxml = path.join(projectDir, 'tiapp.xml');
               var origTiappxml = path.join(projectDir, 'tiapp_original.xml');
               if(!fs.existsSync(origTiappxml)) {
                 // don't re-back up the original
                 fs.renameSync(tiappxml, origTiappxml);
               fs.writeFileSync(tiappxml, fs.readFileSync(path.join(themedir, 'tiapp.xml')));
         grunt.registerTask('reset', 'Resets the original tiapp.xml', function() {
           grunt.log.writeln("Restoring original tiapp.xml");
           var projectDir = path.resolve('.');
           // remove themed tiapp.xml
           fs.unlinkSync(path.join(projectDir, 'tiapp.xml'));
           // rename the backup
           fs.renameSync(path.join(projectDir, 'tiapp_original.xml'), path.join(projectDir, 'tiapp.xml'))
         grunt.registerTask('default', ['theme']);
  4. Fokke Zandbergen 2015-02-04

    [~skypanther] As I wrote in the original ticket description, I was expecting this to be a chicken-egg problem already and I agree it should be handled via Grunt or alike. Instead of your solution to replace the tiapp.xml I would rather read the theme's config.json and then use Tony's tiapp.xml module to make specific changes, but that's just details. It might be a good subject for a blog post.
  5. Tim Poulsen 2015-02-04

    Resolving as Won't Fix because we'll resolve this through a blog post describing how to use a build automation tool to accomplish the goal.

JSON Source