Tutorial: Creating an HTML5 App from a Native Apple iOS* Project with the Intel® HTML5 App Porter Tool – BETA


NOTICE: The current BETA program ended on Dec 31th, 2013. The Intel® HTML5 App Porter Tool - BETA is no longer available.

(Version: 0.5.4216.90)

Legal Information

Please, download the tutorial sample app before starting this tutorial.

Download Sample App

Introduction

This tutorial helps you use the Intel® HTML5 App Porter Tool – BETA to port a native Apple iOS* app to HTML5. The Intel® HTML5 App Porter Tool – BETA will generate clean and easy-to-read code, keeping the auto-generated code as much like the original code as possible.

Objectives

Use this tutorial to:

  • Learn how to configure the tool to get the best results possible
  • Understand the feedback provided by the tool
  • Learn how to finish the translation process by completing the portions of code that could not be translated by the tool

Tutorial Example - “Balloon Ninja”

Balloon Ninja is a mini game where you get points by popping balloons. The more balloons you pop in a minute, the more points you get. The original Balloon Ninja iOS app uses JSONKit as a third-party API for persistence. It also uses Apple NSFoundation, UIKit framework, and Audio Toolbox as native APIs. For this tutorial app, the Intel® HTML5 App Porter Tool – BETA converts about 80% of the native APIs, because most common features in NSFoundation and UIKit are supported.

See a screenshot of the original application running in the iOS* simulator, below.

From Apple iOS* to HTML5 in just 6 steps

This section shows the different steps that you need to follow to successfully run the Intel® HTML5 App Porter Tool – BETA and finish the porting process to get a converted (translated) HTML5 version of this sample app.

Step 1 - Setting the project and output paths

Select the project to translate, in this case Balloon Ninja, and the destination path. For the source path, select the .xcodeproj folder, otherwise you will get an error message saying “This is not a valid Xcode* Project”. Please, make sure that you have write permissions for both the source and destination folders.

Step 2 - Selecting the modules to be processed

In this step, uncheck the JSONKit.m file to exclude it from the translation process. Because JavaScript* has native support with JSON, the best approach is not to translate that library, but to rewrite the JSON management using JavaScript.

Note: Carefully selecting the classes to translate is a key step. As a general criteria, avoid translating any modules in the original app that implement functionality that is already supported in JavaScript. Additionally, avoid translating modules that are implemented using low-level features of C or Apple Objective-C* that may be translated to JavaScript rather unnaturally.

In this case, uncheck the JSONKit/JSONKit.m line below because it uses C low-level features that are not fully supported.

The checkbox on the bottom of this screen lets you add missing include folders or preprocessor directives, if necessary.

In this case, no additional configuration is necessary since the JSONKit sources are already included as a part of the project. However, if the parsing process fails, this is where you should add any API or framework headers that are not included on the project. These errors could be caused by a third party library outside the project folder or a missing preprocessor directive, such as preprocessor definitions for DEBUG or RELEASE, or any #define that should be set manually.

Step 3 - Parsing modules

During this step, Intel® HTML5 App Porter Tool – BETA attempts to parse the project and determines the part of the code that can be translated. If the tool is unable to parse a file, it will allow you to fix issues by editing the files that could not be parsed, as shown in the images below. Otherwise, you can choose to ignore (skip) the files that cannot be parsed. After editing or ignoring those files, you can continue to Step 4. In case you encounter no parsing issues, you will see the sequence of screens below.

Step 4 - Select the methods to be translated

Finally, after parsing and analyzing the entire project, the result is shown in a simple report. You can decide which methods to convert based on the API Coverage shown in the columns on the right.

Uncheck the interface LeaderboardManager because the JSON serialization will be re-done directly in JavaScript.

After you click Next, the following screen will appear. Please, wait until all API calls have been processed.

Additionally, in the following screen, you can choose whether to generate an Intel® XDK zip bundle, or a Microsoft Visual Studio* 2012 project file. By default, both are generated.

Step 5 - Reading the results

After the translation completes, carefully read the "Translation Report" and the "TODO Report" available on the final screen, or in the TranslationReports folder of the translated application:

  • The Translation Report shows some details of the translation itself, such as the mapping between .m and .js files.
  • The TODO Report provides the list of files that represent the template declarations for the APIs that were not mapped to equivalent HTML5 code.

Use these reports to help you complete porting your original app and create a working version of your HTML5 app.

Step 6 - Connecting the missing dots

The automatic translation phase performed by the tool is over. Now, you should complete the porting of those APIs and features that were not supported by the tool. Select Open Project Folder to open the folder where the translated application code is located. There, you can either follow the instructions in intel_xdk_package\upload_instructions.txt file to import the translated code into Intel® XDK, or navigate to the src folder and click over the .jsproj file to open the translated HTML5 code in Microsoft Visual Studio* (if available).

Once you open the translated code, you should be able to edit the JavaScript files. If you look inside each ToDo JavaScript file, you will see methods throwing exceptions and comments about where that function is being called in the project. You need to complete the methods that the tool was not able to translate.

6.1. Implement Audio APIs

Open pendingAPIcallsToPort\TODO_API_application_AVAudioplayer.js. You will see 4 methods to implement, but you only need to implement initWithContentsOfURL_error and play methods. Copy the code below to complete the implementation of initWithContentsOfURL_error and play.

 play: function() {
  var that = this;
  setTimeout(function(){
   that._audio.play();
  }, 0);
 },
 
 initWithContentsOfURL_error: function(url1, arg2) {
  // parameter url1 is of type HTMLAnchorElement
  this._audio = new Audio(url1.href);
  return this;
 },

