Monday, January 28, 2019

Mobile Resources (images and icons)

Now that we have the Aurelia project integrated in the Cordova project and can successfully build and deploy to mobile devices, it is time to get rid of the default Cordova icon and splash screen image and replace them with something a little more to our liking.

Resource Files

Anyone who has built an app for Android or IOS understands the pain and frustration of having to create and integrate the voluminous number of image assets that each platform requires.

In my travels I have discovered a handy online tool to help ease the pain. It isn't perfect, but it is close and can certainly remove hours of resizing, cropping, and configuring these images.

Before we get to the tool itself we must create two image files. One for our icon and one for our splash screen. I'm not a photoshop expert so I won't even go there. I will leave it up to you to cobble together some cool images for your app.

What I can tell you is that the images should be relatively high resolution and quality. The online tool is going to re-size them and crop them to certain parameters so you should also strive to keep your artwork and message in the center of the image and do not use the entire canvas. Leave a relatively large margin around the edges. I achieved relatively good results using a 1024 x 1024 icon image and a  2208 x 2208 splash image. I also saved them as png images so that they are lossless and can be easily resized.

I suggest you save these files in the root/res folder. This is not required, but it is a good place to keep them so that if you require them in the future they will be easy to find.

Now that we have created our two base images it is time to let the online tool do it's magic.
  1. Open your browser to https://www.resource-generator.com and follow the instructions.
  2. Choose your two files and then click the big green button.

  3. The generator is going to crunch away and produce a zip file and a configuration segment.
  4. Copy the configuration segment and paste it into config.xml file in the root of your project.



  5. Download the zip file that contains the generated resource files.

  6. Open the zip file and you will see two png files and a res folder. NOTE: These are not the same png files you uploaded, but resized versions to be used in our app. Do not save them to the res folder because they will overwrite our high res versions. If you want to save them to the res folder then you should first rename the originals.
  7. Copy the icon.png and save it somewhere handy. We will be converting it to an ico file a little later.
  8. Create a new folder in the root of our project called images and copy the splash.png to this folder.

  9. Open the res folder in the project root.
  10. This folder contains an icon directory and a screen directory. Delete both of these directories. They contain the default Cordova resource files.

  11. Open the res folder in the zip file.

  12. Copy the icons and screens directories into the res folder in the root of our project. NOTE: The directory names are a little different than the originals (they end in s). This is by design. Do not change them back to singular!

We now have all of our mobile resources inserted into our project. The res folder contains all of the images needed by the Cordova Android project and the Cordova IOS project. If you decide to use the splash screen in the Cordova browser project, it will use the splash.png in the new images folder.

Next is to replace the favicon.ico file in the root of our project.
  1. Open your browser to https://icoconvert.com and follow the instructions.
  2. Choose the icon.png file that we saved to a handy location earlier.
  3. Click the Upload button and let the tool do it's magic.
  4. You can crop your image or apply a style if you desire. I am just leaving my image as is.
  5. Select the 'favicon for your website' option

  6. Click the Convert ICO button
  7. Click the link to download your new ico file
  8. Delete the existing favicon.ico file from the root of the project.
  9. Copy the downloaded file to the root of the project and rename it to favicon.ico
Now we have our new image assets in the res folder and a new favicon that will be used when we run our project in a browser. Last thing to do is run cordova build from the command prompt. This will copy all our root/res images to the correct locations in the Android project and the IOS project.
  1. Open a command prompt in the root of our project.
  2. Run command cd www
  3. Run command cordova build
  4. Run command cordova run android
  5. We should see our new images on the splash screen and the app icon should be replaced with our new image.


  6. Run command cordova run browser
  7. We should see our new favicon in the browser tab (you may have to refresh the browser to replace the old cached image)

NOTE: The resource configuration data that we inserted in the root/config.xml file instructs the Android project and IOS project how to link the various assets for each project. Take note of the path in the instructions. It uses the icons and screens (plural) directories that we copied from the downloaded zip file. If you make any changes to the res directory or to the resource configuration in the xml file then you must run cordova build to push these changes to the appropriate Cordova projects!

