Introducing Projects

App development is a team sport and most of you want to develop more than one. Which is why, late last week, we pushed a major update to the Toolkit and our website to support Projects.

We wanted to make collaboration much easier than it has been before. Also, many of you are contracted to develop apps on behalf of several end clients. So we wanted to make it simple to separate out different projects and have different apps for each.

So what’s changed?

You develop, build, test and package as you always have. But you manage your account and share your app code in a different way.

Your account can own one or several Projects. Each Project consists of apps that you build and team members with whom you collaborate. If you have an existing account, your first Project has automatically been created for you, and any apps that you’ve created before will be part of that first Project. If you create a new account you will be prompted to create your first Project:

You can create new Projects from your account page. Each Project has its own pricing plan which you should pick based on how many apps you’re building, the team size, and support requirements for the particular Project.

How do I interact with my Projects in the Toolkit?

  1. Start the Toolkit as you normally would.
  2. Incidentally, as part of this release we’ve combined the Toolkit and website login so if you’re logged in once you’re logged in to the same account across both.

  3. The home screen is now the Projects screen – you can see the list of your Projects, manage them or dive into them by clicking on the name:
  4. If you click on the Project name you are taken to the manage apps screen:

    From there you can create apps or import them by clicking the buttons. Or just click through the app name to run or package on various platforms. The difference now is that, as long as you are an owner or collaborator on the project, you can import app code without needing to create your own src/identity.json.

  5. To invite other team members to work on a Project with you, click ‘Manage’ next to the Project in your Toolkit homepage. Your team members will need to have created their own Trigger.io account and you reference them by email address:
  6. Once they have been added to the Project, you can share your app code with them via your usual source control. They can use the “Import existing app” button, pointing the Toolkit at the source you’ve shared with them, to start working on the app with you.

Awesome! Now what’s next?

We’re always working to add new native APIs, UI components and improve the tooling.

Email support@trigger.io with your suggestions. We’d love to hear from you!

On top of that, you can expect releases soon which make our Native Plugins even more powerful, and simpler to share and consume.

New feature roundup: native date / time picker, analytics with Flurry, Android events

Trigger.io is about using the best of native and HTML5 to build amazing apps like these ones, and iterate them fast. So we’re delighted to announce native date / time picker enhancement on Android amongst other improvements.

While we’ve released Native Plugins and Windows Phone 8 as major new features in the past couple of months, we’ve also quickly iterated the core platform and here, we’ll walk you through a few of the new modules we’ve added. If you like what you see, check out the awesome apps our customers are building and sign-up now to build for yourself!

Native date / time picker

Accepting date / time input using regular HTML5 is simple, and on iOS it looks great since the native picker is triggered automatically when you click on the form element.

<p>Birthday (date and time):</p>
<form>
	<input type="datetime" name="bdaytime">
	<button>Submit</button>
</form>

But on Android, not so much…

But now, enabling a native date / time picker on Android is as simple as enabling our new native ui module and using the JavaScript API once your HTML has rendered:

forge.ui.enhanceAllInputs();

See the difference on Android:

Analytics with Flurry

Many of you have asked for an analytics solution and we’ve added the first of these by integrating the Flurry SDK. Use the Trigger.io module for Flurry by simply enabling the module and using the JavaScript API where needed.

Just by enabling the module, simple information such as sessions, active users and new users – will be available in your Flurry dashboard. With the API you can send custom and timed events to really get to grips with how users are using your apps. Let our integration with Flurry handle all the offline caching and synching. Just register the events with the API and forget about it until you visit your dashboard.

Android events

The back button on Android works fine with Trigger.io apps – use a library such as backbone.js and it’s support for pushState / hash-based URL fragments for history.

But sometimes you want finer grain control, such as exiting the app after a certain number of back button touches. Or intercepting it to change the default behavior. To enable that we’ve added two new event APIs:

forge.event.backPressed.preventDefault(function() {

	forge.logging.log('Success preventing default back button action');

}, function(content){

	forge.logging.log('Error: '+ content);

});

forge.event.backPressed.addListener(function(closeApplication) {

	//Close application instead of navigating back in webview history
	closeApplication();

});

That’s it for now…

Sign up now to take advantage of these new features or get in touch with us at anytime at support@trigger.io

Webinar: Update your Trigger.io app without resubmitting to the App Store

Join James Brady, Trigger.io CTO next Thursday for our second webinar that’s open to all our users, including those on free trials.

How to setup and use Reload to iterate your app without resubmitting to the App Store

Join us for a Webinar on November 8

Space is limited. Reserve your Webinar seat now at:
https://www1.gotomeeting.com/register/235041160

Details

Trigger.io co-founder and CTO, James Brady, demonstrates how to setup and use Trigger.io Reload so you can interate your app at web speed.

He will cover:

  • How to set yourself up with Reload
  • Expected usage patterns
  • Explanation of the interfaces
  • Demonstration and pitfalls

There will be an opportunity to ask questions about your specific app, and the best one will earn the asker an exclusive Trigger.io t-shirt!
Title: Trigger.io Webinar: how to setup and use Reload to iterate without resubmitting to the App Store
Date: Thursday, November 8, 2012
Time: 10:00 AM – 10:45 AM PDT
After registering you will receive a confirmation email containing information about joining the Webinar.

System Requirements

PC-based attendees
Required: Windows® 7, Vista, XP or 2003 Server

Macintosh®-based attendees
Required: Mac OS® X 10.5 or newer
Mobile attendees
Required: iPhone®/iPad®/Android™ smartphone or tablet

