Trigger.io Forge v2.5 Beta and iOS 10 Migration Guide

header-image

Hey Trigger peeps!

The iOS 10 launch is almost upon us and it’s time to release a beta for the next major Forge platform update.

Every year Apple blesses us with some changes and, being a conscientious cross-platform framework provider, we do our best to minimize the impact on your team.

The shift is usually transparent but this year a few fundamentals have changed and will require a bit of work to get your app ready for iOS 10:

  • iOS 10 now requires app permission dialogs to display a short usage description explaining why it requires access to device features such as the camera, contacts and calendar.
  • iOS LaunchImages are no longer organized according to device screen resolution. Instead, they are now assigned to size classes. This is good news as it means that the number of separate image files required for iOS have gone down from 13 to only 4.
  • Apple are getting serious about App Transport Security (ATS) and, as of 01 January 2017, its use will be mandatory for all App Store submissions. If you are using the request module and your backend infrastructure is still running HTTP or not configured to modern SSL standards your app will be affected.

Let’s take a quick look at each of these and the steps you will need to take to update your app for Forge Platform v2.5.x.

Module upgrades for iOS 10

If you are using any of the following modules you will need to make sure they are on the latest version:

Module Min Version Notes
calendar 2.8 Requires a usage_description entry
contact 2.10 Requires a usage_description entry
file 2.12 Requires a usage_description entry
tribr_multi_image_select 1.3 Requires a usage_description entry
launchimage 2.10 Requires new launch images
request 2.8 Requires App Transport Security (ATS) configuration
icons 2.7 Requires an iPad Pro icon (167x167px)
barcode 2.5 No app changes required

Add usage descriptions to your module configuration

iOS 10 requires app permission dialogs to display a short usage description explaining why it requires access to device features such as the camera, contacts and calendar:

The affected modules are:

  • calendar – Requires a usage description for Calendars access.
  • contact – Requires a usage description for Contacts access.
  • file – Requires a usage description for Camera, Microphone and Photo Library access.
  • tribr_multi_image_select – Requires a usage description for Photo Library access.

To configure the usage description for each of the modules you can fill in the usage_description field in the config section of src/config.json or the module configuration page in the Toolkit.

For example, to configure the calendar module you can either edit your app’s src/config.json file directly:

…or you can access the configuration through the Toolkit:

Toolkit Configuration

Please note that trying to your app on iOS 10 without a usage description will result in your app exiting immediately when its API methods are invoked!

iOS LaunchImage Size Classes

Apple introduced the concept of adaptive layout in iOS 8 already but, as hybrid devs, we haven’t really been affected as it only applied to native user interfaces.

With the release of iOS 10 however Apple are now requiring the use of Storyboards for App launch screens which means that the old system of having a different launch image for each device pixel resolution falls away.

Instead, there are now only four launch images, one for each Size Class defined in Apple’s adaptive layout framework.

When you App launches, iOS will select the corresponding launch image for the Size Class corresponding to the type of device running the app and its orientation.

Step 1: Upgrade the launchimage module to v2.10

Please make a note of the settings for your Android launchimage configuration before updating!

With the breaking changes for iOS we took the opportunity to do a long-needed re-organization of the module configuration schema and give the properties for Android their own section.

Step 2: Generate new launch images for each size class

The concept of size classes can be somewhat confusing at first but we can get away with only needing to remember that there are four size classes and they are applied as follows:

Size Class Device Landscape Portrait Image Size
width: Compact height: Compact iPhone x 1334 x 750px
width: Compact height: Regular iPhone, iPhone Plus x 1080 x 1920px
width: Regular height: Compact iPhone Plus x 1920 x 1080px
width: Regular height: Regular iPad x x 2732 x 2048px

Step 3: Configure the launchimage module

Finally, to configure the launchimage module you can either use the Toolkit or simply edit your app’s src/config.json file to look something like:

For more information please see the launchimage module documentation.

App Transport Security (ATS)

In a nutshell, App Transport Security (ATS) is a requirement that all iOS App communication with remote servers via the request module use the HTTPS protocol and conform to the following minimum requirements:

  • Encrypted using AES-128 or better.
  • SHA-2 for certificates with either a 2048 bit or greater RSA key, or a 256 bit or greater Elliptic-Curve (ECC) key.
  • Tansport Layer Security (TLS) protocol must be v1.2 or greater.
  • All connection ciphers must be using forward secrecy.

This only applies to communication via the request module. Network access from the iOS WebView is still exempt from ATS.

Step 1: Upgrade the request module to v2.8

If you are already using HTTPS conforming to Apple’s security requirements for all communication with your backend infrastructure this is all you’ll have to do.

If you are still relying on HTTP for communication with backend infrastructure you will want to read the next steps!

Step 2: Disable ATS for development

Unless you are ready to roll-out SSL across your backend by this afternoon you’ll probably want a way to disable ATS during development.

Please be aware that submitting any iOS App built with this setting enabled to the App Store after 1 January 2017 will result in immediate rejection.

To disable ATS you can either edit your app’s src/config.json file:

…or modify the configuration via the Toolkit:

header-image

Step 3: Make a plan to upgrade your backend infrastructure to HTTPS