That wraps up the resources portion of this blog. If you are interested in learning more about Android resources you can start reading here. Xcode may complain about a couple of missing resources depending on the version of Xcode. Sometimes the resource tool is lagging behind recent screen resolutions used by Apple. There is a good tutorial here if you are interested in learning more.

I think it is time for another beer ... :)
Next up is adding and integrating Electron to our project.


Thursday, January 24, 2019

Push Aurelia => Cordova Build

Now that we have access to the Cordova environment in our Aurelia project it is time to modify the build scripts to push the Aurelia project into the correct locations so that Cordova can build our project as a mobile deployment.

Cordova

Before we start pushing files around we really need to understand how the Cordova build environment works. Let's take a quick look at the root folder structure:

  • /hooks                       Cordova build hooks
  • /platforms                 Cordova platform files
  • /plugins                     Cordova plugin files
  • /res                            Resource files (images for different screen resolutions)
  • /www                        Project source files
The hooks folder is a repository for files that can "hook" into the build process. You can read more about it here.

The platforms folder contains a folder for each platform that in turn contain all the required files for a complete build for each platform. Files in this folder structure should not be edited because they are replaced by the build scripts during each build. Each platform folder contains folders and files specific to the specific platform. The android folder contains a complete android project that can be opened and debugged using Android Studio. The ios folder contains a complete xcode project that can be opened and debugged in XCode on a Mac. You will notice that each platform folder has a www folder. If you were developing the project as a stand alone project this is where you would actually do your code editing, but since we are pushing our code into these projects any changes you make here would be overwritten by our scripts.

The plugins folder is a repository for each plugin that you add to the Cordova project. Each plugin folder contains all the files needed to support the different platforms. Again, you should not make any changes to code in this folder. It is possible to author your own plugins. You can read more here.

The res folder contains a collection of various size images to support all the different screen resolution of mobile devices. You can read more about it here. This tool can help you build all the required images. 

The www folder is where you write your code for your Cordova project. It is the single code repository that gets pushed to all the platforms during the cordova build. This will be the destination for our aurelia build scripts. Again, do not manually edit files in this directory. Your changes will be lost during the next aurelia build!

Now that we have a basic understanding on the directory structure it is time to write some Aurelia build scripts. There are a couple of basic concepts to understand here. First, we want to push the files after the bundles are written. You may think that we could just use the copyFiles routine that we previously used, however, that task copies files before the bundler runs. Second, we always want to clean the destination directories before we copy our files into them. If we did not do that, any file that we remove or re-locate in the project would be left behind in the destination as an orphaned file. We always want the destination to be free of old artifacts.

Let's get started.

We will begin by adding a new task to the aurelia_project/tasks folder. We want to build a similar task to the copyFiles task but with some small differences.
  1. Open your code editor and add a new file called push-files.js to the aurelia_project/tasks folder.
  2. Cut and paste code from here into the new file and save.


  3. Open aurelia/project/tasks/build.js in your editor.
  4. Make the following changes and save.

  5. Open aurelia/project/tasks/watch.js in your editor.
  6. Make the following changes and save.


  7. Open aurelia_project/aurelia.json in your editor.
  8. Make the following changes and save.

OK, let's recap what we have just done.

We created a new task that reads instructions from the aurelia.json file. It behaves very much like the copyFiles task, except it executes a del task before it copies the source files to the intended destinations. As we add more resources and files to this push file task the del helps ensure that old and orphaned files are removed from the destinations as we remove or relocate them in our source code as we progress with our development and refactoring of the project.

We included our new push files task in the build task so that it runs immediately after building the bundles.

We also included our new push files task in the watch task, so that when a change in our source code  triggers a build in the Aurelia project, our new push files task gets executed to ensure the build paths are always up-to-date with our latest changes.

We added a bunch of sources and targets to the aurelia.json file to instruct our new task what to do.

The structure of the json node for our new task is very important. It contains a "sources" node and a "targets" node. The sources behaves exactly like the copyFiles task (I always try to be as consistent as possible with existing code).

The sources node is a json object that contains a key value pair for each file or folder that we want to push. It supports standard glob patterns. The key is the filename including the path from root of the resource we are pushing. The value is the receiving directory again referenced from the root.

