Ember Integration

I have been spending a little time with Capacitor over the last week, looking at integrating Ember and how easy it was. From a fresh install there are only a few simple tasks needed to get everything fully working, including live reload.

  1. Install New Ember App
    ember new ember-capacitor-app

  2. Build Ember App to generate /dist folder

cd ember-capacitor-app
ember build
  1. Install Capacitor
    npm install --save @capacitor/core @capacitor/cli

  2. Initialize Capacitor where we set the Ember dist folder
    npx cap init ember-capacitor-app com.example.app --web-dir dist

  3. Edit capacitor.config.json to add Ember Live Reload

{
  "appId": "com.example.app",
  "appName": "ember-capacitor-app",
  "bundledWebRuntime": false,
  "webDir": "dist",
    "server": {
      "url": "http://localhost:4200",
      "allowNavigation": [
        "example.org",
        "*.example.org"
      ]
    }
}
  1. http://localhost:4200 doesn’t work on Android, so you need to be using the IP address of the computer where you are serving ember from instead. localhost works for iOS. When building for production the server:url will need to be removed

  2. For Android you will need to allow cleartext / Ember to be server over http as otherwise Android 9 doesn’t like it, you can remove this setting on production build, edit android/app/src/main/AndroidManifest.xml and add usesCleartextTraffic="true" to application

  3. Install ember-cli-content-security-policy and then setup CORS in your Ember config/environment.js files, not needed to see initial serve / builds working

  4. I haven’t tried this yet, but for Cordova it was best to set the Ember config/environment.js rootURL: ‘’ and locationType: ‘none’ for best results, not using these at the moment and it still works fine.

rootURL: '' OR '/',
locationType: process.env.CORBER ? 'none' OR 'auto',

Below are some quick bash scripts I have setup to automate the process of installing, serving and building for iOS and Android. Works on OSX, put in the ember-capacitor-app folder and run instead of all the steps above.

ember-capacitor-init.sh

#!/bin/bash

# Create Dist Folder
# ----------------------------------------------------------------------------------------------------
if [ ! -d dist ]; then
    echo "Building Ember"
    ember build
fi

# Add Capacitor
# ----------------------------------------------------------------------------------------------------
echo "Installing Capacitor"
npm install --save @capacitor/core @capacitor/cli

# Initiate Capacitor
# ----------------------------------------------------------------------------------------------------
echo "Initiating Capacitor"
npx cap init ember-capacitor-app com.example.app --web-dir dist

# Ember Live Reload
# ----------------------------------------------------------------------------------------------------
node <<EOF
    const fs = require('fs');
    let rawdata = fs.readFileSync( 'capacitor.config.json' );
    let data = JSON.parse(rawdata);
    if ( !data.server ) {
        data.server                 = {};
        data.server.url             = "http://\${ip}:4200";
        data.server.allowNavigation = [ "*.example.org" , "example.org" ];
    }
    fs.writeFileSync( 'capacitor.config.json' , JSON.stringify( data , null , 4 ) );
EOF

# Add iOS
# ----------------------------------------------------------------------------------------------------
if [ ! -d ios ]; then
    echo -n "Add iOS (y/n)? "
    read answer
    if [ "$answer" != "${answer#[Yy]}" ]; then
        ./ember-capacitor-add-ios.sh
    fi
fi

# Add Android
# ----------------------------------------------------------------------------------------------------
if [ ! -d android ]; then
    echo -n "Add Android (y/n)? "
    read answer
    if [ "$answer" != "${answer#[Yy]}" ]; then
        ./ember-capacitor-add-android.sh
    fi
fi

ember-capacitor-add-ios.sh

#!/bin/bash

# Add iOS
# ----------------------------------------------------------------------------------------------------
if [ ! -d ios ]; then
    echo "Adding iOS"
    npx cap add ios
else
    echo "iOS Already Exists"
fi

ember-capacitor-add-android.sh

#!/bin/bash

# Add Android
# ----------------------------------------------------------------------------------------------------
if [ ! -d android ]; then

    # Add Android
    # ------------------------------------------------------------------------------------------------
    echo "Adding Android"
    npx cap add android
    
    # AndroidManifest - Uses Cleartext Traffic
    # ------------------------------------------------------------------------------------------------
    echo "Updating AndroidManifest.xml"
    perl -i -pe's/<application/<application\n\t\tandroid:usesCleartextTraffic="true"/' android/app/src/main/AndroidManifest.xml
    
else
    echo "Android Already Exists"
fi

ember-capacitor-serve-ios.sh

#!/bin/bash

# Build Ember
# ----------------------------------------------------------------------------------------------------
echo "Building Ember"
ember build --environment=development

# Store Config File
# ----------------------------------------------------------------------------------------------------
echo "Reading capacitor.config.json"
config=`cat capacitor.config.json`