The most common obstacle to upgrading server infrastructure is that the cost & difficulty of getting set up with SSL certificates can be a major barrier for projects.

If this is the case for your project we’d like to recommend you check out Let’s Encrypt. Let’s Encrypt is a free, automated Certificate Authority that operates with support from a large number of sponsors such as Mozilla, the EFF, Chrome and Cisco.

The next most common obstacle to upgrading to SSL is that sometimes we rely on servers that are not under our direct control.

For these cases Apple have communicated that they will allow some temporary exceptions to smooth the transition, but the rules moving forward are strict:

  • Most exceptions will need to be justified to Apple. This will likely lead to delays during the approval process and may end with your app being rejected.
  • NSExceptionRequiresForwardSecrecy will not require a justification for now. If used, this exception will be granted automatic approval. This is likely to change in future as forward secrecy becomes more widely spread.
  • NSExceptionAllowsInsecureHTTPLoads and NSExceptionMinimumTLSVersion will all require a reasonable justification for use.

Step 4: Configure ATS Exceptions (optional)

ATS Exceptions can be configured in the Toolkit via the “Configure iOS ATS” section of the request module configuration:

header-image

The fields should be self-explanatory but for more information you can read the request module documentation.

Don’t forget to re-enable ATS once you’ve configured any exceptions!

If you want to edit your app’s src/config.json file directly you may find the syntax is a little more obscure:

The format is an array of objects each with a domain and a set of one or more keys such as NSThirdPartyExceptionAllowsInsecureHTTPLoads that can be set to true for each kind of exception you want to add.

The example above corresponds to the Toolkit screenshot and it requests the following exceptions for all requests to the domain httpbin.org:

  • Override ATS for HTTP requests to httpbin.org, a domain we do not control. If we did control this domain we’d have used the NSExceptionAllowsInsecureHTTPLoads key instead.
  • Override the Forward Secrecy requirement for any HTTPS requests to httpbin.org.

You can find a full list of all the supported keys in Apple’s documentation.

Switch Your App To The Forge v2.5 Beta

If you’ve come this far your app should be ready for testing on the iOS 10 beta and there are just two more steps you’ll need to take:

Step 1: Install Xcode 8

If you haven’t already got it, grab the Xcode 8 GM Seed from the Apple Developer Site and install it into your /Applications directory.

Step 2: Change your App’s Platform Version

Open your app’s src/config.json file, locate the platform_version key and set it to v2.5.1beta-2:

…and you should be ready to go!

Finally

This is a Beta release so standard disclaimers apply :-)

You can keep track of further releases and known issues for this Beta on the Beta Release Notes page.

If have questions or run into issues please check out the Forge v2.5 Beta Topic on the community forum.

Have fun!

Changes at Trigger.io HQ

Dear Trigger.io customers,

Many of you will be familiar with our company history but here’s a brief synopsis for those who have joined us more recently:

2011: Amir Nathoo and James Brady start Trigger.io with the mission to make it possible for web developers to build native mobile apps using HTML5.

2012: Trigger.io becomes publically available for the first time and the team grows to include Connor, Tim and myself.

2013: Amir & James make the difficult decision to step back from the day-to-day running of the business.

2014: I take on the role of General Manager and make a promise to support our customers and ensure the long-term availibility of the Trigger.io service.

2015: The Trigger.io service shows positive month-on-month growth and we announce v2.4 of the Platform, featuring Crosswalk support.

Today, I’m extremely excited to announce another historic event:Trigger.io is changing ownership!

I have come to an agreement with Amir&James to purchase Trigger.io and have incorporated a new entity “Trigger Corp, Inc.” that will provide ongoing development and support of the Trigger.io service.

What does this mean?

There will be no changes to the availability of the Trigger.io service, subscription plans or customer support.

My promise to you remains unchanged and I will continue to make decisions that place our customers and the long-term availaiblity of the Trigger.io service first.

Where the impact of this change will be felt most is in the long run.

The Trigger.io service is no longer beholden to the priorities of external investors and is now wholly free to evolve according to the needs of our customers.

How this evolution proceeds is something I look forward to discovering with you in the years ahead!

The fine print

We’ve updated the following legal notices:

Our Terms Of Service: https://trigger.io/tos/

Our License Agreement: https://trigger.io/license/

Our Privacy Policy: https://trigger.io/privacy/

Whereas these agreements were previously with WebMynd Inc., they have now been transferred to Trigger Corp, Inc.

Trigger Corp, Inc. is a Delaware corporation and a wholly owned subsidiary of Zazpi (Pty) Ltd, Reg no: 2014/064494, a South African limited liability company with offices at:

35 Cockburn Rd

Glencairn Heights

Cape Town

South Africa 7975

No other changes have been made.

What’s next?

Earlier this year I promised that we’ll be providing an alternative to StackOverflow for community support and communication.

We’re live right now at: https://community.trigger.io and I hope you will join me there if you have any questions regarding the ownership change.

I’m also available via email at support@trigger.io if you have any questions or would like to set up a Skype call.

Finally, I’d like to thank Amir, James, Connor, Tim, David and the many good people who have worked with us over the years for the immense contribution they’ve made to the business and wish them the very best in their present and future endaevours.

All the best,
Antoine


Antoine van Gelder
Software Engineer @ Trigger.io