How to create your mobile app backend with Kinvey and ql.io

Kinvey is a Backend-as-a-Service (BAAS) platform which allows you to develop a backend for your app without the hassle of dealing with hosting providers, configuring servers or even writing that much code.

We thought that was pretty cool so we took a trip to Kinvey’s office in Cambridge to meet up with Brian Wilson, their Lead Architect.

http://www.kinvey.com/images/office/sodas_.jpg

After he showed us around (and treated us from the most stupendous soda bar in existence!) we got our laptops out for some serious code-fu. Time passed. The sun set. Then it rose again. Finally the CD player refused to play “Eye of the Tiger” even one more time and we were done.

Enjoy this tutorial we cooked up for you!

It will give you a taste for how easy it is to use Kinvey to create a backend for your Forge application and open the door to a whole new way of thinking data served by web services.

Goal

This tutorial is intended to:

  • Guide you through setting up the original weather tutorial to use as a starting point.
  • Setting up an account on Kinvey
  • Creating a data collection on Kinvey to serve the weather data
  • Creating an alternate data collection on Kinvey to serve the weather data

Preparation

Before starting this project you’ll need to setup your Trigger.io Forge environment so you can build / test native mobile apps using the JavaScript code below. That should take just a few minutes in 3 easy steps:

By the end of that you’ll be able to build and test your mobile app as you write the code described below. So let’s get started…

Goal: Set up the project

To get started grab yourself a copy of our weather tutorial sources by cloning it from the Github repository or by downloading the sources as a zip file and move the files into your app’s src directory.

Before you can run the app to check that everything is correctly set up you first need to sign up for API access at http://www.wunderground.com/weather/api/ and make a note of your API key.

Once you have done that open the src/js/weather.js file and modify the following code to contain your API key:

