Chapter 4. Using plugins to access device features

This chapter covers

  • What plugins are and what they provide for Cordova projects
  • How to find and evaluate plugins
  • How to use the CLI to manage plugins
  • How to use the deviceready event

So far you’ve concentrated on using the Cordova CLI to translate web stuff (HTML, JavaScript, and CSS) to native code. You’ve seen how to create a Cordova project and how to test it as a native application on either an emulator or a real device. The last piece of the puzzle is tapping into the rich set of device features that websites do not have access to: the filesystem, the camera, and so on. This was mentioned in chapter 3 as a problem with your simple application. This is where plugins enter the picture.

4.1. What are plugins?

Suppose you want to write a Cordova application to access your phone’s camera and take a picture. JavaScript, by itself, doesn’t have access to the camera. One of the great features of Cordova is that it provides a mechanism to allow JavaScript to access things it normally wouldn’t be able to. This is done via plugins.

Plugins work by providing a way for your JavaScript to communicate to the device. Figure 4.1 illustrates this.

Figure 4.1. Cordova plugins stand between and facilitate communication between JavaScript and the device.

Plugins are code written in native languages (Objective-C, Java, and so forth) that provide a hook that can be called by a JavaScript file loaded by your Cordova application. They allow your JavaScript code to do things it wouldn’t normally be able to do. There’s no camera.getPicture() function available to mobile browsers, but by using plugins, Cordova provides support for doing just such a thing. The Cordova version (and you’ll see a full example later in this chapter) looks like so: navigator.camera.getPicture(). This only works because the plugin behind the camera support adds this functionality.

For a plugin to work across multiple platforms, multiple versions of the plugin are built. Taking the Camera plugin feature as an example, someone must create native code for Android, Windows Phone, iOS, and other platforms that can access the device camera. Once that’s done, one JavaScript API can be used so your code will work the same (or close enough) on all those platforms. Luckily there are quite a few plugins available for you to use in your Cordova projects.

4.2. Finding (and evaluating) plugins

Before we get into using plugins in your Cordova project, let’s discuss how you find them. While you can write your own plugins (to be discussed in chapter 8), most people find their plugins online. You used the command line npm to install Cordova; as mentioned previously, npm is a tool often used to install other programs. Cordova plugins are now (a very recent change) stored at www.npmjs.com so you can search for them there. At the time this chapter was written, there were nearly 150,000 npm packages available, but you can search for Cordova plugins using ecosystem:cordova in the search box. Or simply bookmark www.npmjs.com/browse/keyword/ecosystem:cordova. The search results are shown in figure 4.2.

Figure 4.2. Cordova assets at www.npmjs.com/package/cordova-plugins

Note that this search returns plugins and related Cordova assets. For example, cordova-app-hello-world is the source for the www folder in new Cordova projects. Providing a way to search for only plugins is something that’s currently being worked on.

You probably won’t have any trouble finding a plugin for common needs. What’s more difficult is evaluating which plugin makes the most sense for your project. Given that you can find a plugin to support some particular need, how do you handle figuring out if the plugin is well written? Or what do you do when multiple options exist? In general, the same types of checks you should make for any open source project will apply here as well.

  • How long ago was the plugin updated? —Typically I look for a plugin updated within three months. I also mentally sort plugins by when they were last updated. Given two plugins that match a particular need, I’ll automatically give precedence to the one updated most recently.
  • Is the plugin used by many people? —While it’s impossible to tell exactly how many people are using a plugin, the Cordova Plugins Registry does report on the number of downloads for a particular plugin. As with the date it was last updated, I’ll typically check the plugin with the most downloads first.
  • Are there many open issues for the plugin? —Any project is going to have bugs. The question is, how quickly does the author respond to and try to fix those bugs? If you see a plugin with many open issues, and ones that are quite old, it may be another sign of an abandoned project.