The targets node is an array of destinations for our push task. Each destination is referenced from the root of our project. You will see that I have added the root www folder as well as a www folder for each platform we added to the Cordova project. The task will take each destination or target, add the receiving directory from sources and then push the files to this new location.

If we break this down to a math type of equation it would look like this:

  • "sources": { "f": "d" }, "targets": [ "a", "b" ]
would result in:

  • d/f  being copied to  a/d/f   and  b/d/f 
While it is not necessary to add each platform www folder to the targets list (every time you build the Cordova project the www folder gets copied), it is desirable if you have a project open in Android Studio or XCode for debugging. Adding these target destinations results in our Aurelia code changes automatically appearing in the Cordova projects without having to continually build the entire Cordova project ... sweet ... !

NOTE: Our new task only pushes the Aurelia project and associated resources to the Cordova project. If you make any changes to the Cordova project structure you would have to do a Cordova build to include the Cordova changes that you have made.

As we add more resources to our project we may elect to have some resources reside in the root directory instead of inside the client folder. There are many reasons for doing this. Sometimes it is because of logistical concerns, sometimes it is simply personal preference. For example, we will be adding Internationalization to our project and I like to keep the translation files in a separate folder called 'locales' in the root of the project. We could include this folder in our file push by simply adding "locales/**/*": "locales" to the sources node of the aurelia.json file.

NOTE: If you remove an entry from the aurelia.json file, the corresponding files will NOT be removed from the targets the next time the task runs because the task simply does not know about them anymore. You have to manually do housekeeping on the target directories in this scenario!

NOTE: When changes are made to core files outside the client directory (such as aurelia.json or any of the task files), the Aurelia file watcher will NOT pick them up. You must cancel the command prompt session and run the 'au run --watch' command to rebuild the Aurelia project and capture these changes.

OK, lets fire up the Aurelia app to test our additions.
  1. Open a command prompt.
  2. Run command 'nvm use 10.14.0'
  3. Run command 'npm install merge2 --save-dev' to install new library used in push-files.js
  4. Run command 'au run --watch'
  5. Open a file explorer to the root/www directory of our project.
  6. You should see our 'pushed' files and directories have appeared. 

  7. We should check each destination in our target list to ensure the files have arrived.



  8. You should see extra files that have been inserted by the cordova build process in each platform. We must ensure that we do not remove or copy any of these files because they are platform specific. We only want to push our Aurelia project files to these folders!

NOTE: If you are working on a Windows machine you will not be able to run the 'cordova build ios' command. This can only be done on a Mac (or on a Mac VM running on Windows). I have run the command on my Mac and copied the files back to my Windows machine for the purpose of obtaining the screen shot shown above. Your ios/www directory may be missing the Cordova injected files. Don't worry about this if you are running on a Windows machine.   

We should now have a fully automated push from Aurelia to Cordova whenever we start up the Aurelia run process or whenever we make any changes to the Aurelia client project when the Aurelia run process is active. Let's test our solution.
  1. Run command 'au run --watch'
  2. Open a new (second) command prompt in the root of our project.
  3. Run command 'nvm use 10.14.0'
  4. Run command 'cd www'
  5. Run command 'cordova run browser'
  6. You should see the browser open to the Aurelia 'Hello World' page. Remember we disabled the splash screen for browsers.

  7. Run command 'cordova run android'
  8. You should see the emulator open and the Cordova splash screen for a couple of seconds and then the Aurelia 'Hello World' should appear ... magic ...


If you have a MAC you can follow the same process and should see the same results!

NOTE: You will get an error if you try to run the 'cordova ... ' commands from the project root. Node finds our cordova.js shim and tries to execute it instead of running the Cordova build script. (I am still researching to determine if this behavior can be changed ...). An easy fix is to change directory to the www folder (any will do) and run the Cordova commands from there!

Congratulations! We have successfully integrated our Aurelia project into a Cordova project! Go ahead and open up your editor, open a command prompt and au run, then make some changes to the Hello World screen and save your changes. Open Android Studio and run the app ... You should see your changes in the emulator!

You can even go ahead and deploy the app to an Android or IOS device ... awesome ...

Android Studio has a built in file watcher that auto rebuilds the app, however at the time of writing this, the watcher does not see our pushed file changes, therefore you will need to re-start the app to see your changes. I'm hoping that this feature will be modified in the future to pick up our changes.