function getWeatherInfo(location) {
    var api_key = "YOUR_API_KEY";
    .
    .

Once you’ve done this build and run your app to verify that it works.

Goal: Create an account on Kinvey

Now that you have a working app you will need to sign up for an account at kinvey.

Once you’ve signed up you will be able to download the JavaScript version of the Kinvey library and place it in your src/js folder.

Using Kinvey to serve weather data

Goal: Create a data collection for weather underground data

Kinvey provides a collection API that can serve data to your app from a wide variety of sources such as a relational datastore, location services, social networking feeds or almost any other web service you can imagine.

For this tutorial we’re going to start by using Kinvey to access an existing web service to supply the weather data for your app.

To get started open the Kinvey management console and perform the following steps:

  1. Click on Add an App and create a new application called Weather App
  2. Open the app you created and make a note of your App Key and App Secret as you’re going to need it a bit later.
  3. Now click on New Collection and create a collection called weather making sure you check the This collection will be used for Data Integration checkbox.
  4. Select Custom/Private and click on the ql.io tab.

Next, we’ll use the ql.io language to tell kinvey how to access the weather service we want to use. If you are familiar with SQL you should find it quite easy to follow!

To do this, enter the following ql.io Script in the text field:

create table weather
        on select get from
        'http://api.wunderground.com/api/<your-wunderground-api-key>/conditions/forecast/q/{state}/{city}.json'
        using patch 'support/patches/acceptAll.js';
    data = select * from weather;
    return [ "{data}" ];

(Remember to replace the text <your-wunderground-api-key> with the key you obtained earlier!)

What this does is to create a table called weather which contains the results of the request made to api.wunderground.com. The last line simply selects the entire content the table and returns it to your app.

You can test that everything works by opening the Kinvey API console and entering the following in the URL target input field:

/appdata/<your-kinvey-app-key>/weather/?query={"state":"CA", "city":"San_Francisco"}

You should then see something like this:

Query the data collection from your app

Goal: Modify the weather app to query Kinvey

If you’ve not already done so, download the Kinvey JavaScript library and place it in your project’s src/js directory.

Open index.html in your editor of choice and modify the head tag as follows:

    <head>
        <link rel="stylesheet" type="text/css" href="css/style.css">
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript" src="js/mustache.min.js"></script>

        <!-- add the Kinvey javascript library -->
        <script type="text/javascript" src="js/kinvey-js-0.9.10.js"></script>

        <script type="text/javascript" src="js/weather.js"></script>
    </head>
    .
    .
    .

Then open weather.js and add the following code to the jQuery.ready listener:

Kinvey.init({
        appKey: "<your-kinvey-appKey>",
        appSecret: "<your-kinvey-appSecret>"
    });

Also in weather.js go to the getWeatherInfo() function and replace the call to forge.request.ajax with the following code:

/* forge.request.ajax({
        url: "http://api.wunderground.com/api/" + api_key +
        .
        .
        .
    }); */

    var query = new Kinvey.Query();
    query.on("state").equal(location.split('/')[0]);
    query.on("city").equal(location.split('/')[1]);
    var collection = new Kinvey.Collection("weather", { query: query });
    collection.fetch({
        success: function(data) {
            forge.logging.info("[getWeatherInfo] success");
            callback(data[0].attr);
        },
        error: function(error) {
            forge.logging.error("[getWeatherInfo] " + JSON.stringify(error));
        }
    });

It’s that simple! Now if you build and run the app you should see the same behavior as before except that now your data is being server by kinvey.

Configure Kinvey to supply the weather data from an alternate provider

Goal: Modify the data collection

Round about now you may be asking yourself what the point of all this was. After all, your app isn’t working any better than before!

But what happens when a web service your app relies on is suddenly discontinued or bought out by someone else? (Don’t laugh, it happened to us with the first version of our weather app tutorial!)

Also, what happens when you find an alternative service which is cheaper and more powerful, or you’d like to easily combine an existing web service with your own data, location data and social networking data?

To demonstrate the power of what we’ve done so far we’re going to replace the Weather Underground API we’re currently using to obtain forecasts with another provider.

So open your browser and surf over to http://www.worldweatheronline.com/register.aspx for the interminably annoying process of swapping your email address for an API key.

Next, modify your ql.io Script on Kinvey as follows:

-- set up a weather table we can query for our results
    create table weather
        on select get from
        "http://free.worldweatheronline.com/feed/weather.ashx?q={^city}&format=json&num_of_days=2&key=<your-api-key>"
        resultset "data";

    -- massage the data into resembling something our code can digest
    data = select * from weather;
    return [ {
        "current_observation": {
            "display_location": {
                "full": "{data.request[0].query}"
            },
            "observation_time": "{data.current_condition[0].observation_time}",
            "weather": "{data.current_condition[0].weatherDesc[0].value}",
            "temp_f": "{data.current_condition[0].temp_F}",
            "temp_c": "{data.current_condition[0].temp_C}",
            "relative_humidity": "{data.current_condition[0].humidity}",
            "wind_string": "",
            "icon_url": "{data.current_condition[0].weatherIconUrl[0].value}"
        },
        "forecast": {
            "simpleforecast": {
                "forecastday": [
                    { "date": { "weekday_short": "{data.weather[0].date}" },
                      "high": { "fahrenheit": "{data.weather[0].tempMaxF}",
                                "celsius": "{data.weather[0].tempMaxC}" },
                      "low": { "fahrenheit": "{data.weather[0].tempMinC}",
                               "celsius": "{data.weather[0].tempMinC}" },
                      "conditions": "{data.weather[0].weatherDesc[0].value}",
                      "icon_url": "{data.weather[0].weatherIconUrl[0].value}" },
                    { "date": { "weekday_short": "{data.weather[1].date}" },
                      "high": { "fahrenheit": "{data.weather[1].tempMaxF}",
                                "celsius": "{data.weather[1].tempMaxC}" },
                      "low": { "fahrenheit": "{data.weather[1].tempMinC}",
                               "celsius": "{data.weather[1].tempMinC}" },
                      "conditions": "{data.weather[1].weatherDesc[0].value}",
                      "icon_url": "{data.weather[1].weatherIconUrl[0].value}" }
                ]
            }
        }
    } ];

Replace <your-api-key>, hit save, restart your app and bazinga!

That’s it!

If this isn’t the coolest thing you’ve seen all year you’re definitely keeping better company than us.

Without changing a single line of code in your app and without forcing your users to wait for an updated version of your app to make it through the app store approval process you’ve switched to an alternative data source!

To find out more about the sheer awesome you can now accomplish go take a look at the kinvey documentation and the ql.io website.

Any problems at any point? Check out the Trigger.io tutorials, the Catalyst debug tool or contact support@trigger.io for fast help.

 

Windows Phone 8 Support

We announced our support of Windows Phone earlier this year, and with Microsoft’s launch today of Windows Phone 8 we’ve updated our builds to use the latest v8 SDK.

You can see builds in action and submission to the app store with our earlier screencast:

It has been a pleasure to work with the team at Microsoft and the technology they have provided. Apps build with the previous SDK will work on Windows Phone 8, and we found the process of updating to the latest version for our builds to be fast and simple.

Amongst the many improvements with the latest SDK, we can now do file transfers when the app is in the background which we are able to leverage with the Reload feature allowing you to push updates to your HTML5 without needing to resubmit the app to the store.

Read more about Windows Phone 8 for developers at  and sign-up for our Go Pro plan now to build native Windows Phone 8 using HTML5.

 

Guest post – inside Hojoki’s mobile build process

This guest blog post was written by Patrick Rudolph, Mobile Lead at Hojoki. They are a Germany-based startup that provide a platform for individuals and teams, integrating all your different cloud apps into one comprehensive app. As well as their web app, Hojoki offers mobile apps for iOS and Android (powered by Trigger.io).

 

By the time we decided to build our mobile apps with Trigger.io, we already had a web app in place for a year. There were existing processes that made testing and deploying easier, so we figured it might be best if the mobile development takes advantage of these practices. See Hojoki in action with this screencast by Amir of Trigger.io:

Here’s a run-down of the various tools, processes and scripts we use to handle our mobile builds.

When it comes to building our apps, we use Grunt, a task-based command line build tool for JS projects. Alongside some predefined tasks, such as validating & minifying your code or running QUnit tests, you can include 150+ plugins or write your own tasks. Luckily, next to their GUI Toolkit, Trigger.io also provides a couple of very easy commands (such as forge build and forge run), which can be easily integrated in a custom Grunt task.

Instead of using this type of build tool, one could also take advantage of Trigger’s hook system, which lets you easily perform tasks at certain points during the build process. However, we are not using hooks because we only use Trigger.io for our mobile apps, but want to keep the same build process for all of our projects.

Validation

Hojoki is doing a lot of processing on the client side. This means we have a huge JS code base. For many reasons, these JS files are organized in modules and get loaded on demand (we use a custom loading mechanism on top of LABjs). The resulting bulk of modules and dependencies adds a lot of complexity, which needs to be carefully validated. When calling grunt without any parameters, we’ll perform two tasks:

  1. dependency checks (ensure nothing is missing)
  2. jslint (ensure everything is valid)

Example of running grunt and getting a dependency issue and a JS error.

Deploy to the web

As soon as we want to build our app for the web, (this also includes the browser version of the mobile app) there are some more tasks to complete on top of the validation. Using many JS files that are loaded in demand is nice for development, but would result in lots of requests for the user if deployed directly. Another related topic is to prevent caching issues for users when updating an existing web app. Our command for this step is called grunt deploy and it performs the following tasks:

  1. copy all relevant files to dist/web/
  2. concat and minify CSS and JS
  3. include md5 hash in minified files
  4. replace placeholders in index.html with new file names
  5. gzip HTML, CSS and JS

Deploy the native apps

Lets get to the part where Trigger.io’s Forge tools come into play. This is basically an improved version of “grunt deploy” and includes the following tasks:

  1. All steps from grunt deploy
  2. copy all files to dist/native/
  3. forge build target
  4. delete unnecessary files to reduce app size
  5. forge run target
  6. forge package target
  7. copy a snapshot of the current code base to our revision control in order to have the legacy version available when making use of Trigger.io Reload

In order to trigger the tasks above, we registered the following commands:

  • Step 1 – 4: grunt build
  • Step 1 – 5: grunt run-target *
  • Step 1 – 6: grunt package-target **
  • Step 1 – 7: grunt release-target **

*  target can stand for ios or android
** target can stand for all, ios or android, step 5 is ignored for grunt package & release

Let me get into more detail on some of the steps mentioned above:

Until recently, we have updated the manifest file (Android) and the Info.plist (iOS) after step 3, to enable custom URL schemes (e.g. hojoki://) for our app. However, custom urls been implemented as a native feature by Trigger.io as of API version 1.4.15, making it very easy for everybody to use this.

Step 4 can come very handy if your app’s resources (especially images) vary heavily between iOS and Android. Once the app has been built, we delete all Android images in the iOS build and vice versa. Here is a snippet right from our grunt code:

log.writeln('\nreducing app size'.yellow);
[ 'dist/native/development/android/assets/src/images/ios',
  'dist/native/development/ios/device-ios.app/assets/src/images/android'
].map(function(folder2delete) {
  log.writeln('  deleting ' + folder2delete.blue);
  rimraf.sync(folder2delete);
});
log.writeln('[   DONE]'.green);

As of API version 1.4.17, we are also using wireless distribution to accelerate iOS testing on multiple devices even more. A possible integration of this new feature into the build tools involves replacing the placeholder URLs and renaming the wireless distribution plist file. Otherwise we’d always need to change the link to the plist file on the distribution page. Of course there are other ways, like detecting it automatically with a server-side language like PHP. Here is our implementation, which runs right after grunt package is finished:

log.writeln('\npatching ios wireless distribution plist'.yellow);
grunt.file.expandFiles([
  'dist/native/release/ios/*-WirelessDistribution.plist'
]).map(function(plistFile) {
  var pflistContent = file.read(plistFile);
  var versionId = plistFile.split('-')[1];
  pflistContent = pflistContent.replace(
    'http://www.example.com/app.ipa',
    'http://www.yourpage.com/custompath/appname-' + versionId + '.ipa'
  );
  pflistContent = pflistContent.replace(
    'http://www.example.com/image.57x57.png',
    'http://www.yourpage.com/custompath/filename-57.png'
  );
  pflistContent = pflistContent.replace(
    'http://www.example.com/image.512x512.jpg',
    'http://www.yourpage.com/custompath/filename-512.png'
  );
  file.write(plistFile, pflistContent);
  fs.renameSync(plistFile, 'dist/native/release/ios/appname.plist');
});
log.writeln('[   DONE]'.green);

Another interesting part of our build process might be step 7. Here we commit a snapshot of the current code base in an extra branch of our revision control, in order to use Trigger.io Reload more easily later on. Imagine you want to fix something in one of your older app store versions, which has many parts of its code already changed by now. How would you be able to change a small portion of the code and push a Reload without having the source code of this exact version? Here is the code:

if (release) {
  log.writeln('\nadding snapshot to svn'.yellow);

  [ 'dist/native/development',
    'dist/native/.template',
  'dist/native/.lib' ].map(function(folder2delete) {
    log.writeln('  deleting ' + folder2delete.blue);
    rimraf.sync(folder2delete);
  }); // we don't want to commit those

  var url = 'https://your-version-control-url/snapshots/' +
    moment().format('YYYY-MM-DD');
  log.writeln('  deleting old');
  grunt.helper(
    'hojoki-exec', // similiar to grunt-exec
    'svn delete ' + url + ' -q -m "deleting old"',
    true, true)
  .always(function() {

  var config = JSON.parse(file.read('dist/native/src/config.json'));
  var msg = '#snapshot of version ' + config.version +
    ' (platform ' + config.platform_version + ')' +
    ((target_android &amp;&amp; ' #android') || '') +
    ((target_ios &amp;&amp; ' #ios')   || '');

  log.writeln('  committing "' + msg + '"');
  grunt.helper(
    'hojoki-exec',
    'svn import dist/native/ ' + url + ' -q -m "creating ' + msg + '"',
    true, true)
  .done(function() {
    log.writeln('[   DONE]'.green);
  });
});
}

Example of an automated commit (as seen in Beanstalk) done by step 7 when running grunt release-all.

In case you are wondering, hojoki-exec is basically the same as grunt-exec, but with deferreds (done(), fail(), always()). The code snipped above triggered the following output when I released our app version 1.4.2 for both Android and iOS:

What else?

Even though our mobile apps share lots of their code base with our web app, the latter has a much longer history when it comes to a customized build process. Other tools that we have in use, include image conversation and optimization (ImageMagick, pngquant, ImageOptim), image spriting (Glue) and running QUnit tests (predefined grunt task).

Sure enough, there is always more you can do for automation. One thing we’d like to do soon is switching to LESS or Sass and include CSS validation in the build process. Adding support for source maps and playing around with lazy JS instantiation are also interesting topics related to this.

This blog hopefully provided you with some insights to our build process and will help to make building and deploying apps with Trigger.io even easier.

 

Sign-up for Trigger.io now to get started with your mobile app. Questions? Email support@trigger.io anytime.

Work On What You Want Week #2

When you’re developing software it’s easy to fall into the habit of ploughing through the backlog to knock off the most-requested features and highest priority bugs, iteration after iteration, without setting aside time to explore and experiment our product and our service.

At Trigger.io, work on what you want week (wowyww) happens once a quarter: the idea is we give all our developers free rein to hack on anything they want, so long as it’s somewhat related to one of our products.

This time around, wowyww produced a tile-based game built on our Forge platform using canvas elements, an improved analytical backend to help us understand what parts of the platform our customers use most, and a custom sound generator built on our shiny new plugin system. Here, I’ll let the guys describe what they did and why.

Antoine

What did I want to work on?

I wanted to push the limits of our Forge tools a little and see if it was possible to write a mobile game using Javascript and the Canvas element.

I’m a huge fan of simulation games such as SimCity so I came up with the idea of adapting a model from the book “The Limits To Growth” by
Meadows & Randers and creating a simple tile-based game around it.

Why did I want to work on that?

I’m a firm believer in the principle of “Eating your own dog food” and wanted to get a real feel for the behavior & performance of our tools when used in anger.

Getting to have a boatload of fun in the process was, of course, no small incentive!

What was the result at the end of the week?

No doubt I’m somewhat biased but my strongest impression of using Forge over the course of the week was how little time I spent thinking about Forge vs the amount of time I spent thinking about my code!

I used the Trigger Toolkit primarily to create the project, manage my app configuration and deploying to a physical device. For rebuilding my changes and testing them in an emulator I opted to use our Command-line Tools instead.

During development I also used Trigger Catalyst which provides a remote WebKit-style debugger. It’s an incredibly powerful tool but I found it could be a bit slow when your network connection is heavily loaded.

(Game graphics courtesy of the most excellent Danc’s Miraculously Flexible Game Prototyping Graphics for Small Worlds)

This was my first time writing a game for a mobile device instead of the desktop so I wasn’t sure what to expect.

While I knew writing Javascript would be orders of magnitude easier than a language such as Java or Objective-C I had concerns about the amount of effort required to coax realistic performance from HTML5/Canvas.

It therefore came as a welcome surprise to find that I could populate a 2048×2048 pixel canvas with over a thousand bitmap tiles to create a smoothly scrollable game world without applying even the simplest of optimizations to my code.

Overall I found mobile gaming performance to be bounded more by the memory constraints of the device rather than Javascript execution speed or rendering performance. A nice constraint to have indeed!

Connor

What did I want to work on?

I wanted to try out our new native plugins from the perspective of a user. I wanted to make something fun that couldn’t be done without native code, so I decided to make a plugin to generate silly noises based on user input.

Why did I want to work on that?

Seeing things from the perspective of the user is a good way for us to find out if we’re doing things that make sense: this is especially important in a large project (like native plugins) where we have had to make a number of decisions and assumptions about how users will want to work.

Acting as a user allowed me to see what worked well and what could be improved, and doing this while we are still developing native plugins means this feedback can be quickly applied in our development iterations.

It also provided a chance to check our documentation made sense and to create a more detailed example of what a complete plugin looks like, rather than just the very basic example code we include with the inspector projects used to develop native plugins.

What was the result at the end of the week?

First I created a plugin working on both Android and iOS that can start, stop and change the properties of a continuously generated noise. The start and stop events are hooked up to touchstart and touchend events, and changing the noise to touchmove in Javascript.

The result is an app that when touched makes noise that the user can control:

Native Plugins for Trigger.io Forge: a simple sound generator.

This sort of feature could be really useful when creating a game or other fun apps, and it demonstrates the power of native plugins and how you can go about coding them.

All of the source is available on GitHub: https://github.com/Connorhd/forge-plugin-noise.

Tim

What did I want to work on?

Analytics on the config.json files submitted by our users when creating apps with our cloud build service. Users use the config.json file to specify what version of the Forge platform they want to use in their app, as well as which modules they need and various other metadata.

Why did I want to work on that?

The Forge platform (both the native code and JavaScript code) are being developed at a rapid pace by the team at Trigger.io, so we wanted a better way to keep track of what parts of our platform people are using.

This will hopefully lead to better insights as to what features our users really value in the platform, and generally help us keep track of the uptake of new versions of the platform, which lets us deprecate older versions at a pace which doesn’t inconvenience anyone.

What was the result at the end of the week?

The analytics are live and we’re now able to get a better idea about what people are requesting from the Forge build service, in terms of both platform versions and modules.

Most people seem to stay up to date with the Forge platform by sticking with the latest major version (currently v1.4), which always refers to the latest deployed code in the 1.4.x series.

On the left we can see the most used modules: request, logging and reload are among the most popular.

Now that we have a system in place for collecting these basic analytics from the build service, we should be able to measure more statistics on builds without too much work!

Trigger.io Native Plugins beta

Trigger.io now supports native plugins – docs here.

This lets  you to add to the basic Trigger.io native modules for mobile by creating your own native APIs, like our existing camera API, and native UI elements, such as our native topbar component.

Or integrate 3rd party native SDKs like we have with Facebook and Parse.

We expect most developers to continue using Trigger.io to create mobile apps without writing any Objective-C or Java at all. But everyone will benefit from this feature:

  1. We will provide tools for web developers to easily consume the new native modules that are created by others
  2. Eventually, we will let you charge people for usage of your plugins – meaning you can actually make money by creating a plugin!

Here’s a short video showing a fun example plugin in action – it lets an app generate noises when the user touches the screen that change as the user moves their finger. Pretty good for games! The code  for this plugin is available on GitHub.

I created this plugin as part of our recent work on what you want week (which will be featured in another blog post shortly). Read on to start building plugins of your own.

Get started

Signup for a plan and email support@trigger.io so we can enable your account for the beta.

Install the Trigger.io Toolkit and familiarize yourself with the basic build / test process with our tutorials.

Problems or questions? Ask on our StackOverflow tag or email us anytime, we’d love to hear from you.

Tutorial: How to create a Trigger.io native plugin

Note, for the latest information on how to create plugins, see the official docs – they are updated more frequently than blog posts!

In order to develop plugins, we provide what we have called Inspector projects. These are Xcode or Eclipse projects, setup to run a mobile app including the Forge platform, with a prebuilt front-end app that can be used to exercise your plugin during development. Let’s take a look at what this actually means and how we can use it.

First of all, we have to register a new plugin: I can do that using the Toolkit once plugins have been enabled.

As this is a new plugin, we’re going to create a new local version to work with. If you joining the development of a plugin, you should share this local version via source control, then choose the “Import” option instead.

create local version

iOS

We are going to look at iOS first, we’ll see how Android compares further down in this blog post.

First, we need to download the Xcode Inspector project – after clicking “Update iOS inspector” you should find the Xcode project in inspector/ios-inspector:

In Xcode we can immediately Run the ForgeInspector target and try out the app.

Here we can see an interface to test our native API methods. The Inspector app includes an example “alert” plugin to get you started, so we can try that out straight away.

By choosing the module and method I want to run, the inspector app will let me give some test input and call the API method. Here we can see the alert.show method called with input {text: "Test"}. The app also allows us to see what went on behind the scenes with a log of all calls and results which we can further down on the phone screen.

In the blue box, we see the original invocation with our parameter, and in the green box (green meaning success), the return value of the invocation – in this case, null.

Next we can look at the source for the alert module which will give us the basic structure for modules in general.

The important things to notice about the source are:

  • We are working in a class called alert_API: any API you want to be exposed to JavaScript must go in a called called modulename_API.
  • The method signature looks like + (void)show:(ForgeTask*)task text:(NSString *)text.
    • The name of this API method is show.
    • The first parameter is always a ForgeTask object.
    • Any additional parameters are up to you and will be populated based on the object sent back from JavaScript. In this case the “text” property from JavaScript will be passed as the second parameter.
    • If you want optional parameters or other advanced usage you can use [task params] within the method to access the full parameter object passed from JavaScript.
  • To finish an API method invocation, [task success:result] or [task error:result] is called: you should always call exactly one of these methods when an API call is made.

That’s about it! At this point we recommend you try editing the alert module to get a feel for how plugins work, from there you should be able to create your own class and export your own module. Further details can be found in the iOS plugin docs.

Android

For Android we start by updating the Inspector project with the “Update Android inspector” button. Once the download is complete, you can import the Android projects into Eclipse by importing the inspector/an-inspector directory:

Once imported, we can run the ForgeInspector project as an Android app, and we will see a similar setup to iOS – a simple app that lets us test out our API methods.

Entering “Test” and running the alert.show method shows an alert box as we would expect:

And the app records the API call and response:

Now we have tried out the alert module we can take a look at the code:

The important parts of this code which will be needed in any module are:

  • The class is called API, and is in a package io.trigger.forge.android.modules.alert, API methods are always looked for in io.trigger.forge.android.modules.modulename.API.
  • The method signature looks like public static void show(final ForgeTask task, @ForgeParam("text") final String text)
    • The name of the API method is show.
    • The first parameter for all API methods is a ForgeTask object.
    • The second parameter has an annotation: this is required in order to match up parameters passed from JavaScript. In this case the text property of the parameters object in JavaScript will be passed as the second argument to the API method.
  • API methods are always completed by calling exactly one of task.success(result) or task.error(result).

We’re now at the same point on Android as iOS – hopefully you can edit the alert module and create your own using it as a template. For further details see the Android native plugin docs.

JavaScript

The final thing you need to know is how to call your new plugin API methods from JavaScript. On both platforms the inspector app will help you out by letting you call your various API methods through a simple interface. In order to let you fully test your plugin you can edit the HTML and JavaScript included in the Inspector project – to do this simply open the assets/src/index.html file in the ForgeInspector project in either Xcode or Eclipse and start editing.

To call an API method in JavaScript you simply use forge.internal.call('module.method', params, success, error).

  • module.method is your API method, for example 'alert.show'
  • params is a object containing any parameters you want to pass back, for example {text: "Test"}. If you don’t need to pass parameters, simply use {}.
  • success and error are callback functions called on either success or error, in the same way you are used to with built in Forge modules.

That’s it!

Native plugins for Trigger.io are still in private beta, but we’re always adding new features, improving the workflow and correcting problems. Sign up to try now, and stay tuned for more news!

Trigger.io and Apigee enable fast mobile app development for the enterprise

The shift to mobile makes it necessary for enterprises to change the way they engage their customers – we see the opportunity all the time with new consumer services such as Uber and Exec disrupting older models. To keep up, enterprises need to find ways to reach their customers through new types of applications.

Trigger.io allows enterprises to reuse their existing web skills and investments to create native mobile apps while Apigee enables “business-as-service” – allowing an enterprise’s business value to be consumed by their customers in new ways through APIs.

You can create a native mobile app for iOS, Android or Windows Phone using an enterprise-ready back-end in just a few minutes using Trigger.io with Apigee.   

We recently created such an app. This blog post summarizes the steps we took. We’ll cover:

  • Getting started with Trigger.io and Apigee’s App Services data store
  • Creating a simple mobile app using Apigee’s HTML5 example code with Trigger.io and testing it in the iOS emulator
  • Adding native mobile UI components such as a topbar
  • Adding native mobile features like contacts access and SMS

Let’s get started…

Setting up Trigger.io with Apigee

Getting started is as simple as signing-up for both Trigger.io and Apigee’s App Services service for free.  Then download and start the lightweight Trigger Toolkit.

We’ll create an example app called Messagee – a simple HTML5 Twitter clone. We’ll get it running as a native mobile app that can be submitted to the App Store or Google Play. To do this you need to:

  1. Click ‘Create’ in the Trigger.io Toolkit, entering ‘Messagee’ as the app name and selecting the default location.

     You’ll now be able to see the app in the homepage of the Toolkit with the path to the code location.

  2. To get the example code running with Trigger.io you need to copy the code into your app’s ‘src’ subdirectory while keeping the ‘src/config.json’ and ‘src/identity.json’ files that were automatically created.

    To do this, open up a terminal navigate to the app directory and run the following commands:

    cd src
    mv identity.json ..
    mv config.json ..
    rm -rf *
    git clone https://github.com/apigee/usergrid-sample-html5-messagee .
    mv ../identity.json .
    mv ../config.json .
  3. Make one code change to the index.html file that you cloned from the GitHub repos to customize it for your account. That file should now be in ‘src/index.html’ and you need to change one line to reference your Usergrid app. For example:
    Usergrid.ApiClient.init('amirnathoo', 'sandbox');

  4. Build the app and see it in the emulator. 

    With a Mac, all you have to do is click on the app name in the toolkit and the click on the ‘iOS’ link to kick off the Trigger.io build and run the app in the emulator which takes just a few seconds. But even on Windows, you can still build / test on an iOS device with a little more setup. 

    After just a few minutes we already can see the app running in the iOS emulator:

Create an account in the app, compose a new message for your stream and try it out!

Apigee makes remote data storage simple

Ok now we have the app up and running in the emulator let’s take a look at the code.

The app using jQuery Mobile to handle various UI elements and navigation and Apigee’s JavaScript SDK to make accessing a remote data store simple.

You can see the JavaScript SDK in the usergrid.appSDK.js file. This makes it super simple to store and retrieve data from the Apigee backend. For example, in app.js, setting up your data objects takes just a few lines and no server-side configuration using Apigee’s JavaScript SDK:

//a new user object
var appUser = new Usergrid.Entity('user');
//a new Collection object that will be used to hold the full feed list
var fullActivityFeed = new Usergrid.Collection("activities");
//make sure messages are pulled back in order
fullActivityFeed.setQueryParams({"ql":"order by created desc"});
//default to full feed view
var fullFeedView = true;
//a new Collection object that will be used to hold the user's feed
var userFeed = new Usergrid.Collection('users/me/feed');
//make sure messages are pulled back in order
userFeed.setQueryParams({"ql":"order by created desc"});

Then later in the code we can see it reading from the user’s feed and using the data to render the HTML:

//get the users feed
userFeed.get(
	function(){
		drawMessages(userFeed);
		if (userFeed.hasPreviousPage()) {
			$("#previous-btn-container").show();
		} else {
			$("#previous-btn-container").hide();
		}
		if (userFeed.hasNextPage()) {
			$("#next-btn-container").show();
		} else {
			$("#next-btn-container").hide();
		}
	},
	function(){
		$("#messages-list").html("There was an error getting the messages!");
	}
);

function drawMessages(feed) {
  var html = "";
  var usersToBind = [];
  feed.resetEntityPointer();
  while(feed.hasNextEntity()) {
    var message = feed.getNextEntity(),
      created = message.get('created'),
      content = message.get('content'),

...

Let’s reiterate: you have created a remote data store using Apigee without ever needing to provision a server of your own, and you’ve created a native iOS app that’s now running in the emulator using HTML / CSS / JavaScript and not a hint of Objective-C in sight!

Pretty cool…

Adding Native Mobile Features

It gets even better – now that you have the basic HTML5 example app running with Trigger.io you can add native mobile features to it.

For example, you may want to replace the jQuery mobile titlebar with a genuine native topbar element. Here’s how to do this with Trigger.io’s Forge platform:

  1. Firstly, let’s enable the native modules we need in src/config.json. We’ll add the topbar, contact and sms modules. You can do that easily by checking the right boxes in your app’s App Config tab in the Trigger.io Toolkit:
  2. Now let’s remove the existing jQuery Mobile header – that isn’t really native, just HTML and CSS faked to look close to native. So let’s remove all div elements with data-role=”header” in index.html, like this one:
  3. <div data-role="header" data-theme="b">
    	<h1>Messagee</h1>
    	<a href="#login" id="btn-logout" data-role="button">Logout</a>
    	<a href="#page-update-account" id="btn-show-page-update-account" data-role="button" data-icon="gear" data-rel="dialog" data-transition="fade">Settings</a>
    </div>
    
  4. Then we can add controls for the native header in our JavaScript at the bottom of app.js.

    Notice how we add buttons to the native topbar using the Trigger.io Forge JavaScript API and can set the styling and callback functions:

    function addTopbarButtons() {
    	forge.topbar.addButton({
    		text: "Logout",
    		position: "left"
    	}, function (button) {
    		logout();
    	});
    	forge.topbar.addButton({
    		text: "Settings",
    		position: "right"
    	}, function () {
    		window.location = "#page-update-account";
    		forge.topbar.removeButtons();
    	});
    }
    
    forge.topbar.setTitle('Messagee');
    forge.topbar.setTint([57, 107, 158, 1]);
  5. Finally we need to add and remove the buttons according to navigation within the app. Search app.js for places where we set window.location and use the Trigger.io Forge API to remove the buttons where we navigate away from the main feed page and add them back when we navigate to it e.g.
    window.location = "#page-login";
    forge.topbar.removeButtons();
    
    window.location = "#page-messages-list";
    addTopbarButtons();

Great! You’re ready to test the app again – if you run the app in the iOS emulator by clicking the iOS link in the Trigger.io Toolkit and logging in, you’ll see the native topbar with buttons like in the screenshot at the top of this post.

Adding contact selection and SMS features

Now let’s add an option so that when a user posts a new message to their feed they can also send the same message by SMS to one of their contacts.

That’s super simple with Trigger.io Forge – we’ve already enabled the contact and SMS modules in the App config tab in the Toolkit. So all we need to do is:

  1. Add a new ‘Post & SMS’ button to the create new message view by modifying index.html:
    <div data-role="page" data-theme="b" id="page-new-message">
    	<div data-role="content">
    		<form name="login" id="login-form">
    			<label for="content">Message (150 Chars max)</label>
    			<textarea id="content" class="input-xlarge" rows="3" style="margin: 0px; width: 100%; height: 125px; "></textarea>
    		</form>
    		<div style="width: 100%;">
    			<button id="post-sms-message">Post &amp; SMS</button>
    		</div>
    		<div style="width: 50%; float: right">
    			<button id="post-message">Post</button>
    		</div>
    		<div style="width: 50%; float: right">
    			<a href="#page-messages-list" id="btn-close-new-message" data-role="button">Cancel</a>
    		</div>
    	</div>
    </div>
    
  2. Then let’s add the JavaScript needed to enable that button – these are powerful native features we’re adding but look how few lines of code it takes:
    function postSMSMessage() {
    	forge.contact.select(function(contact) {
    		forge.sms.send({
    			body: $("#content").val(),
    			to: contact.phoneNumbers[0].value
    		}, function () {
    			alert("Message sent");
    			postMessage();
    		});
    	}, function() {
    		postMessage();
    	});
    }
    
    $('#post-sms-message').bind('click', postSMSMessage);

That’s it

In just a few short steps we’ve built an enterprise mobile app using Trigger.io and Apigee!

You can get started now by signing up for free.

The final code for the Messagee app with the native features described here is available on Github.

What’s next?

If you like what you’ve read and would like to keep going, here are a few things to try:

  • How about replacing the jQuery Mobile buttons to navigate between the feeds and settings view with a native tabbar component.
  • Try testing the app on an actual iOS device rather than just the emulator to see the phone contacts and SMS access live. That’ll require you to setup an Apple developer account and configure your provisioning profile and certificate in the Local config tab in the Trigger.io Toolkit

Any problems at any point? Check out the Trigger.io tutorials, the Catalyst debug tool or contact support@trigger.io for fast help.

Webinar: learn how to build and package for iOS devices

Join James Brady, Trigger.io CTO and the team next Wednesday for our second webinar back by popular demand!

This webinar is available to customers on our paid plans: sign up for a paid plan starting from a LIMITED-TIME OFFER of $19 for Go Iterate. This offer will be discontinued next week and the $19 rate will only be available with a year up-front payment after that.

How to setup provisioning profiles and certificates for building and packaging for iOS

Join us for a Webinar on October 10

Space is limited. Reserve your Webinar seat now at:
https://www1.gotomeeting.com/register/219522065

Details

Trigger.io co-founder and CTO, James Brady, demonstrates how to setup your Apple developer center and Trigger.io environment for building for iOS and packaging for App Store submission.

Title: Trigger.io Webinar: how to setup provisioning profiles and certificates for building and packaging for iOS
Date: Wednesday, October 10, 2012
Time: 10:00 AM – 10:45 AM PDT

After registering you will receive a confirmation email containing information about joining the Webinar.

System Requirements

PC-based attendees
Required: Windows® 7, Vista, XP or 2003 Server

Macintosh®-based attendees
Required: Mac OS® X 10.5 or newer
Mobile attendees
Required: iPhone®/iPad®/Android™ smartphone or tablet