For the most part, we’ll be focused on the core plugins that are maintained by the Apache Cordova project. Technically every plugin is just as usable as any other, but there is a set of plugins maintained by the Apache Cordova team that is kept up to date and tested on the platforms supported by Cordova. These plugins once were part of the core Cordova framework itself, but in version 3, every feature was converted into a plugin. This was done so that developers didn’t have to ship code for a feature they weren’t using. The core plugins are:

  • Battery Status (cordova-plugin-battery-status)
  • Camera (cordova-plugin-camera)
  • Console (cordova-plugin-console)
  • Contacts (cordova-plugin-contacts)
  • Device (cordova-plugin-device)
  • Device Motion and Orientation (cordova-plugin-device-motion and cordova-plugin-device-orientation)
  • Dialogs and Vibration (cordova-plugin-dialogs)
  • File System and FileTransfer (cordova-plugin-file and cordova-plugin-file-transfer)
  • Geolocation (cordova-plugin-geolocation)
  • Globalization (cordova-plugin-globalization)
  • InAppBrowser (cordova-plugin-inappbrowser)
  • Media and Media Capture (cordova-plugin-media and cordova-plugin-media-capture)
  • Network Information (cordova-plugin-network-information)
  • Splashscreen (cordova-plugin-splashscreen)
  • Vibration (cordova-plugin-vibration)
  • StatusBar (cordova-plugin-statusbar)
  • Whitelist (cordova-plugin-whitelist)

We’ll discuss those cordova-plugin values in a bit.

Another Option