Open Source Spotlight: ngForge

header

Heya TriggerFolk!

This week we’re going to be taking a look at a great Open Source project started by Trigger.io user Andres Olave:

ngForge provides a set of idiomatic AngularJS wrappers for the
Forge modules that allow for easy & clean integration with Google’s AngularJS framework.

Here, in his own words, is Andres to tell you all about it…

An Introduction to ngForge

Angular & Trigger.IO are a great combination for developing mobile apps. Using either iOS or Crosswalk for Android it’s possible to build hybrid mobile apps we could only dream of in the past few years.

ngForge is a set of Angular wrappers for Trigger.io Forge modules with the aim to:

  1. Seemlessly switch between mobile & browser implementations
  2. Provide a AngularJS friendly experience:
    • Dependency Injection not globals.
    • Promises not callbacks.
    • $http API equivalency for the request module.
  3. Provide a basis for use in modern JS development:
    • Use the browser as the primary development environment – because there are many commonplace, well supported, free tools.
    • Don’t require trigger.io builds in the browser environment.
    • Be optimised for standard JS build tools: Grunt, Gulp, etc.
  4. Allow services to be configured & reconfigured on the fly in browser mode.

How it works

Using AngularJS emphasises the use of dependency injection. The typical use is to inject services into controllers, or the Angular’s $http service into services.

Let’s say you are building a web app with a service that has a saveLocally method:

With ngForge you can now instead use $forgePrefs which delegates to the forge.prefs module when running as a mobile app, and to localStorage when running in a browser.

For example, we can inject it into any service implemented in Angular:

This way AngularJS allows us to implement the service before it provides the $forgePrefs service and ngForge can detect whether it is running in a mobile environment or a browser.

  • if it’s a mobile environment ngForge delegates all service calls to the Trigger.io module.
  • if it’s a browser environment ngForge:
    • returns mock data – for example $forgeContacts returns mock data.
    • and/or implements a mock version of the module – for example $forgePrefs delegates to localStorage in browser mode.

In fact even if ngForge doesn’t mock out a method, it is still able to delegate service calls to Trigger.io in mobile environment mode.

Promises NOT callbacks

The Forge module API’s are currently still based on Node.js-style callbacks which often lead to callback hell and are not a natural fit with Angular’s Promises-based approach to deferred and asynchronous computation.

ngForge extends the Forge Module API’s with support for Promises which allows you to use them in the same way as you would in your regular Angular app.

For example, using standard Trigger.io you’d access forge.prefs like this:

With Promises, it instead becomes:

Much cleaner wouldn’t you agree?

Service Configuration

In browser mode, ngForge services can be configured by using Angular config methods. You may want to configure:

  1. Mock data: for example the mock contact book data used by $forgeContact, or
  2. Implementation configuration, for example what key to store data under when using the localStorage version of $forgePrefs.

Each service documents what is configurable. Here is an example config:

Using $forgeHttp instead of the forge.request module

Trigger.io’s forge.request module offers cross-origin access and native performance for HTTP request.

However, the request module’s API is based on a subset of the JQuery API and if you are using Angular it would be preferable to replicate the $http service API. (See the Angular $http service documentation for more details.)

This is what the $forgeHttp API looks like:

The following methods are not implemented as yet:

Additionally, the config object supports the following properties:

  • params{string|Object}: Params that are not already query strings are serialized as query strings and appended to the URL.
  • data{Object}: Data to be sent as the request message data. If it’s a get request then it is serialized as a query string and appended to the URL.
  • headers{Object}: Map of strings representing HTTP headers to send to the server.
  • cache{boolean|Object}: A boolean value or object created with $cacheFactory to enable or disable caching of the HTTP response.
  • timeout{number}: timeout in milliseconds
  • responseType{string}: See XMLHttpRequest.responseType.

All these methods return a promise that support the standard methods: then, catch & finally methods that take function with a single argument of the http response object. It also supports the deprecated success & error methods for handling responses. See the Angular Promises Documentation for more detail.

Results of GET are, by default, not cached. Caching is supported in the same way as in $http, that is, by default using simply the value true, or by an instance of $cacheFactory. (See the Angular $http caching documentation for more information)

We also support interceptors that allows you to implement cross cutting concerns for requests or response. Simply add interceptors to the $httpProvider as in the Angular documentation.

The future

AngularJS is a 3rd generation web framework but is already being replaced by 4th generation frameworks such as Angular2 & ReactJS. These feature simpler programming models, ECMAScript 2015 (or even TypeScript) & vastly superior performance.

There are some exciting Trigger.io updates coming that will make it possible for us to update ngForge with support for Angular 2 and Observables and we are planning broad framework support for ngForge in the near future.

I hope you enjoyed reading this quick introduction to ngForge.

Check the project out on GitHub and if you have any questions please feel free to drop me an email: andres@sportwize.me

Fork me on GitHub

Big up to 7cups.com

7cups banner

Trigger.io users are people we are proud to be associated with! The recent growth of 7cups.com is a testament to the kind of skill and effort we regularly encounter amongst the Trigger.io community.

The aim of the 7cups initiative is to provide online emotional support in a world with “an immense love deficit”. From their website:

7 Cups of Tea is an on-demand emotional health and well-being service. Our bridging technology anonymously & securely connects real people to real listeners in one-on-one chat.

