From Zero to App: The Cross-platform Development Approach Simplified
The demand for mobile application developers is extremely high. However, learning each platform's native programming language and toolsets can be a significant, time-consuming challenge.
Fortunately, there's a better way! Cross-platform application development.
The goal of cross-platform development is to create software that seamlessly runs on multiple platforms using one set of tools and programming languages. The benefits of this approach include lower costs, rapid prototyping, and skill reuse.
To begin creating an application with this approach, most developers select a framework as their starting point. Fortunately, there are lots to pick from. Some, including React Native, NativeScript, Vue, Angular, and Ionic, are built using web technologies. Others, like Xamarin and Flutter, leverage a diverse set of programming languages including C# and Dart.
Most of these are stellar; however, it can be overwhelming at first to decide which approach to take, which framework to pick, and then to get up to speed on its unique nuances.
After following this two-part guide, you'll be prepared to jump into a more serious framework should you wish to explore this approach further. In part one, we'll create the mobile app, and in part two, deploy it to a device using Adobe's PhoneGap Build tool.
Mobile App Building Blocks
Before jumping into creating the app, let's define the technologies we'll be using:
- Apache Cordova: An open-source mobile development framework that provides the tools to turn a web-based application into a native one.
- Adobe PhoneGap: Adobe's distribution of Cordova. It's essentially the same as Cordova, but with some extensions and additional tooling (such as PhoneGap Build). PhoneGap and Cordova are used interchangeably here.
Cordova App Architecture
A Cordova app is made up of a few different components: a web application, the HTML rendering engine (WebView), and native plugins.
The WebView is the secret sauce of a Cordova application. It is essentially an embedded web browser that the web application runs in. The WebView is then placed into a native app shell, allowing an app created with web tech to be deployed as a native app.
If a core plugin doesn't fit one's needs, third-party plugins are an option. They are open-source and created by the Cordova community. Virtually every use case is already available as a plugin, and if not, developers are free to create their own.
Altogether, this makes for a compelling solution to cross-platform development. The one piece of the puzzle that Cordova doesn't provide, though, is user interface (UI) widgets. It's up to the developer to implement the UI layer.
Fortunately, there's no need to start from scratch, as many open-source frameworks are available. This includes Kendo UI, which we'll look at as part of our application's design.
Creating the App
The mobile app we'll be creating is located here. For the rest of this article, all code referenced can be found in the “app – part one” folder.
The complete app below, running in Google Chrome, displays an image of the PhoneGap logo when first opened. When the user taps the button at the bottom of the screen, the device's camera opens, allowing the user to take a picture. Additionally, the captured photo is saved on the device so that when the user closes the app and comes back to it later, it is displayed immediately.
Also in this folder is the config.xml file, a configuration metadata file for Cordova. PhoneGap Build uses this file to determine how to create iOS and Android apps from the web app. We'll implement this in part two.
Additionally, other folders include “icons,” all icon image files to be used when creating the iOS and Android app, and “splash,” all splash screen images that display when the mobile app is opened.
These images will be created in part two.
App Code: index.html
With an overview of the structure of the Cordova app, we're ready to dive into the implementation of our app. Let's begin with index.html, the main container of the app.
At its core, this is an HTML5 web app, declared via this simple DOCTYPE tag at the top of the file: <!DOCTYPE html>.
Next, a meta tag defines a Content Security Policy (CSP). CSPs are an added layer of security for web pages and apps that mitigate certain types of attacks, such as cross-site scripting. In cross-platform mobile apps, they are a security mechanism used to ensure only the third-party content specified (via APIs or images, etc.) is loaded. More information can be found on the Mozilla Developer Network (MDN) web docs.
Last, there are two link tags that bring in the app's CSS, both for Kendo UI and any custom styles we wish to define.
Next up is a portion of the document's body. To demonstrate how to create multiple pages in an app, there are two here. The main page displays the picture taken from the device's camera and an “About” page displays some text that describes the app's capabilities.
Notice the two div tags with a data-role=”view” attribute. This is specific to the Kendo UI framework and represents each screen (or “view”) of the app. The first view, with title “Picture Viewer,” displays the last image taken by the device camera via a simple <img> tag. Immediately below, there are two other data-role attributes, footer and tabstrip. These tell Kendo UI to create a footer that contains clickable buttons like we'd see in a typical mobile app.
Continuing on, the next data-role represents the “About” page. Only one new custom attribute is used here, the listview, a common mobile UI pattern. As the name implies, it styles and groups together a list of items. In this case, we give it an unordered list (<ul>) and it takes care of the rest.
How does this really work? When this HTML file is opened in a browser, Kendo UI reads all of their custom attributes and performs some magic in order to create the resulting UI widgets that the user sees. Yes, the HTML is changed in the browser, but writing an app with it is very straightforward.
The last portion of the HTML document body defines a feature that really makes this web app feel like a mobile app: a drawer widget, which opens via a left or right swipe, or by tapping on the hamburger menu icon:
The two outer divs define the drawer menu and its arrangement within the app. The data-views attribute of the drawer tells it what pages to link to (“Photo Viewer,” “About,” and the parent HTML file itself), defined again using an unordered list for each. Kendo UI ships with a variety of common web/mobile icons. Changing them is as simple as reviewing this list, choosing one, and updating the reserved word (such as “info” to “search”).
The next div with data-role layout declares that the drawer menu should be displayed on every page in the app. The hamburger button points to the drawer via the href tag and the “my-drawer” id.
Next up, there is Kendo UI, jQuery, and Controller.js, which contains all of the app's setup and main logic code unique to this app.
App Code: Controller.js
Within Controller.js, we write the code that will provide the interactive functionality of the app, such as using the mobile device's camera to take a photo.
We begin with an initialization function, which executes immediately when the app loads. First, we need Kendo UI to stylize the app by creating a new instance of “kendo.mobile.Application”.
The first parameter given, document.body, is always used because we want Kendo UI to have access to the entire web app. The second parameter represents various configuration options. I've set the skin property to “flat,” referencing the popular “flat design” user interface style. If we left out this property entirely, Kendo UI automatically detects which type of device the app is running on (iOS or Android in this case), stylizing it according to that platform's design preferences.
The layout property tells Kendo UI which general layout to apply to the app. As you'll recall from the above HTML, we created a layout that attaches a drawer menu to every page within the app. We defined the layout in HTML by using the data-role=”layout” and data-id=”drawer-layout” attributes.
When the camera plugin is added to the app using PhoneGap Build in part two of this article, a “navigator.camera” object becomes available. The plugin's creator defines an API for us to use, which abstracts away the underlying native code. The magic of this is that we don't need to change the code for iOS and Android; it works the same regardless of platform.
In this app, we'll use the “getPicture” API. When this is called, the camera app is opened and ready to take a picture.
If the user is successful in taking a photo, then the cameraSuccessCallback function is executed. If something goes wrong or the user closes the camera without taking a picture, then the cameraFailCallback function is executed. Additionally, there are a variety of configuration options we can set, including the quality of the captured image and file type. For more options and APIs, see the documentation.
The last part of this code is the conditional check around the existence of the “navigator.camera” object. This is just a good coding practice I like to implement. If we don't include it then test the app in a web browser, the app will break and nothing will happen in the UI. Therefore, it makes the app more robust by displaying the no-camera.png file to signify the lack of availability of the camera plugin.
Upon successfully taking a photo, the camera plugin will execute the function provided as the “successCallback” parameter.
The image data is passed into the function, allowing us, in this case, to display it immediately and cache it via localStorage.
If something goes wrong or the user closes the camera without taking a picture, the “errorCallback” function is executed.
A more enhanced user experience could definitely be crafted, but for now it's enough to show the user an alert message detailing the issue.
App Code: Cordova Plugin Initialization
There is one last concept to cover that is unique to Cordova apps. Before we can access and use a plugin and its device APIs in our code, we must wait for Cordova to fully load first. Otherwise, the code will fail upon execution.
This is not an issue in this example app because the user can't interact with the camera plugin until the app fully loads anyway. However, it's worth mentioning since it's typically a source of confusion for developers.
To ensure that everything has loaded properly, attach a function to the HTML body “onload” event. Next, register a “deviceready” function that Cordova will execute when it has fully loaded. Once it has, we're free to interact with any plugins.
We now have a fully implemented, web-based, cross-platform app that allows users to access the device's camera to take and display photos. In part two, we'll cover the steps to transform it into a native Android and iOS app.
Interested in learning more about the cross-platform development approach? Check out my Pluralsight course, PhoneGap Build Fundamentals. It covers everything you need to go from zero to app store, including in-depth coverage of native plugins, testing and debugging on mobile devices, and app store submission.