# Set Local IP Address For Live Reload
# ----------------------------------------------------------------------------------------------------
ip=$( ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' )
echo "Setting Live Reload To:" $ip
perl -i -pe's/\${ip}/'$ip'/' capacitor.config.json

# Sync Distribution
# ----------------------------------------------------------------------------------------------------
echo "Syncing Distribution"
npx cap sync ios

# Reset Config File
# ----------------------------------------------------------------------------------------------------
echo "Resetting capacitor.config.json"
echo "$config" > "capacitor.config.json"

# Open Xcode
# ----------------------------------------------------------------------------------------------------
echo "Opening Xcode"
npx cap open ios

# Serve Ember
# ----------------------------------------------------------------------------------------------------
ember serve

ember-capacitor-serve-android.sh

#!/bin/bash

# Build Ember
# ----------------------------------------------------------------------------------------------------
echo "Building Ember"
ember build --environment=development

# Store Config File
# ----------------------------------------------------------------------------------------------------
echo "Reading capacitor.config.json"
config=`cat capacitor.config.json`

# Set Local IP Address For Live Reload
# ----------------------------------------------------------------------------------------------------
ip=$( ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' )
echo "Setting Live Reload To:" $ip
perl -i -pe's/\${ip}/'$ip'/' capacitor.config.json

# Sync Distribution
# ----------------------------------------------------------------------------------------------------
echo "Syncing Distribution"
npx cap sync android

# Reset Config File
# ----------------------------------------------------------------------------------------------------
echo "Resetting capacitor.config.json"
echo "$config" > "capacitor.config.json"

# Open Android Studio
# ----------------------------------------------------------------------------------------------------
echo "Opening Android Studio"
npx cap open android

# Serve Ember
# ----------------------------------------------------------------------------------------------------
ember serve

ember-capacitor-build-ios.sh

#!/bin/bash

# Build Ember
# ----------------------------------------------------------------------------------------------------
echo "Building Ember"
ember build --environment=production

# Store Config File
# ----------------------------------------------------------------------------------------------------
echo "Reading capacitor.config.json"
config=`cat capacitor.config.json`

# Ember Live Reload
# ----------------------------------------------------------------------------------------------------
node <<EOF
    const fs = require('fs');
    let rawdata = fs.readFileSync( 'capacitor.config.json' );
    let data = JSON.parse(rawdata);
    if ( data.server && data.server.url ) {
        delete data.server.url;
    }
    fs.writeFileSync( 'capacitor.config.json' , JSON.stringify( data , null , 4 ) );
EOF

# Sync Distribution
# ----------------------------------------------------------------------------------------------------
echo "Syncing Distribution"
npx cap sync ios

# Reset Config File
# ----------------------------------------------------------------------------------------------------
echo "Resetting capacitor.config.json"
echo "$config" > "capacitor.config.json"

# Open Xcode
# ----------------------------------------------------------------------------------------------------
echo "Opening Xcode"
npx cap open ios

ember-capacitor-build-android.sh

#!/bin/bash

# Build Ember
# ----------------------------------------------------------------------------------------------------
echo "Building Ember"
ember build --environment=production

# Store Config File
# ----------------------------------------------------------------------------------------------------
echo "Reading capacitor.config.json"
config=`cat capacitor.config.json`

# Ember Live Reload
# ----------------------------------------------------------------------------------------------------
node <<EOF
    const fs = require('fs');
    let rawdata = fs.readFileSync( 'capacitor.config.json' );
    let data = JSON.parse(rawdata);
    if ( data.server && data.server.url ) {
        delete data.server.url;
    }
    fs.writeFileSync( 'capacitor.config.json' , JSON.stringify( data , null , 4 ) );
EOF

# Sync Distribution
# ----------------------------------------------------------------------------------------------------
echo "Syncing Distribution"
npx cap sync android

# Reset Config File
# ----------------------------------------------------------------------------------------------------
echo "Resetting capacitor.config.json"
echo "$config" > "capacitor.config.json"

# Open Android Studio
# ----------------------------------------------------------------------------------------------------
echo "Opening Android Studio"
npx cap open android
1 Like

Hi @MatthewPringle

Nice to see I’m not the only one interested in Ember and hybrid app development.

Two ways to build hybrid apps:

  1. packing static assets (html, css, js) into the app
  2. packing a “container-app” and loading the website at app-start

If you configure your capacitor with the above capacitor.config.json, you go for mode 2.. Thus, it is sufficient to just use the normal Ember build workflow, without any modifications to live-reload etc. Just run it in development mode. Since you use a container-app, you can use a plain Capacitor starter app:

  • npx @capacitor/cli create
  • `npx cap add android’
  • npx cap add ios
  • add the server with url and allowNavigation to capacitor.config.json,
  • have fun!

If you want to go for a REAL hybrid app an packing your assets (html, css, js) into the app:

  • don’t add the server part
  • specify /dist as webDir
  • run ember build --environment=development
  • run npx cap copy or what cap commands you need
  • run the emulator
  • enjoy

For this scenario, I actually don’t know how to easily setup live-reload, but I’d try to use the “pwa” mode for quick development or the “container”-approach and only periodically check the “packed”-mode

What do you think?
Crixx