Anyone who wants to talk about whatever is on their mind can quickly reach out to a trained, compassionate listener through our network. We have hundreds of listeners who come from all walks of life and have diverse experiences.

Glen Moriarty, Founder and CEO, is a psychologist who is passionate about the Internet’s power to help people lead better lives. He is joined by a team of professionals with a wide range of capabilities, from counselling and social work to engineering and web design.

As well as a running a succesful website and an app which is available on both IOS and Android, 7cups also maintains an active reddit community, and encourages academic research interest through their Open Research Platform

Working with Trigger.io

header

We asked Ezra Morse, the Full Stack Engineer at 7 Cups, to tell us a little about working with Trigger.io as a platform for development.

Q – Why did 7cups choose to work with Trigger.io?

As the world’s largest emotional support network, 7 Cups is about bringing people together. The last thing we need is to sacrifice dev time on hunting for platform bugs, solving plug-in conflicts and triaging build issues.

Trigger.io allowed us to swiftly convert a legacy, first-generation mobile website into a reactive one-page application with the native plug-ins we needed, while keeping our focus where it should be: on user experience and our community.

In the end, we were able to produce a lean, performant app that isn’t mired by stability issues or the long iterative cycles characteristic of a fully native app. We finally have a stable and evolving application that better positions us to reach more people in need.

Q – What is your overall experience of hybrid development in today’s market?

To be honest, Trigger.io wasn’t our first choice on this project. Let’s just say that our first pass at modernizing our app could be described as wanting to have our cake and eat it too.

We bought into too many promises and tried to relegate far too much functionality (UX included) to the native device, thereby leaving us with a slow, bloated hybrid-application that would crash as often as freeze. So we went from an extremely bad scenario where our concerns about speed and the memory footprint of the app simply didn’t allow us to take any chances.

If we wanted to keep our app hybrid, a cordova-flavor just wasn’t going to give us the lean and stable app we wanted to share with the world; we simply could not afford to have performance issues continue to stand in between the people on each end of the device.

In summary, I feel a lot of the hybrid approaches fail to keep it simple on both the application level and the build process, and thereby, the end product suffers. As hybrid developers, should we really need to focus on too much more than what is going on inside that single webview?

7cups screenshot

Thanks Ezra, for making the time to speak to us and fill us in on your development process. We look forward to many more collaborations in the coming months.

From everyone at Trigger.io, keep up the good work!

Discover Trigger.io Forge v2.4: Runtime App Permissions

runtime-app-permissions

Following our announcement of Trigger.io Forge Platform v2.4 earlier this month I’m pleased to present, as promised, our first article about the new features that landed with this release.

Today I’ll be covering the support we’ve added for managing iOS and Android runtime permissions and showing you:

  • How you can use our Runtime Permission features to increase your app install rates.
  • How to dynamically adapt your app to the permission preferences of your users.
  • How to save your users from an epic journey into their device preferences if they didn’t grant an app permission the first time round.

What Are Runtime Permissions?

Both iOS and Android apps execute inside a sandboxed environment which places hard restrictions on the device resources accessible by your app.

The goal of this sandboxed environment is to limit the amount of mischief a malicious or misbehaving app can inflict on your device.

In a perfectly secure world, apps would not be able to access any resource outside of their own environment. Unfortunately this would also mean we could not develop apps that make use of device features such as cameras, photo albums, geolocation or notifications.

The compromise then is for apps to explicitly request the user to grant specific “device permissions” to the app.

This informs your users of the device capabilities they are entrusting to your app, but it also places the onus on you, the app developer, to give the user a reason to trust you!

On older versions of Android, and a lesser extent iOS, the user was forced into an all-or-nothing decision about whether to grant access to resources during the initial app installation process.

Given how long the list of requested device permissions can get this unfortunately results in many users responding to such a big “ask” by simply not installing the app.

It’s a little hard to win your user’s trust if they’re not running your app in the first place, right? :-)

Luckily, with the release of Android Marshmallow, Forge v2.4 and our new forge.permissions module, users no longer have to make an upfront leap of faith as it’s now possible to incrementally request device permissions at runtime on both iOS and Android.

This helps your users feel more in control, while simultaneously giving you a chance to make a powerful case for the benefits of trusting you with their device.

Forge and Runtime Permissions

Up till now, the way we’ve dealt with runtime permission requests on iOS and Android Marshmallow has been to automatically trigger the system permission request dialog whenever a module calls a native API requiring that permission.

For example:

Which results in an app flow that looks like this:

Default Runtime Permissions Flow

The good news is that this behaviour has not changed with the release of v2.4 and if you’re satisfied with the way your app works you can stop reading right now. :-)

However, an important gotcha to be aware of is that both Android and iOS devices have the following behaviours hardcoded into their operating systems:

  • On Android: When a user clicks “No” the first time they are asked, they will have the option to prevent the app from making subsequent requests.
  • On iOS: When a user clicks “No” the first time they are asked, the app will be prevented from making subsequent requests.

What this means is that once a permission request has been denied, there is a high likelihood that the only way the user can grant that permission in future is by digging in their device’s System Preferences.