See the Pen %= penName %> by Intel IDZ (@intelidz) on CodePen

6.2. Implement JSON serialization

Because JavaScript provides native support to deal with JSON it is better to provide new implementations for serialization directly in JavaScript. Here we use HTML5 localStorage API to implement the persistence.

Open the file Classes\LeaderboardManager.js and replace the code for functions leaderboard, addScore_name, saveData and getData with the one provided below.

application.LeaderboardManager.leaderboard = function() {
    return application.LeaderboardManager.getData("leaderboard");
};
 
application.LeaderboardManager.addScore_name = function(score, name) {
    var leaderboard = application.LeaderboardManager.leaderboard();
    
    var scoreDic = new APT.Dictionary();
    scoreDic[new String("name")] = name;
    scoreDic[new String("score")] = score;
    leaderboard.push(scoreDic);
    
    leaderboard = leaderboard.sort(function (a, b) {
        if (a.score > b.score) return -1;
        if (a.score < b.score) return 1;
        return 0;
    });
    
    var leaderboardDictionary = { "leaderboard": leaderboard };
    var leaderboardString = JSON.stringify(leaderboardDictionary);
    application.LeaderboardManager.saveData("leaderboard", leaderboardString);
};
 
application.LeaderboardManager.saveData = function (name, data) {
    localStorage[name] = data;
    return true;
};
 
application.LeaderboardManager.getData = function (name) {
    var data = localStorage[name];
 
    if (data == null) {
        return new Array();
    }
    else {
        var jsonVar = JSON.parse(data);
        for (var i = 0; i < jsonVar.leaderboard.length; i++)
        {
            jsonVar.leaderboard[i] = new APT.Dictionary().initWithDictionary(jsonVar.leaderboard[i]);
        }
        return jsonVar.leaderboard;
    }
};

See the Pen %= penName %> by Intel IDZ (@intelidz) on CodePen

6.3. Re-factor dynamic calls

Open the file Classes\LeaderboardViewController.js and look into the function tableView_cellForRowAtIndexPath to remove the call integerValue():

/* call to 'integerValue()' removed */
cell.detailTextLabel().setText(APT.Global.sprintf(new String("%i"), scoreDic.objectFor(new String("score"))));

See the Pen %= penName %> by Intel IDZ (@intelidz) on CodePen

The call to integerValue() is not translated by the tool (in JavaScript is not needed) because it is a dynamic message to a generic Objective-C object. Current version of the tool does not support API translation of dynamic messages. Because of that, it is recommended to provide type information for all variables and temporal values in your original source code before running the translation.

6.4. Tweak CSS files

In the next step, you will change properties in generated CSS files. The tool generates a pair of .html and .css file for each view found in translated .xib files.

The current tool does not support all of the properties or kind of values available in .xib files. For some labels, the sample use other color spaces that are not RGB. Those color properties are not translated and we need to update the generated code.

Open the file Classes\WriteScoreViewController_View_XXXXXX.css (the number at the end is not important) file and for each div#Label with a missing color: property add a new line "color: white;". See the example below.

div#Label_934540285
{
    text-align: right;
    width: 54px;
    height: 21px;
    position: absolute;
    left: 14px;
    opacity: 1;
    top: 116px;
 
    /* new attribute color added */
    color: white;
}
 
div#Label_760896869
{
    text-align: left;
    width: 105px;
    height: 23px;
    position: absolute;
    left: 168px;
    opacity: 1;
    top: 54px;
 
    /* new attribute color added */
    color: white;
}

See the Pen %= penName %> by Intel IDZ (@intelidz) on CodePen

To make the code more readable, you can change the 'id' attribute in the .html file. But you may need to also update the file xibboilerplatecode.js. The numbers in the id attribute, are numbers used internally by .xib files in the original application.

Next, open the file BalloonNinjaViewController_View_XXXXX.css and add properties to label's CSS selectors to make the font bold and bigger.

div#Label_88872199
{
    text-align: center;
    width: 55px;
    height: 37px;
    position: absolute;
    left: 133px;
    opacity: 1;
    top: 7px;
    color: rgba(255,246,6,1);
    
    /* change the font to be bold and 16pt*/
    font-weight: bold;
    font-size: 16pt;    
}
   
div#Label_397160484
{
    text-align: center;
    width: 114px;
    height: 37px;
    position: absolute;
    left: 206px;
    opacity: 1;
    top: 7px;
    color: rgba(0,255,74,1);
    
    /* change the font to be bold and 16pt*/
    font-weight: bold;
    font-size: 16pt;
}

See the Pen %= penName %> by Intel IDZ (@intelidz) on CodePen

The last file that you need to update is Classes\LeaderBoardViewController_View_XXXXX.css. Open that file and set the TableView's property background-color to transparent as shown below.

div#TableView_91620652
{
    /* change background color to transparent */
    background-color: transparent;
   
    /* and change width from fixed size to relative */
    width: 80%;
    height: 283px;
    position: absolute;
    left: 54px;
    opacity: 1;
    top: 80px;
}

See the Pen %= penName %> by Intel IDZ (@intelidz) on CodePen

Now, you are ready to test your new HTML5 application by running the project in the Intel® XDK or the Windows 8* OS emulators. For example, read the readme.txt file in the output HTML5_Conversion directory and locate the zip file (bundle) and upload instructions in the /intel_xdk_package subdirectory.

Translated app running inside the Intel® XDK emulator

Translated app running in Windows 8* OS emulator from Microsoft* Visual Studio*

Resources