You can also browse plugins at Telerik’s Verified Plugins Marketplace (http://plugins.telerik.com/). Telerik constantly updates this list to ensure the listed plugins actually work and are well maintained.

4.3. Managing plugins and the Cordova CLI

Now that you know what plugins do and where to find them, how do you get them into your project? The Cordova CLI provides a method to add new plugins, remove existing plugins, list what’s installed, and search against the main registry. The simplest action to take is to list the current plugins for a project. Navigate to any existing project, and simply type cordova plugin. This will output a list of plugins that for you will most likely be blank. Note that you can use the alias plugins instead of plugin. Either works just fine.

Adding a plugin is done via the cordova plugin add command. There are a couple of different options you have in terms of from where the plugin will be loaded, but for the purposes of this book you’ll use the pluginid value—that is, the cordova-plugin values you saw in the list of core plugins. The command diagram at right demonstrates this.

The result of this command can be seen in figure 4.3. In the figure, pay particular attention to the last line. For this project, the only installed platform was for iOS. Basically, the Cordova CLI grabbed the plugin and then prepared it for the platforms your project supports. The CLI is intelligent enough to know that if you decide to add Android, it needs to install the Camera plugin, as demonstrated in figure 4.4.

Figure 4.3. Response from the Cordova CLI after adding the Camera plugin

Figure 4.4. After installing Android, the currently installed plugins are copied to the new platform.

Removing a plugin is simply a matter of using cordova remove and the ID of the plugin you want to remove. As before, the CLI is intelligent enough to know what platforms you’ve installed for a project and will correctly remove the plugin from each, as shown in the command diagram at right.

The search option is useful if you can’t remember the name of a plugin. The CLI searches against the website (http://plugins.cordova.io) and returns the results at your command prompt. Figure 4.5 demonstrates the result of searching for “camera.”

Figure 4.5. Searching for the Camera plugin

Once you’ve installed a plugin, you can begin using it in your code. How you use a plugin will depend on what it does. Each plugin has its own API and documentation. Later in the chapter we’ll go over a few example plugins so you can see them in action. Just remember that every plugin is unique. Be sure to carefully read its documentation to know how to correctly use it.

4.4. Plugins and the development cycle

In chapter 3 we outlined the development cycle for a typical Cordova project. How does working with plugins change this? Not much! Figure 4.6 demonstrates the updated process.

Figure 4.6. Final flow chart of the Cordova development process

As you can see, we’ve simply added a new step (add plugins) to the flow. You can add plugins late in the development process (perhaps the client changes the requirements right before release, something that never happens, right?). But typically, much like with platforms, you’ll set up your plugins at the beginning of your project.

4.5. The deviceready event

You’ve seen how to find plugins. You’ve read about how to perform due diligence and judge the health of a plugin. You’ve seen how easy it is to use the CLI to install, list, and remove plugins from your project. Most likely you’re excited to jump into development and start doing cool things with the camera and other device features.

First, there’s a critically important aspect of Cordova development that you need to learn. Before your application can talk to a plugin, Cordova has to set up a line of communication between your code and the device. That sounds complex, but it really isn’t. Basically, Cordova knows what it has to do on each supported platform to let plugin code access device hardware. All you have to do is wait for Cordova to finish. So how do you know when this has happened? All Cordova applications will fire an event called deviceready which can be listened to in your JavaScript code. So why did the real (but simple) application in chapter 3 work? Because you weren’t doing anything special. Listening to events in JavaScript is fairly simple.

At the most simple level, the DOM method addEventListener() is what you’d use to create a listener for an event. If you use jQuery, you’d use the on API. The following listing demonstrates this.

Listing 4.1. deviceready example

Pretty much every single Cordova application will make use of the preceding code block. The name of the function that will be run, init in the listing, is completely up to you, but should be named something obvious. If you do any jQuery work you may be familiar with using $(document).ready as a way of delaying your code until the DOM is ready. For the most part you can mentally exchange that with the deviceready handler and use it in much the same way.

4.6. Plugin example: Dialogs

For our first example of a plugin we’ll look at the Cordova Dialogs plugin. It provides native dialogs and audio notifications to your Cordova application and is a big improvement over what JavaScript provides by default. After I demonstrate how to use the plugin and why it’s better than the default JavaScript method, you’ll use it in a sample application.

4.6.1. Better dialogs with the Cordova Dialogs plugin

JavaScript has long had a way to create dialog, or modal, windows. While these methods work, they tend to be avoided as they cannot be styled and can be overly obtrusive. When used in a mobile browser they can be even more obtrusive. In figure 4.7, a Cordova application is using the alert() method to display a message to the user.

Figure 4.7. A default alert() method in a Cordova application

Notice that the dialog has a title on top, index.html. This cannot be changed or modified and immediately flags your application as being a web page. The OK button cannot be changed either. Now compare the same (well, a similar) use of the Dialogs plugin’s alert() method in figure 4.8.

Figure 4.8. A cleaner, more professional dialog

By switching to the Dialogs plugin, you have a much nicer dialog. You can customize the title as well as the button. You cannot control things like color and fonts, but you can still create a much better-looking dialog with minimal effort.

4.6.2. Building an application with the Dialogs plugin

Dialogs are used to alert the user about something important happening in your application. What that important event is doesn’t necessarily matter, but the idea is that you want to get the user’s attention. For this first example you’ll create an application that lets you test all of the methods of the Dialogs plugin:

  • Alerts are modal dialogs (miniwindows) that float on “top” of the application. Use this when you want to present a message to the user.
  • Prompts are also modal, but ask the user to type something in. Like alerts, they’re modal.
  • Confirmations ask the user to specifically accept or deny a particular action. Use this when you want to ensure the user really wants to perform some action while also providing the user a quick way to say no.
  • Beeps make noise. You can use this with the dialogs to really get the user’s attention.

Beeps are—obviously—not a dialog but an auditory alert; but as they’re pretty simple to use we’ll demonstrate them as well. Your final application, as shown in figure 4.9, will provide a set of buttons to test each aspect of the plugin.

Figure 4.9. Sample application demonstrating the Dialogs plugin

Each of the buttons tests one aspect of the plugin and is labeled appropriately. To create this application, you can follow the same procedure you did in chapter 3. If you extracted the book’s zip file to /Users/mary/Downloads/cordovabook, you can create a new Cordova project and seed it with the code for this example like so:

cordova create notificationdemo --copy-from=/Users/mary/Downloads/
     cordovabook/c4/dialog_demo

Don’t forget that before you can make use of a plugin, you need to install it. In the new project you created, run the following command:

cordova plugin add cordova-plugin-dialogs

You can also create a new project and then modify the code to match the code displayed next. Let’s begin by looking at the index.html file shown in the following listing.

Listing 4.2. Dialog demo homepage (index.html)

For the most part there isn’t much to talk about here. The application is rather simple—four buttons and nothing more—so the HTML part of the project is only a few lines long. This example calls out to an application-specific CSS file and a JavaScript file . You may be curious about the line that loads cordova.js . If you look at your project folder, this file doesn’t actually exist because this JavaScript file is injected by the Cordova CLI itself when you create a platform-specific build. So when you tell it to create an iOS build, for example, an iOS version of the cordova.js file will be copied along with everything else you write. If you have an Android version, the same thing happens but an Android-specific version is used instead. As a Cordova developer, you don’t have to worry about providing the file, but you must include a <script> tag loading it so your project can function correctly.

Let’s look at the CSS file shown in listing 4.3. Note the use of app.css and app.js in this application just because it makes it obvious that these files are application-specific and not part of some third-party library. There’s nothing special about “app” being used in the name. It’s nothing more than a convention.

Listing 4.3. Application CSS file (app.css)
body {
     margin: 20px;
}

button {
     padding: 10px;
     width: 100%;
     font-size: 1em;
}

That’s it. Only a few lines to add a margin around the body and make the buttons a bit easier to see on a mobile screen. In later chapters we’ll look at how to make this better. Now let’s look at the final part of the project, the JavaScript file, shown in the following listing.

Listing 4.4. Application JavaScript file (app.js)

The more important aspect of this JavaScript file is the initial event listener for deviceready. As noted earlier in the chapter, before you do anything with device features you must listen for this event. Therefore, the majority of the code for this application is nestled inside that function. The Dialogs plugin is documented at www.npmjs.com/package/cordova-plugin-dialogs, and the code simply demonstrates an example of each of the four methods supported by the plugin.

The alert() method

The alert() method allows for customization of the body (first argument) and title (third argument), as well as the button (fourth argument). The second argument, which is specified as null, is a callback function to run after the alert is dismissed. If you wanted your application to do anything at that point you could define it there. Figure 4.10 demonstrates the result.

Figure 4.10. Demonstrating the alert() method

The confirm() method

The confirm() method works similarly to the alert() method. Note though that you can actually specify multiple buttons instead of a default set of two. For the confirm() method example you want to display what the user clicked so you use the callback to alert it, as shown in figure 4.11.

Figure 4.11. Side-by-side demonstration of the confirm() method and the result

The prompt() method

The prompt() method is also pretty similar to the last two—you provide a default prompt, a callback, the title of the dialog, a set of buttons, and an optional default. The callback is a bit more complex. It’s passed a result object that contains a key for the input (input1) and the index of the button selected (buttonIndex). For your application you alert back what the user entered, as shown in figure 4.12.

Figure 4.12. On the left is the prompt with the default answer. If the user changed it to say “MORE COOKIES!” then the result on the right would be shown.

The beep() method

The most simple method of the plugin is beep(). You simply pass in the number of beeps to make; the sound will be based on the user’s default notification sound. Please use this method with caution and resist the urge to pass an incredibly large number to it. In case you’re curious, you can do both a beep and an alert at the same time to get the user’s attention:

navigator.notification.beep(2);
navigator.notification.alert(
      "Wake up! ", null, "Alert Test", "OK! ");

If you click the buttons and nothing happens, most likely you forgot to include the plugin as instructed earlier. Figuring out mistakes like this will be covered in chapter 8 when we cover debugging techniques.

4.7. Plugin example: Camera

Now that you’ve seen the power of a simple plugin in action, let’s kick it up a notch and talk about one of the more popular plugins, Camera. From Instagram to Facebook, users love taking pictures. The Camera plugin lets you prompt the user to take a new picture or select from the gallery. It has multiple options for where the image ends up and lets you control the size of the picture returned to your application. At the most simple level you can prompt the user to take a picture and then render that picture in your application. More advanced applications can use these pictures by uploading them to other services and manipulating them.

This demo provides buttons to prompt the user to either take a new picture or select one from the device, as shown in figure 4.13.

Figure 4.13. Default view of the application

Once the user has selected an image, it will be displayed in the application and styled a bit, like figure 4.14.

Figure 4.14. A selected picture displayed in the application

Now let’s look at the code. Don’t forget to actually create the new project. As before, you can use the CLI’s --copy-from feature to point to the code you downloaded for the book. For this application to work correctly in your emulator, or device, you’ll need to install not one but two plugins:

cordova plugin add cordova-plugin-camera
cordova plugin add cordova-plugin-dialogs

Using multiple plugins is a perfectly normal part of Cordova development and it will not be unusual for your application to use many of them.

Let’s begin by looking at the HTML for the application, shown in the following listing.

Listing 4.5. Application HTML page (index.html)

As before, because the application is so simple, the HTML doesn’t have much to it. For the most part it comes down to the two buttons (, ) used to prompt the user to take or select a picture. The empty image will be used to display what the user takes or selects. The CSS file shown in the following listing is similar to the previous application with the addition of a new style for the image.

Listing 4.6. Application CSS file (app.css)

The sepia filter is used to colorize the selected image. You can think of it as an Instagram filter done simple. Now review the JavaScript in the following listing.

Listing 4.7. Application JavaScript file (app.js)

Once again the code begins with an event listener for deviceready , a consistent technique for your Cordova applications. Both buttons (shown in figures 4.13 and 4.14) make use of touch events to listen for user action. Both make use of the core Camera plugin functionality to get pictures, navigator.camera.getPicture. The only difference in the two calls (, ) are the options. The first button that’s requesting a new picture uses a source of Camera.PictureSourceType.CAMERA. This means a new picture driven by the device camera. The second button uses a source of Camera.PictureSourceType.PHOTOLIBRARY, which represents an existing picture from the device’s photo gallery.

The Camera plugin can send the picture as either Base64 data (a text representation of binary data) or from the location of the picture on the device’s filesystem. In general, using the FILE_URI destination as used here is almost always preferred because it uses less memory then the Base64 version. (This is discussed on the plugin’s documentation page.) Once the camera action is complete, the success handler is run and, because you’re passing in a file URL, you can set that to the blank image created in the HTML page. Note as well the error handler. It’s using the nice dialogs described earlier.

4.8. Plugin example: Contacts

For our final example we’ll work with the Contacts plugin, which (no surprise here) lets you add, edit, and delete contacts. That’s handy. A more typical use for contacts is to find a contact to be used in some other action. Imagine you’ve made use of the Camera plugin. Because you’ve just taken what is obviously the best picture of a cat ever, it would be even cooler if you could share that picture with a friend. The Contacts plugin would make it easy to let you find that friend and fetch their email address, or phone number, so that your friend too can bask in the awesomeness of your cat photo.

While the plugin provides a find() method for low-level searching, it has a better method of asking the user to select a contact. The plugin can ask the device to use its default Contact Picker UI that’s shared among other native applications. This provides a familiar user experience to the person working with your application. By using the navigator.contacts.pickContact() method as provided by the plugin, you can display the appropriate UI for the device’s OS, as shown in figure 4.15.

Figure 4.15. How iOS (left) and Android (right) handle contact picking

The application will make use of this API to simply prompt the user to select a contact. After a contact is selected, information about the contact will be displayed in the application, as shown in figure 4.16.

Figure 4.16. Example of a selected contact

In doing so though, you’ll discover one of the issues you run into from time to time with plugins: platform quirks.

The documentation for the Contacts plugin (www.npmjs.com/package/cordova-plugin-contacts) discusses how the plugin works and points out oddities or quirks for an individual plugin. While all plugins strive to work exactly the same across their supported platforms, sometimes this is not possible.

Tip

While most developers know it’s important to read the documentation, most of us probably don’t do a great job of it. I recommend paying attention to the quirks when using any plugin. Many times I’ve lost time to debugging something that ended up being a quirk that I simply didn’t pay attention to.

For the Contacts plugin there’s one quirk in particular that’s going to impact the sample application. The docs say this:

displayName: Not supported on iOS, returning null unless there is no ContactName specified, in which case it returns the composite name, nickname, or “ ”, respectively.

Interesting. So if the application is going to display a contact, it will need to be prepared to handle running under iOS and not having access to that particular property.

I know you didn’t forget to create a new project and add the plugins, right? This project makes use of both the Contacts plugin (cordova-plugin-contacts) and Dialogs plugin (cordova-plugin-dialogs).

Let’s look at the code. The first template is the index.html file for the application shown in the following listing.

Listing 4.8. Contact demo HTML file (index.html)

As with the other examples, the HTML is rather simple. You’ve got one button you’ll use to fire off the Contacts plugin and an empty div that will be filled with details from the selected contact .

Now let’s look at the JavaScript code for the application shown in the following listing.

Listing 4.9. Contact demo JavaScript file (app.js)

As in the previous examples, the code begins with a listener for deviceready. By now this should be familiar territory. The plugin API, navigator.contacts.pickContact , only takes two arguments: a success callback and a failure callback. The success callback is passed an instance of a Contact object, a basic representation of a particular contact. The documentation fully covers all the keys but for the purposes here, only a few are displayed. Note that some properties are arrays and can be iterated over. Make note of how to handle the iOS issue mentioned earlier. The getName() function will check to see if displayName() is null and, if so, try to find an appropriate value elsewhere. If all else fails it will return Nameless.

In the previous chapter, we discussed a few problems with the sample application you created. It didn’t make use of any native features. In this chapter you’ve seen how easy it is to make use of those features using plugins. We also demonstrated how the application wasn’t necessarily designed well for the mobile environment. The next chapter will cover this.

4.9. Summary

Let’s review the major topics covered in this chapter.

  • Plugins are what provide real power to Cordova applications.
  • Plugins can be fully managed via the command-line tool.
  • All code that makes use of plugins must wait for the deviceready event to fire.

In the next chapter we’ll cover how to design applications for the mobile environment.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
34.231.180.210