Or to put it another way, once a permission request has been denied (iOS) or disabled (Android) all future requests to forge.contact.selectAll() will only ever trigger the error callback.

Not an ideal situation, but all is not lost!

We created the forge.permissions module to address precisely this problem and to help you get more control over when and how permission requests are presented.

How To Use The forge.permissions Module

Step 0: Update your platform version and modules to the latest versions

To use the forge.permissions module you need to be on at least platform version v2.4.1 and at least the following module versions:

module version
contact 2.9
calendar 2.7
geolocation 2.4
camera 2.3
file 2.11

Step 1: Add the permissions module to your app

In the modules section of your app’s src/config.json file add the module as follows:

Alternatively, launch the Trigger.io Toolkit and navigate to the Modules section of your app and search for the permissions module.

Step 2: Check Whether You Need To Make A Permission Request

Before we actually request a permission we first need to check whether the user has already granted the permission or not.

Once we know this, we will know whether we will need to initiate a permissions request or whether we can proceed normally with our app.

The API that will give us this information is: forge.permissions.check()

So, let’s say we have a feature that needs to use the forge.contact.selectAll() API which relies on the forge.permissions.contacts.read permission.

To perform the check you then simply do something like this:

You can find a list of modules and the permissions they require by checking out the Permissions Module Documentation

When granted is true you can simply continue with your app flow and when it is false you can take the steps needed to make a permission request of the user.

Step 3: Request Permission

Now that you know how to check for a permission, you will need to know how to handle the case where the permission has not yet been granted.

To do this we’ll use the forge.permissions.request() API:

Note that, although the user will be presented with the permissions popup when you call forge.permissions.request() this is slightly deceptive.

The dialog the user will see is not generated by the device operating system but rather by the module. If the user clicks “No” in this dialog any future requests for the permission will no longer fail automatically.

It is only after the user has clicked “Yes” that the real system dialog is presented.

With this code, your user will be asked for permission when you call forge.permissions.request() and you then have the option to take an alternate action if the user did not grant the request.

All Together Now

Now that you know how to check for and request permissions, let’s look at an example of how you could put all the pieces together for a smooth user experience in your app:

Custom Runtime Permissions Flow

There are a couple of advantages to doing it this way:

  • The call to forge.permissions.check() provides a logical place to fork your app logic depending on whether the user has already granted the permission or not.
  • By linking the forge.permissions.request() call to a user action which explicitly relates to the permission being requested you greatly reduce uncertainty in the user’s mind about the purpose of the permission request.
  • Being able to check the outcome of the permission request you’re able to easily update your application and explain to the user why you need access to that permission.

That said, this is only one example of how to do it and you may find your application needs a different approach.

For some great ideas on increasing Runtime Permissions conversion I highly recommend you check out this article by Brenden Mulligan: The Right Way To Ask Users For iOS Permissions

Finally, don’t forget to check out the documentation for the Permissions module!

Conclusion

I hope you enjoyed this quick journey through the iOS & Android Runtime Permissions models, how Forge handles permissions by default and the tutorial on how to use the forge.permissions module to implement custom handling of runtime permissions.

As always, please hit us up at support@trigger.io if you have any questions or comments!

Trigger.io Forge v2.4.1 – Intel Crosswalk, Runtime App Permissions & Android Studio support

crosswalk-project-logo

Towards the end of last year I wrote about our upcoming 2.4 release and today I’m happy to announce its arrival!

We’ll be covering the individual features landing with v2.4.1 in more detail over the coming weeks but let’s take a quick look at the highlights:

New forge build target: Crosswalk

crosswalk-project-logo

With the release of Trigger.io Forge v2.4.1 our crosswalk target has finally graduated from the beta branch and has been declared ready for production use.

Anyone developing hybrid apps for Android will be familiar with the myriad of compatibility issues that pop up when you start testing your app against different versions of Android.

Android versions before v4.4 shipped with a proprietary System WebView which lacked many basic HTML5 features, performed poorly and suffered from compatibility issues.

Android versions after v4.4 use whichever version of the Chrome-based System WebView was current when the device shipped.

The very latest versions of Android now periodically update the System WebView when newer versions of Chrome are released but this creates new problems when System WebView changes suddenly render your code inoperable.

The Crosswalk Project resolves these fragmentation issues by integrating the open-source Chromium WebView with your app.

By using our crosswalk target you can now use the latest web standards across all Android devices and control when you want to upgrade your app to support newer Chromium releases.

For more background information please read: Solving Android Fragmentation with Trigger.IO Forge and Intel’s Crosswalk

Runtime App Permissions

runtime-app-permissions

With the release of Trigger.io Forge v2.4.1 and our new forge.permissions module we fully support the new Android Runtime Permissions framework and give you complete control over when and how your app makes native permission requests.

By default, all forge module API’s will now only make a request to the user for permissions when the API is called and not during application startup.

While this has the benefit of not requiring a user to make an “all-or-nothing” decision when they install the app it still has the downside that it can quickly get quite complex to handle situations where users deny permission requests.

By using the forge.permissions module you have fine-grained control over permission management, can easily handle cases where permissions are denied and greatly increase the probability that users will grant your app the permissions it requires.

Android Studio Support

android-studio-logo

