Creating a hybrid mobile Application with Ionic, Cordova and AngularJS
May 3rd, 2015 by Micha KopsNowadays in the realm of hybrid mobile application development there is a variety of available frameworks worth having a look at.
In the following tutorial I’d like to demonstrate the development life-cycle for a complete mobile application using Ionic, Cordova and AngularJS (and others) covering every step from the initial project setup, creating Angular Controllers, Directives, adding Cordova Plug-Ins, running and testing the application in the browser and emulator up to finally running the application on an Android device and assembling files for a release.
Finally I’d like to show some special features from the Ionic ecosystem like the Ionic Cloud and running our applications using the IonView app.
Contents
- What we're going to build
- Installing Ionic and Cordova
- Creating a new Project by Template
- Running the Sample Application in the Browser
- Enabling the Android Platform
- Angular Module Configuration
- Implementing the Search Function
- The About Tab
- Testing the final app in the browser
- Generating App Icon and Splash Screen Images
- Adding Cordova Plugins: InAppBrowser
- Running with the Android Emulator
- Running on a connected Android Device
- Packaging for Android
- App Distribution using Ionic.io
- Tutorial Sources
- Resources
- Other Ionic/Mobile Development Articles of mine
- Article Updates
What we’re going to build
The main functionality of our application is to search for articles from my blog at www.hascode.com by a given tag that the user enters into a search field in the first tab of the tabular layout used.
If blog articles are found, they should be rendered in a list displaying their featured image, their title and an excerpt of their content and – of course – they should link to the original article on the website.
In the second tab, some basic information about the plug-in and its author is display .. the classical “about” dialogue.
The mockup above gives a first impression of the user interface of our mobile application.
Installing Ionic and Cordova
Since we’re going to build our application with Ionic and Cordova, we should install both first ;)
We need to have nodejs installed – if it’s not installed yet, we should visit the nodejs download site, download and install nodejs - it should take a few minutes only.
Now we’re ready to install Ionic and Cordova using the nodejs package manager (npm):
npm install -g cordova ionic
That’s all for now and we may start with the fun stuff…
Creating a new Project by Template
First of all we need to create a new Ionic project. Luckily for us the console client allows us to bootstrap a new project with ease and in addition we may choose from three available pre-set templates: blank, tabs and sidemenu.
As we’re going to build a tabbed application, we’re using the tabs template as a starting point and doing so we’re able to create our initial project using the following command:
$ ionic start hascode-tag-wizard tabs
This creates a directory named hascode-tag-wizard that contains everything we need including bower configuration, gulp tasks, sample templates, working angular routing and module configuration, separated angular services, controllers and a lot more..
Running the Sample Application in the Browser
At this point all we have is a sample application. To run this application use the following command to start a web-server, start a new browser instance and listen for changes in our project’s file system. If we change files in our project, the browser is automatically reloaded – nice.
$ ionic serve Running dev server: http://localhost:8100 Running live reload server: http://localhost:35729 Watching : [ 'www/**/*', '!www/lib/**/*' ] Ionic server commands, enter: restart or r to restart the client app from the root goto or g and a url to have the app navigate to the given url consolelogs or c to enable/disable console log output serverlogs or s to enable/disable server log output quit or q to shutdown the server and exit
We should press ‘c‘ here to enable client debugging – it prints the output from console.log() in the application to the console.
Here is an example from a later version of our application:
ionic $ c Console log output: enabled Loading: /?restart=644673 ionic $ 0 174983 log searching articles for tag tdd 1 175307 log hits received: 13 2 188088 log searching articles for tag javaee 3 188425 log hits received: 11
If we’re opening the sample application at http://localhost:8100 (or a higher port if 8100 was already in use) it should look similar to this one:
Now we’re ready to implement our real application.
Enabling the Android Platform
To enable the application for a designated target platform, simply run ionic platform add. I’m using the Android platform throughout the tutorial but I’m positive, that building for the iPhone (with an existing license etc.) or other possible platforms should be working without a problem, too (I hope so).
$ ionic platform add android
Angular Module Configuration
Next we’re doing some basic setup like modifying our index.html to include all style-sheets and scripts we need in their correct order.
The following code shows our index.html. We have added an additional file for our Angular directives named directives.js in there.
Besides this, our navigation bar is added here and we’re referencing our Angular module named hascodeTagWizard that’s going to be created in the next step.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <title></title> <link href="lib/ionic/css/ionic.css" rel="stylesheet"> <link href="css/style.css" rel="stylesheet"> <script src="lib/ionic/js/ionic.bundle.js"></script> <script src="js/app.js"></script> <script src="js/controllers.js"></script> <script src="js/services.js"></script> <script src="js/directives.js"></script> <script src="cordova.js"></script> </head> <body ng-app="hascodeTagWizard"> <ion-nav-bar class="bar-stable"> <ion-nav-back-button> </ion-nav-back-button> </ion-nav-bar> <ion-nav-view></ion-nav-view> </body> </html>
In the following file named app.js we’re specifying our Angular module. Besides some boilerplate code from the Ionic framework, we’re adding our navigation rules in the module configuration to specify link-patterns and their assigned view-templates and controllers.
The search-tab is bound to the SearchController, the about-tab to the AboutController and if a link does not match any rule, the search tab is rendered as a fallback.
/* global angular, console, cordova, StatusBar */ angular.module('hascodeTagWizard', ['ionic']) .run(function ($ionicPlatform) { "use strict"; $ionicPlatform.ready(function () { if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) { cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); } if (window.StatusBar) { StatusBar.styleLightContent(); } }); }) .config(function ($stateProvider, $urlRouterProvider) { "use strict"; $stateProvider .state('tab', { url: "/tab", abstract: true, templateUrl: "templates/tabs.html" }) .state('tab.search', { url: '/search', views: { 'tab-search': { templateUrl: "templates/tab-search.html", controller: 'SearchController' } } }) .state('tab.about', { url: '/about', views: { 'tab-about': { templateUrl: "templates/tab-about.html", controller: 'AboutController' } } }); $urlRouterProvider.otherwise('/tab/search'); });
Tab Views Configuration
In the next step we’re configuring our tab container and the icons used for its different states in the external file named tabs.html.
<ion-tabs class="tabs-icon-top tabs-color-active-positive"> <ion-tab title="Search" icon-off="ion-ios-search" icon-on="ion-ios-search-strong" href="#/tab/search"> <ion-nav-view name="tab-search"></ion-nav-view> </ion-tab> <ion-tab title="About" icon-off="ion-ios-information" icon-on="ion-ios-information" href="#/tab/about"> <ion-nav-view name="tab-about"></ion-nav-view> </ion-tab> </ion-tabs>
Ionic Icon Search – Ionicons
The icons used above have been selected from the Ionicons website. It’s a nice tool to find and select an icon needed in no time.
Implementing the Search Function
Finally we’re starting to implement the main functionality of our application – the tag search.
Search View
We’re beginning with out view template named tab-search.html that is bound to the SearchController as specified in our route declaration above.
There is not much to say, however we’ve got an input field that starts the search when the enter button is pressed. If the search term entered changes, the search result list is reset.
The search results are rendered using an ng-repeat and a custom directive to display each blog article found (the directive is described in the next chapter).
<ion-view view-title="hasCode.com Tag Search"> <ion-content class="padding"> <div class="list list-inset"> <label class="item item-input"> <i class="icon ion-search placeholder-icon"></i> <input type="text" placeholder="Search articles by tag" ng-model="term" ng-keyup="$event.keyCode == 13 && searchTerm()" ng-change="resetResults()"> </label> <h3 ng-show="showResults">{{hits.length}} Hits for "{{term}}"</h3> <div class="list" ng-repeat="hit in hits"> <blogarticle data="hit"/> </div> </div> </ion-content> </ion-view>
Blogarticle Directive
Our directive named blogarticle renders a single blog-article with its featured image, title and an excerpt and manages clicks on the item (more about this later in “Using the InApp Browser“).
/* global angular, console */ angular.module('hascodeTagWizard') .directive('blogarticle', function () { "use strict"; return { restrict: 'E', scope: { article: '=data' }, link: function (scope, element, attrs) { scope.browse = function (url) { console.log('opening link: '+url); window.open(url, '_blank', 'location=yes'); }; }, template: '<a class="item item-thumbnail-left item-text-wrap" ng-click="browse(article.url)">' + '<img ng-src="{{article.image}}">' + '<h2>{{article.title}}</h2><p>{{article.excerpt}}</p></a>' }; }) ;
Search Controller
The search controller delegates search requests to the search service and manages the control flow and state of our views.
angular.module('hascodeTagWizard') .controller('SearchController', function (searchService, $scope) { "use strict"; $scope.term = ''; $scope.hits = []; $scope.showResults = false; $scope.searchTerm = function () { searchService.searchByTag(this.term).then(function(response){ $scope.hits = response.data || []; console.log('hits received: '+$scope.hits.length); $scope.showResults = true; }); }; $scope.resetResults = function () { $scope.showResults = false; $scope.hits = []; }; });
Same-Origin-Policy (SOP) and Cross-Origin-Resource Sharing (CORS)
To work around the same-origin-policy restriction the remote back-end sends the following header to enable cross-origin-resource-sharing:
Access-Control-Allow-Origin: *
Server Side Response
This is a sample response from my blog (shortened):
[ { "title":"A short Introduction to ScalaTest", "url":"https://www.hascode.com/?p=980", "image":"http ://www.hascode.com/wp-content/uploads/2013/01/infinitest.png", "excerpt":"ScalaTest is an excellent framework to write concise, readable tests for your Scala or Java code with less effort. [..]" }, { "title":"BDD Testing with Cucumber , Java and JUnit", "url":"https://www.hascode.com/?p=1162", "image":"https://www.hascode.com/wp-content /uploads/2014/12/cucumber-second-test-in-junit-runner.png", "excerpt":"[..]" } ]
Search Service
The search service manages the communication to the remote server and returns a promise used by the controller.
/* global angular, console */ angular.module('hascodeTagWizard') .factory('searchService', function ($http) { "use strict"; var blogUrl = 'http://THEBLOGURL/byTag.php?tag='; return { searchByTag: function (tag) { var searchUrl = blogUrl + tag; console.log('searching articles for tag ' + tag); return $http({method: 'GET', url: searchUrl}); } }; });
The About Tab
The about-tab simply displays the ugly logo from my blog, a link to my blog and the current year.
About View
This is the view template in a file named tab-about.html bound to the AboutController.
<ion-view view-title="About" ng-controller="AboutController as about"> <ion-content class="padding"> <div class="card"> <div class="item item-divider"> <h2>hasCode.com Tag Search App</h2> </div> <div class="item item-image"> <img src="img/icon.png"> </div> <div class="item item-divider"> <a ng-click="about.browseBlog()">{{about.year}} Micha Kops / www.hascode.com</a> </div> </div> </ion-content> </ion-view>
About Controller
This is the designated controller, nothing special here.
/* global angular, console */ angular.module('hascodeTagWizard') .controller('AboutController', function () { "use strict"; this.year = new Date().getFullYear(); this.browseBlog = function(){ window.open('https://www.hascode.com/', '_blank', 'location=yes'); }; }) ;
Testing the final app in the browser
Running ionic serve again, we’re now able to test the application in a browser.
The result should look similar to this one:
Generating App Icon and Splash Screen Images
Another nice feature of the Ionic framework is the possibility to generate the different images in different sizes needed to display the application icon and splash screen for the different target platforms.
Simply add the source image using a format like PNG, Photoshop psd or Illustrator ai files, copy them to the resources directory e.g. replacing the existing icon.png or splash.png and run the following command and the new app icon or splash screen is added to our application:
$ ionic resources Ionic icon and splash screen resources generator [..] generating splash android drawable-port-xxxhdpi-screen.png (1280x1920)... generating splash android drawable-port-xxhdpi-screen.png (960x1600)... generating splash android drawable-port-xhdpi-screen.png (720x1280)... ✓ splash android drawable-port-xhdpi-screen.png (720x1280) generated generating splash android drawable-port-hdpi-screen.png (480x800)... ✓ splash android drawable-port-hdpi-screen.png (480x800) generated generating splash android drawable-port-mdpi-screen.png (320x480)... ✓ splash android drawable-port-mdpi-screen.png (320x480) generated generating splash android drawable-port-ldpi-screen.png (200x320)... ✓ splash android drawable-port-xxhdpi-screen.png (960x1600) generated generating splash android drawable-land-xxxhdpi-screen.png (1920x1280)... ✓ splash android drawable-port-ldpi-screen.png (200x320) generated generating splash android drawable-land-xxhdpi-screen.png (1600x960)... ✓ splash android drawable-land-xxhdpi-screen.png (1600x960) generated [..] etc ...
More information about icon and splash screen image generation can be found in the Ionic documentation here.
Adding Cordova Plugins: InAppBrowser
To open external links using an in-app-browser we need to add the Cordova plug-in of the same name.
Installing Cordova plug-ins is easy and the following command is everything we need to to to add the in-app-browser plug-in:
$ ionic plugin add org.apache.cordova.inappbrowser
From now on we may use this browser when opening links like this:
window.open(url, '_blank', 'location=yes');
Running with the Android Emulator
For near-real experience and the Android SDK installed, we’re now able to run our application using the Android emulator by running the following command:
$ ionic emulate android
This is what the about-tag looks like in the Android emulator.
And this is the search result for the term “tdd” run in the emulator:
You may use logcat to receive the logs as described in the following article of mine here.
Running on a connected Android Device
Deploying the application for test on a real Android device is really easy.
All you need to do is to enable “USB debugging” in the developer settings and run the following command:
$ ionic run android
This is a screenshot taken from a Sony Xperia Z3 compact with Android Lollipop:
Again you may use logcat to receive the logs as described in the following article of mine here.
Packaging for Android
To build an an Android apk-file we simply need to run the following command.
More detailed information about the release build process and apk-signing can be found in the Ionic Documentation here.
$ ionic build android Updated the hooks directory to have execute permissions running cordova build android [..] -build-setup: [getbuildtools] Using latest Build Tools: 21.1.2 [echo] Resolving Build Target for MainActivity... [gettarget] Project Target: Android 5.0.1 [gettarget] API level: 21 [echo] ---------- [echo] Creating output directories if needed... [echo] ---------- [echo] Resolving Dependencies for MainActivity... [dependency] Library dependencies: [dependency] [dependency] ------------------ [dependency] Ordered libraries: [dependency] [dependency] ------------------ [echo] ---------- [echo] Building Libraries with 'debug'... [..] -package: [apkbuilder] Found modified input file [apkbuilder] Creating MainActivity-debug-unaligned.apk and signing it with a debug key... [..] BUILD SUCCESSFUL Total time: 9 seconds Built the following apk(s): /data/project/hascode-tag-wizard/platforms/android/ant-build/MainActivity-debug.apk
App Distribution using Ionic.io
Another nice feature of using Ionic is the possibility to upload an application to the cloud, share it there, manage deployments of these applications and install them on our Android/ios Devices using IonView to bypass the registration process in the native application marketplaces.
First of all we need to register an account at https://apps.ionic.io/signup
Afterwards we’re able to login by using the credentials from the step above by running the following command from our project’s directory:
$ ionic login
Afterwards we’re able to upload our application to the cloud and the application gets an identifier assigned:
$ ionic upload
Now we’re able to manage our application on the Ionic Apps website: https://apps.ionic.io
Sharing Apps
Now that our application is online, we may share the app using the sharing feature as show in the following screenshot:
App Deployment
Another feature is the possibility to switch between different existing versions of our application for deployment.
The following screen-shots demonstrates this feature:
Ion View App
The IonView app allows us to bypass the registration process for our application on the native markets. A user only needs to download the IonView app on Google Play or Apple’s AppStore and may download our application from the Ionic.io cloud.
We should be aware though that this application is still beta and depending on the APIs we’re using in one of our applications we might encounter problems when using this bypass solution – nevertheless it is an interesting solution and I wanted to include it here.
This is a screenshot when running IonView on my Android device with our search app downloaded and installed.
Tutorial Sources
Please feel free to download the tutorial sources from my Bitbucket repository, fork it there or clone it using Git:
git clone https://bitbucket.org/hascode/hascode-tag-search-app.git
Resources
- Ionic Website
- Apache Cordova Website
- AngularJS Website
- ionicons – Icon Overview for Ionic
- Cordova Plugin Registry
- InAppBrowser Cordova Plugin
- nodejs Project Site
- Ionic Documentation: Icon and Splash Screen Generation
Other Ionic/Mobile Development Articles of mine
Please feel free to have a look at other articles of mine about this topic here:
Article Updates
- 2015-05-05: Information about generating app icons and splash screens added.
- 2015-11-17: Links to other Ionic tutorials of mine added.
Tags: ajax, Android, angular, angularjs, controller, cordova, cors, directive, emulator, gulp, hybrid, ionapp, ionic, ionview, ios, javascript, js, json, logcat, mobile, npm, sop
September 11th, 2015 at 6:06 pm
HI, first, thanks for the sample, thanks for the step by step….very useful. The only issues I found:
- The Same-Origin-Policy (SOP) and Cross-Origin-Resource Sharing (CORS), didn’t understood where and how, so I checked your GitHub files and it worked and
- I made all the steps for IOS, adding the platform, and uploaded it to IonicView but on the Ipad I don’t get the search to work, any suggestion?
Again, thank you for the material.
September 26th, 2015 at 2:40 am
Thanks dude..
Great tutorial !!! :*
September 26th, 2015 at 2:32 pm
Thanks, you’re welcome :)
October 23rd, 2015 at 7:20 am
Awesome Tutorial thanks
October 23rd, 2015 at 7:41 am
Thanks, you’re welcome!
November 13th, 2015 at 9:38 am
Hello there,
thanks for the awesome tutorial:)
my question is this, after running “ionic build android” and then the u get “…-debug.apk” how do you publish your app on Appstore from there?
thanks
November 16th, 2015 at 8:39 pm
Hi sony,
you need to apply the IOS platform first as I’m covering only Android here but perhaps one of these resources might be a help for you:
http://cordova.apache.org/docs/en/5.1.1/guide/platforms/ios/index.html
https://medium.com/@_qzapaia/deploy-an-ionic-app-to-the-ios-app-store-702c79a2dd97