XCode also requires you to re-launch to see the changes. However this is a small inconvenience when we consider the level of integration we have achieved so far!

In the next blog we will deal with adding resources to our project for mobile builds



Tuesday, January 8, 2019

Merge Cordova => Aurelia

Now that I've had a couple of beers and a much needed break it is time to jump into the fun stuff!

First we need to do a little research and understand how our two projects perform builds and where resources are located. Our mission is to modify some of the build scripts so that each project gets populated with the required files automatically when project resources are changed or modified, either by us in the editor or by the project's build scripts being executed by the CLI.

AURELIA

The Aurelia project is a SPA. It uses some build scripts to bundle up all your internal javascript, css, html, and resource files into a single file called app-bundle.js. It also uses an auto tracer to scan your code and bundle all the required resources (node packages) into a file called vendor-bundle.js. These two files are located in the scripts folder in the root of our project. The vendor bundle is added to the index.html file using a <script> tag. The app bundle is auto inserted into the document header by the vendor bundle. This provides a nice simple and clean way to deliver our SPA to a client. It also works very nicely with our Cordova project.

If any of you have ever worked on a Hybrid Mobile project in Cordova you will probably know about a very annoying little issue that always pops up in a new project. The Cordova framework is injected into our project by using a <script> tag in the index.html page ... just like Aurelia does. Since we are editing and testing our SPA in a browser outside of the Cordova environment we are constantly "reminded" by an error message in the console that the cordova.js file cannot be found. Secondly, the entire Cordova framework is not available during the development process. We used to deal with this by commenting out the script tag during desktop development and then adding it back in for mobile debugging in XCode or Android Studio ... not a very good solution!

The good news is that Cordova has a browser platform that can be included during desktop development that solves this problem and gives you access to the Cordova framework on your desktop during development ... sweet ... !

So let's start by adding the Cordova framework to our Aurelia project.
  1. Open the index.html file in your editor.
  2. Add  <script type="text/javascript" src="cordova.js"></script> directly below the <body ... > tag.

  3. Open a command prompt in the root of your project.
  4. Run command 'nvm use 10.14.0'
  5. Run command 'au run --watch'
  6. Open a browser to 'localhost:9000'
  7. Open the Dev Tools (inspect) and check the console.
  8. You will observer the following error:

Now lets fix this problem. We need to add the cordova.js and the cordova_plugins.js files to the root of our project. These files are auto generated by the Cordova CLI during a build event based on the current platform. Normally these files are NOT included in the project because they are subject to change based on environmental configuration. So we need to indulge in a bit of the age old "Chicken and Egg" scenario here. We will use an Aurelia build script to copy the Cordova files to our project root during an Aurelia build event BUT we will not include these files when we push our project files back to the Cordova file structure ... I'm getting a little ahead of myself here, but it is necessary to understand this process. We will address pushing our project files to the Cordova project in the next steps ...

OK, first we need to ensure the files we need have been created by Cordova CLI.
  1. Run command 'cordova prepare'
  2. You should see the platforms and plugins directories in the root of the project
  3. Open a file explorer to 'platforms\browser\www' directory.
You should see the cordova.js and cordova_plugins.js files. These are the files we need to copy back to the root of our project. We will do that by using a built in feature of the Aurelia build script.

NOTE: It is worth a mention here about the mysterious www folder that keeps appearing at various places in the Cordova project. This is a source of great confusion to developers and has been written about and documented extensively. You can read about it here. In a nutshell ... you create and edit your Cordova project files (your SPA) in the root/www folder. During Cordova build events these files are copied to the platform/www folders and then the build uses the platform specific folders to build each platform. You should NOT edit any files in the platform directory ... these are reserved for dynamic builds ... any editing you make there will be lost during the next build! ... simple once you understand how Cordova builds it's projects ...

There is a small problem running the Cordova files in the browser that we must address. When Cordova builds the platform specific files it performs some platform specific modifications to the package files that it uses as it's base. The base files are located in the platforms and plugins folders in the project root. The resulting build files are also located in these folders but reside at very specific directory levels. This all gets a little confusing but necessary because the generated files contain path specific requires to ensure all files needed by a platform get loaded for the specific platform. What all this means is we need to ensure we copy the correct file set to our project during the Aurelia build. Remember, these files are only used by our project for development and debugging. The Cordova build generates it's own files for the packaging and deployment of our app.