With the release of Trigger.io Forge v2.4.1 we have migrated our cloud compilation service to the Gradle build system and updated our Forge Native Module SDK to support the Android Studio IDE.

While we’re huge fans of the IntelliJ IDEA-based Android Studio the primary motivator for this shift came about because Google have now officially deprecated Eclipse for Android development.

This means that all development and official support for the Android Developer Tools (ADT) in Eclipse have now ended. Specifically, this includes the ADT plugin as well as the Android ant build system.

We’ll continue to support native module development with ant and Eclipse for as long as practical but you may be pleasantly surprised at how much easier Native Module development can be with Gradle & Android Studio!

Upgrade your app to Trigger.io Forge v2.4.1

You can find more information in the v2.4.1 release notes but the following steps should get you going:

Step 1 – Upgrade your platform version

Open your app’s src/config.json file in your favorite text editor and set the platform_version key to v2.4.1 as follows:

Step 2 – Check your module versions

Due to changes introduced by the new runtime permissions framework in Android 6.0 Marshmallow (API level 23) you may need to update your modules.

If you are using any of the following modules please ensure you are on the latest versions:

module version
contact 2.9
calendar 2.7
geolocation 2.4
camera 2.3
file 2.11

Step 3 – Develop!

To build your app against the new crosswalk target you can simply run:

Our android and ios targets remain unchanged.

Crosswalk options

We’ve also added two new optional configuration keys to src/config.json that control Crosswalk behaviour:

If you are experiencing rendering issues on some devices the disable_gpu_rasterization setting will work around bugs in their OpenGL implementations.

The disable_pull_to_refresh_effect setting allows you to disable Crosswalk’s default behaviour of refreshing the screen when the user “pulls-down’ on a page.

Check the documentation for more information.

In Conclusion

v2.4.1 is a massive release for us and represents the culmination of almost a year’s worth of engineering effort.

The complexity of integrating a new Forge runtime while simultaneously migrating our Android build system over to Gradle has been non-trivial and I’d like to give a special shout out to:

  • The v2.3beta branch testers who tirelessly hammered on each release, reported bugs and – often – contributed hours of their time to help us track down and reproduce issues. Y’all know who you are, thank you!

  • The Crosswalk team @ Intel. Crosswalk is beautifully engineered so it was rare that we got stuck, but when we did you were there with rapid responses, answers and marketing support!

Finally, if you run into any issues with v2.4.1 or have any questions about this release please don’t hesitate to get in touch with us at support@trigger.io.

Winding down for the year

Dear Trigger developers,

Well here we are again. The year is drawing to a close, there’s a definite festive spirit in the air and I’m wondering where the time has gone.

2015 has been a landmark year for Trigger.io and I’m pleased as punch to share that we are once again showing stable month-on-month growth. This marks the completion of the transitionary period from externally-funded startup
to a sustainable business and is a reliable indicator that we will continue to be here for all of you, now and in the future.

We wouldn’t have come this far without the willingness of the Trigger.io community to bet on us. So from our oldest customers who have been with us since we were in beta to our newest customers who only joined this week:

“Thank you, you rock!”

I’m not going to get into details on the engineering work we have planned for the new year as I covered it last month. Instead, I’d like to talk about the softer side of the platform.

Over the last couple of weeks I’ve heard from many of you with suggestions and questions about what 2016 holds in store. The dominant theme in all these conversations have been that it’s time for us to put energy and
resources into the Trigger.IO community.

Based on these conversations, some of the things we’d like to look at are:

  • Opening up the development processes around our open source native modules.
  • Making the knowledge accumalated in our support systems publicaly available.
  • Alternatives to stackoverflow.com for community support and communication.
  • Re-organising tutorials and other how-to information on our blog and website for discoverability.
  • Rebooting a sadly lapsed tradition of showcasing the work our customers are doing.

If you’ve also got ideas you’d like to share, please get in touch.

Finally, our offices will be shutting down on the 15th of December 2015 and will open again on the 7th of January. We will however have someone checking in on support during this time in case any emergencies come up.

Wishing everyone a fantastic holiday to recharge for the coming year, I have a feeling it’s going to be a great one!

All the best,
Antoine

Ch-ch-ch-ch-changes!

The road to 2.4


Update

v2.3.2beta-1 has now been pushed to production. Please check the changelog for details.


If you were to dig through our platform release notes you’d notice that it’s been nearly 18 months since the last major version number update to the platform.

During this time we’ve released 16 minor platform updates to help you navigate through:

  • Two major iOS software and hardware releases.
  • Support for writing custom native modules using the Swift programming language.
  • Four major Android API releases.
  • Beta support for Intel’s Crosswalk web runtime.
  • More App Store rule changes than anyone (including Apple) keeps track of.

I’ll be honest, surfing this tsunami of change isn’t always fun but once in a while I’ll come across something that reminds me of the value of what we do:

Legacy

I don’t want to get into a rant about the kind of thinking responsible for this state of affairs but I would like to place it in perspective:

If, twenty years ago, you compiled a C/C++ application for the Windows WIN32 API using C/C++ there is every chance that your original binary executable will still work on Microsoft’s latest Windows 10 release.

Binary compatibility is unfortunately out of our reach and it’s still too early to tell if Trigger.IO will match Microsoft’s track record but we’re certainly giving it the old college try.

Simply put:

If you shipped a HTML/CSS/JS Trigger.IO app in 2012 chances are very, very good that it will still run on the latest versions of iOS and Android without requiring anything more from your side than a forge build ios && forge build android.

Your legacy? It matters to us.

Platform Version 2.4

The road to 2.4 has been long and I know a lot of you have been patiently waiting for the Crosswalk support from our beta branch to finally make its way to stable release.

Well, I’m pleased to announce that today we finished the last major piece of work that has been holding this back!

Basically, we had two major blockers:

  1. The Ant build system had problems dealing with application resources from multiple external libraries which led to all kinds of horrible bugs when using Crosswalk with some native modules.
  2. There was no simple way to test custom native modules in both the Android and Crosswalk environments.

The resolution wasn’t simple but, ironically, it came in the form of the kind of announcement we’d normally dread:

As of next year Google will no longer be supporting Eclipse or the Ant build system.

It’s taken the better part of two months, but we’ve finished migrating our Android build system over to Gradle and it has brought a wealth of cool stuff, including:

  • Android Studio support for custom native module development.
  • Support for using .aar packages directly from your custom native modules.
  • Support for including module dependencies directly from Maven and other repositories.
  • Support for debugging modules against both Android and Crosswalk.
  • Support for building x86 and 64-bit packages for Android.
  • No more module resource conflicts!

We’ll continue to support Eclipse for as long as possible, but you may be surprised how easy (and pleasant!) it is to move your module development over to Android Studio.

Release Timeline

Migrating the Android build system is a massive change and, no matter how much testing we do on our side, there is still potential for things to break.

We’re now officially in feature-freeze for v2.4 and will be pushing v2.3.2beta-1 to production early next week.

Depending on how much feedback we get from y’all at support@trigger.io we’re hoping to pull the trigger on stable release before the end of the year.

Trigger.io Forge support for iOS9 and OSX “El Capitan” is ready!

Trigger.io Forge is ready for iOS9 and OSX El Capitan

If you caught last night’s Apple event you’ll know Apple have finally pushed the GM releases for Xcode 7, iOS 9 and OSX El Capitan.

The GM release is what Apple will be shipping to the general public in a week’s time so, if you haven’t been following along during the Beta-test phase, now is the time to make sure your app is ready for iOS 9.

We’ve been working towards this moment since the initial announcement in June and are pleased as punch to announce that Trigger.io supports iOS9 and OSX El Capitan as of platform version v2.2.16.

To get your app running on iOS 9 all you’ll need to do is take the following steps:

1. Upgrade your Xcode to version 7

You can grab the GM seed from the Xcode Developer Center or, if you don’t mind waiting a week, download the update from the App Store.

2. Update your iOS device to iOS 9 (Optional)

If you don’t want to wait till next week, you can head over to the iOS Developer Center and grab the install image.

We also support the new iOS 9 simulator in Xcode 7 so this step is not necessary if you want to hold off on upgrading your hardware immediately.

3. Update your app to platform version v2.2.16

To update your app to the latest platform version open up the Trigger.io Toolkit, navigate to your app config and click on the Change version button:

Toolkit App Config

In the popup dialog, simply click the Switch to v2.2.16 button:

Toolkit App Version

That’s it!

Feedback

Sometimes there are minor teething issues with GM releases as Apple often adds a bunch of new stuff that wasn’t present in the betas. So please, if you run into any problems or have questions, don’t hesitate to let us know at support@trigger.io and we’ll be all over it!

Important note for Ionic/Angular users:

We’ve heard reports that UIWebView for iOS 9 introduced a breaking change that can cause issues for apps that rely on the semantics of window.location.

If your app uses the Angular $location service you can find a patch and more information here:

http://blog.ionic.io/ios-9-potential-breaking-change/

Shipping Code with Trigger.io Forge
Part 2: Choose Your App Architecture

header

Welcome to the second part of our new monthly blog series, “Shipping Code”!

In the previous instalment we took a look at the various strategies available for developing your mobile app. We covered Mobile Web Apps, Native Apps and Hybrid Apps.

For the remainder of the series we’ll be leaving Web & Native Apps behind to focus purely on Hybrid App development because that’s what we do here at Trigger.io!

How should I structure the architecture of my Hybrid app?

Now that you’ve decided on a Hybrid App for your development strategy the next question you’ll face is how to structure your code.

There are a variety of architectural patterns in common use and the approach you decide on will depend largely on the type of application you are developing.

In general terms we can break the patterns down into the following broad categories:

  • Single Page: The “Single Page” architecture is the most common pattern found with hybrid apps. This architecture takes the form of a single index.html page which serves as the containing document for the app. Content and resources are then dynamically loaded into this page via Javascript.
  • Static Site: The “Static Site” architecture is similar to a traditional web site. The app consists of multiple HTML pages which are linked together via hyperlinks.
  • Hosted Iframe: In the “Hosted Iframe” architecture the app takes the form of a single index.html page with an embedded <iframe/> tag which contains a remote web site.

Let’s take a closer look at each of these patterns:

Option 1: Single Page

single-page architecture

The trend over the last ten years has been towards so-called “Single Page” apps which move responsibility for rendering the application UI from the server towards client-side HTML and Javascript.