If you are totally confused at this point don't worry. Just follow the next instructions which will get the correct files into the correct locations and everything will work and hopefully will make sense ...

Now we can add instructions to copy these files to the project root/scripts directory instead of the root directory.. I have chosen this directory because it holds the Aurelia generated files therefore it is a logical place to store the Cordova generated files. Remember, do not edit these files because they get replaced during builds.

The reason we cannot copy the files to the root is because they contain path specific includes that will ultimately load the wrong support files if we run them from the root folder. We will fix this by including all of the required support files in a correct hierarchy inside the scripts folder.
  1. Open 'aurelia_project/aurelia.json' file in your editor
  2. Under the 'build:loader' node add a new node 'build:copyFiles'
  3. Add "platforms/browser/www/cordova*.js": "scripts"
  4. Add "platforms/browser/www/plugins/**/*.js": "scripts/plugins"

  5. Save the changes.
  6. Run command 'au run --watch'
  7. The two Cordova files and the plugins directory should appear in the scripts folder

So far so good. Every time Aurelia builds we will get the required Cordova file set injected into our project. A nice little bonus of using the Aurelia build to preform this task is that it also adds a file watcher to the source files, so if a Cordova build changes the source files (maybe a version update) Aurelia will automatically inject the newer files into our project ... gotta love Aurelia! ....

We still have a problem to solve. The cordova.js file resides in the scripts folder but our <script> tag is trying to load it from the root folder. You may be tempted to change the <script> tag to point to the cordova.js file in the scripts directory. Don't do this! When we build the mobile project in Cordova the cordova.js file will be in the root and not in the scripts folder. The script tag MUST load the cordova.js file from the root folder for our mobile builds to be successful.

OK, don't worry. This is all by design. Remember, these copied files are only used during development and not in production. What we will do to solve this little problem is create a shim file in the root directory that loads the cordova.js file located in the scripts directory. This shim file will also be called cordova.js so our script tag in the index.html file can remain the same between development and production builds.
  1. Add a new file to the project root and save it as 'cordova.js'

  2. Open this file in the editor and add the following code. This injects a new script tag into the document body that loads the cordova.js script in the scripts folder. Remember, this file gets replaced by the real cordova.js file during production builds ... this is only a shim for the development environment.

  3. Open 'client/main.js' in the editor. We need to delay the Aurelia start until after Cordova loads. Cordova adds an event called 'deviceready'. We will add a listener that will start Aurelia.

OK ... It's time to try to test this. When we run the Aurelia project it should load Cordova first, then launch our familiar "Hello World" start page.
  1. Run command 'au run --watch'
  2. Open a browser to localhost:9000 and inspect the page
  3. The Cordova file error should not appear. Instead you should see the Cordova plugins reporting followed by the Aurelia starting message. There are some new errors introduced by the splash screen plugin. We will take care of those next.

  4. Open the Network tab in Dev Tools and refresh the browser.
  5. You will see the Cordova files load as well as some files needed by the Cordova platform.

  6. We now have a fully operational Cordova framework included in out Aurelia desktop development environment! ... life is good ...
Let's get rid of the remaining console errors. These are generated by the Splash Screen plugin. The splash screen is required on mobile devices to display something to the user while the device loads and initializes the app. It is not required by our browser platform so we can simply disable it. If you want a functional splash screen in the browser platform you can opt to supply a logo image and set the configuration parameters. (Note: You will have to delay the Aurelia start function because it replaces the <body> elements and effectively removes the splash screen when it starts) For this project I am going to disable it, but only for the browser platform.

  1. Open the 'config.xml' file found in the project root in your editor.
  2. Add the following node

  3. Run command 'au run --watch'
  4. Inspect the console. All errors should be gone.


 NOTE: Remember to terminate your command session and re-run 'au run --watch' after making any changes to the root of the project. The Aurelia file watcher only watches the interior project files so it may not catch your changes!


Next we will merge our Aurelia project into the Cordova project so that when Cordova builds it will be building our project instead of the sample Cordova project.