This approach brings a number of advantages, most importantly:

  • Speed: With traditional server-side architecture there is a significant delay after each user interaction as a request first has to be sent to the server and any UI updates have to be returned to the user.
  • Simplicity: Rather than managing complex application and UI state on the server for each user, that state can now be maintained locally on the user’s device.

See the Wikipedia page for a thorough discussion on Single Page applications.

While the entire app is hosted on a single page local to the device the backend web server still plays a role. Most commonly, a RESTful JSON interface will be exposed on the web server which provides the following services to your app:

  • Implementing application logic for the data endpoints used by the application.
  • Retrieval and persistence of application state.
  • User authentication and authorisation.

The components of a Single Page App

The exact structure of your Single Page app will depend largely on whether you are using vanilla HTML/Javascript/CSS or one of the many Third-party Single Page app frameworks to implement your app.

That said, most Single Page apps will contain some combination of the following elements:

  • A src/index.html file containing:
    • The basic app layout
    • Imports for your Javascript code.
    • Imports for your CSS code.
    • Imports for any Third-party Javascript & CSS libraries.
  • One or more src/templates/*.html files containing:
    • Templates for your views
    • Templates for your UI components
  • One or more src/js/*.js files containing:
    • Your application logic.
    • Third-party libraries and frameworks.
  • One or more src/css/*.css files containing:
    • Rules for the look & feel of your application.
    • Third-party CSS frameworks.
  • Binary resources such as images, audio or video.

Third party Single Page App Frameworks

There are a large number of Third-party Single Page libraries and frameworks available that simplify the task of structuring and developing your Single Page app.

While the borders aren’t always clear-cut, we can divide Single Page app Frameworks into two broad categories:

  • Application Frameworks: Provide functions to handle app navigation (routing), template rendering, user event processing and data-binding between the application’s data and user interface elements.
  • User Interface Frameworks: Provide User Interface elements such as buttons, lists, popovers, transitions etc. that mirror the functionality (and sometimes also the look & feel) of native apps.

Some examples for each type of framework are:

Application Frameworks

User Interface Frameworks

Figuring out which framework will work best for your purposes can be a complex endeavour and is a topic we’ll cover in-depth with our next instalment.

Pros for Single Page Architecture

  • Provides a fluid user experience with complex interactions comparable to Native Apps.
  • It’s much easier to develop complex Single Page apps than traditional server-based applications.
  • There is a huge selection of high-quality Third-party Single Page app frameworks available.
  • You can access all forge.* API’s from your app.
  • Users can still use your app even if they are not connected to the Internet.

Cons for Single Page Architecture

  • If you have not developed Single Page apps before you’ll have to go through a mild learning curve to get comfortable with the concepts.
  • If you want to use functionality from your existing website you may need to implement a RESTful JSON interface for transferring data between your app and backend services.

Option 2: Static Site

static architecture

This approach can work well with simple apps that require interaction with native device features and consist primarily of statically served web pages, images and other resources.

The components of a Single Page App

Structured in the same way as a website serving static content, your hybrid app contains a separate HTML file for each page in the site.

While it’s tempting to think you could take any existing website and easily convert it to a web app in this way it’s worth remembering that this will only work with the very simplest of sites as you will no longer be able to rely on the server for processing user interaction or other forms dynamic processing.

Pros for Static Site Architecture

  • It can be the easiest way to transfer content from an existing site to mobile.
  • You can access all forge.* API’s from your app.
  • Users can still use your app even if they are not connected to the Internet.

Cons for Static Site Architecture

  • Maintaining a complex application as a set of HTML pages can quickly become overwhelming.
  • If your existing site features complex server interactions you will have to rewrite those as client-side Javascript and expose a RESTful JSON interface on your server.

Option 3: Hosted Iframe

hosted iframe architecture

If you have an existing web app which does not require complex interactions with native device features or functionality you can simply “host” it inside a hybrid app by using an <iframe /> HTML tag inside your app’s main page.

An important factor to bear in mind is that you cannot directly access forge.* API’s from the remote site’s pages.

If you would like to make use of native device features you will need to bridge the calls from the remote page to your app’s src/index.html page by using the window.postMessage() and window.addEventListener() API’s to marshall communication between the hosted site and the parent hybrid app.

A Simple Example

The code for the remote page, hosted on the remote server:

The code for your app’s src/index.html page:

Pros for Hosted Iframe Architecture

  • You can re-use portions of your existing site’s functionality.
  • You can decide which portions of your app will be implemented locally and which portions will re-use existing site functionality.

Cons for Hosted Iframe Architecture

  • You will need to apply responsive design to your remote content or it may look odd on mobile devices.
  • Accessing device functionality through the forge.* API’s is more complex as function calls will need to be marshalled through the iframe’s parent window.
  • Users may not be able to use your app unless they are connected to the Internet.

Conclusion

All of the above options are supported by Trigger.io Forge but we will be spending the bulk of our time in this series focusing on the Single Page App Architecture (Option 1) as it has emerged as the most practical and popular pattern for hybrid app development.

In the next instalment of this series we’ll be taking a closer look at some Single Page app frameworks and the problems they solve.

Until then, if you have any questions about the material we’ve covered so far, we’d love to hear from you at support@trigger.io!