Adobe
Products

Top destinations

  • Adobe Creative Cloud
  • Creative Suite
  • Adobe Marketing Cloud
  • Acrobat
  • Photoshop
  • SiteCatalyst
  • Students
  • Elements family

Adobe Creative Cloud

  • What is Adobe Creative Cloud?
  • Design
  • Web
  • Photography
  • Video
  • Students
  • Teams
  • Enterprise
  • Educational institutions

Design and photography

  • Photoshop
  • Illustrator
  • InDesign
  • Adobe Muse
  • Lightroom

Video

  • Adobe Premiere
  • After Effects

Web development and HTML5

  • Edge Tools & Services [opens in a new window]
  • Dreamweaver
  • Gaming [opens in a new window]

Adobe Marketing Cloud

  • What is Adobe Marketing Cloud?
  • Digital analytics
  • Social marketing
  • Web experience management
  • Testing and targeting
  • Media optimization

Analytics

  • SiteCatalyst
  • Adobe Discover
  • Insight

Social

  • Adobe Social

Experience Manager

  • CQ
  • Scene7

Target

  • Test&Target
  • Recommendations
  • Search&Promote

Media Optimizer

  • AdLens
  • AudienceManager
  • AudienceResearch

Document services

  • Acrobat
  • EchoSign [opens in a new window]
  • FormsCentral [opens in a new window]
  • SendNow [opens in a new window]
  • Acrobat.com [opens in a new window]

Publishing

  • Digital Publishing Suite

  • See all products
Business solutions

By business need

  • Digital analytics
  • Digital publishing
  • Document management
  • Media optimization
  • Social marketing
  • Testing and targeting
  • Video editing and serving
  • Web development [opens in a new window]
  • Web experience management
  • See all business needs

By industry

  • Broadcast
  • Education
  • Financial services
  • Government
  • Publishing
  • Retail
  • See all industries
Support & Learning

I need help

  • Products
  • Adobe Creative Cloud
  • Adobe Marketing Cloud
  • Forums [opens in a new window]

I want to learn

  • Training and tutorials
  • Certification [opens in a new window]
  • Adobe Developer Connection
  • Adobe Design Center
  • Adobe TV [opens in a new window]
  • Adobe Marketing Center
  • Adobe Labs [opens in a new window]
Download
  • Product trials
  • Adobe Flash Player
  • Adobe Reader
  • Adobe AIR
  • See all downloads
Company
  • Careers at Adobe
  • Investor Relations
  • Newsroom
  • Privacy
  • Corporate Social Responsibility
  • Customer Showcase
  • Contact us
  • More company info
Buy
  • For personal and professional use
  • For students, educators, and staff
  • For small and medium businesses
  • Volume Licensing
  • Special offers
  • Adobe Marketing Cloud sales [opens in a new window]
Search
 
Info Sign in
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Welcome,
My Adobe
My orders
My information
My preferences
My products and services
Sign out
My cart
Privacy My Adobe
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out Privacy My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Promotions
Estimated shipping
Tax
Calculated at checkout
Total
Review and Checkout
Adobe Developer Connection /

Using Parse.com with PhoneGap – Part 2: The phone strikes back

by Raymond Camden

Raymond Camden
  • raymondcamden.com

Content

  • Cell reception is your achilles heel
  • Adding Geolocation to the Mix
  • Showing the note's location
  • Where to go from here

Created

4 February 2013

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
HTML5JavaScriptPhoneGap Build
Was this helpful?
Yes   No

By clicking Submit, you accept the Adobe Terms of Use.

 
Thanks for your feedback.

Requirements

Prerequisite knowledge

You should read Part 1 of this series: Using Parse.com with PhoneGap – Part 1: A marriage made in Awesome

User level

Beginning

Required products

  • PhoneGap Build

Sample files

  • Beginning files from previous article
  • Completed sample files

In my previous article, I discussed how to integrate Parse.com into your PhoneGap application. Parse.com handles data storage for you. This gives you the ability to store data for your mobile applications in the cloud. Parse has quite a few features and my article focused primarily on simple storage techniques, but I encourage you to check out their site for more examples.

In that article, we walked through the set up of Parse as well as the creation of a simple application that stored simple "Note” objects. We didn't actually make use of any PhoneGap features. That's perfectly OK, but doesn't truly create a memorable experience for the user. One of the things that makes PhoneGap truly epic is the combination of other services, like Parse, with the device features that PhoneGap gives you access to. In this article, I'll be improving on the previous sample application by adding offline/online support, geolocation, and child browser features.

Cell reception is your achilles heel

As powerful as our little mobile devices are, they have one weakness. No, it isn't red kryptonite. It's signal strength. I live in a mid-sized city and still encounter areas where my phone mysteriously stops loading data. It is frustrating, but what makes situations like this even more frustrating are apps that don't correctly handle being offline. Certainly some apps cannot really do much if they cannot get online. Being able to recognize your network connection and handle changes is the mark of a superior application. Let's begin by doing some basic modifications to our application to handle both an initial connection check as well as a change in connection.

function onDeviceReady(e) { $(document).on("online", onlineFunc); $(document).on("offline", offlineFunc); if(!(navigator.connection.type === Connection.UNKNOWN && navigator.connection.type === Connection.NONE)) { $(document).trigger("online"); } else { $(document).trigger("offline"); } }

The code snippet above is a portion of the onDeviceReady event handler. If you have not used PhoneGap before, this may be new to you. Basically, any code that makes use of device features needs to wait for a "device-ready” event to be fired by the underlying PhoneGap framework. In the prior sample application, we relied on the jQuery document ready event. In this example, we will replace that JavaScript code, in main.js, with the code above.

Begin by adding two event handlers to the document object: one for online and one for offline. As you can probably guess, these handlers respond to a change to your connection status. First, we need to check the current status. 

First, we need to check the current status. PhoneGap's Connection object provides a simple way to check device connectivity. The value of navigator.connection.type is one of Connection.UNKNOWN, Connection.ETHERNET, Connection.WIFI, Connection.CELL_2G, Connection.CELL_3G, Connection.CELL_4G, or Connection.NONE. With these values, you see if the user has any connectivity as well as the the relative strength of the connection. This is useful for deciding if it makes sense to download large media files for example. What is a good idea on a 4G connection is not necessarily on a 2G connection. For our needs, we simply care if there is no connection at all. We also took the pessimistic view that if we cannot determine the connection at all (Connection.UNKNOWN) then we assume the device is offline. Now let's take a look at those handlers.

var parse_init = false; var online; function offlineFunc(e) { console.log('offline'); online=false; navigator.notification.alert("You are offline. Posting notes have been disabled.", null, "Offline!"); addNoteButton.attr("disabled","disabled"); if(geoWatch) navigator.geolocation.clearWatch(geoWatch); } function onlineFunc(e) { console.log('online'); online=true; if(!parse_init) { initParse(); getNotes(); } geoWatch = navigator.geolocation.watchPosition(onGeo, onGeoError, { timeout: 30000 }); addNoteButton.removeAttr("disabled"); }

We have a few things going on here in both handlers, so let's take it step by step. The offline handler first sets a global variable (online) to false. This will be used elsewhere. (Yes, we could re-use the Connection check we had earlier, but this seemed like a simpler solution.) Next, we notify the user that, due to the device being offline, functionality has been disabled. PhoneGap has a Notification API that is perfect for this. (As an added bonus, you could use the same API to vibrate the phone to ensure the user really gets the message.) After the notification we then disable the button used to add notes. And finally, we clear out any geolocation activities the device may be doing. (You'll see where that starts up in a second.)

Now turn your attention to the online handler. As before, we update a global variable reflecting our connection status. The next block handles Parse initialization. As this can only be run once, it is checks the value of parse_init to see if it has already been set. Since we mentioned earlier that geolocation would be part of our updates, the watchPosition call here asks the device to report the user's current position and reports on changes. Finally, we remove the disabled attribute (if it is there) from the button used to add notes.

The initParse() function simply contains the Parse setup logic that was detailed in the previous article:

function initParse() { Parse.initialize(PARSE_APP, PARSE_JS); NoteObject = Parse.Object.extend("NoteObject"); parse_init=true; }

Adding Geolocation to the Mix

You've seen already where geolocation support was added - both to the online and offline handlers, but let's look at how this data is actually used in the application. The online handler made use of the "watch” feature in Geolocation. This will use the device's GPS to figure out the user's location as well as handling any changes to that location. When I set up the watch I specified onGeo for the success handler and onGeoError for any errors. Because we want to add location to our note objects as an enhancement, the onGeoError handler actually does nothing at all (rather than causing an error, we'll simply leave geolocation data off the note).

function onGeoError() { //So yeah, do nothing and I'm ok with that. }

Obviously you could do something more here if you wanted, but for now we will leave it open. The success handler is going to copy the values into a global variable.

var geoPoint; function onGeo(g) { geoPoint = {latitude:g.coords.latitude, longitude:g.coords.longitude}; }

Now that we've got the user's location, how do we use it? We could simply pass them into the data stored at Parse. Remember, Parse lets you store anything. But instead we'll take advantage of Parse's special support for handling location objects. Let's take a look at the handler fired when user's click the Add Note button to see how this works.

$("#addNoteBtn").on("touchend", function(e) { e.preventDefault(); //Grab the note details, no real validation for now var title = $("#noteTitle").val(); var body = $("#noteBody").val(); var note = new NoteObject(); note.set("title", title); note.set("body", body); //if we have _some_ data if(geoPoint.longitude) { note.set("position", new Parse.GeoPoint({latitude:geoPoint.latitude, longitude:geoPoint.longitude})); } note.save(null, { success:function(object) { console.log("Saved the object!"); $("#noteTitle").val(""); $("#noteBody").val(""); getNotes(); }, error:function(object,error) { console.dir(error); alert("Sorry, I couldn't save it."); } }); });

We've made two significant changes to the handler. First, we no longer pass in a structure of data to the first argument of the save() call - notice it is null now. Instead, we use the set() API on the note object to set our values. We can then use a simple conditional to see if we have the user's location. If we do, we pass in a new instance of Parse.GeoPoint. By using a GeoPoint, it enables my application to do a number of geolocation based queries. While I won't be using it in this demo application, we could now use the Parse API to query for notes posted within a certain distance of a location. This is very powerful and Parse makes it incredibly easy.

Showing the note's location

So now that we have location data available along with our basic note text, how do we make use of it? One way would be to show it on a map. Google provides comprehensive mapping support, but for our purposes we can get by using their simpler Static Maps API. This API provides for basic mapping that doesn't require interactivity. By creating a URL that includes location data and other parameters, you can create a simple map that shows up as a basic image. But where do we show it?

One of the recent additions to PhoneGap (in version 2.3.0) is the addition of the InAppBrowser API. For folks who made use of the Child Browser plugin in the past, this will be familiar. Essentially, this lets you create a window above your application. It is useful for tasks like displaying web links that exist in a context outside of your application. It even provides multiple hooks into the window for noticing things like page loads and when the user closes the window. Luckily for us our needs are much simpler. Let's look at the modified version of the getNotes function.

function getNotes() { var query = new Parse.Query(NoteObject); query.find({ success:function(results) { console.dir(results); var s = ""; for(var i=0, len=results.length; i<len; i++) { var note = results[i]; s += "<p>"; s += "<b>"+note.get("title")+"</b><br/>"; s += "<b>Written "+note.createdAt + "<br/>"; //Do we have a geo point? if(note.has("position")) { var pos = note.get("position"); s += "<a href=\"\" class=\"navLink\" data-longitude=\"" + pos.longitude +"\" data-latitude=\"" + pos.latitude+"\">View on Map</a><br/>"; } s += note.get("body"); s += "</p>"; } $("#notes").html(s); }, error:function(error) { alert("Error when getting notes!"); } }); }

Our changes begin in the result loop. I've added new code to handle checking for the existing of a position value. Remember, not all of our data may have it. If it does exist, I add some more HTML to our result. This includes a simple HTML link with a class of navLink. Also, note the use of data attributes to store the position values. In order to make these links work I've got an event handler just for touch events on them.

$(document).on("touchend", ".navLink", function(e) { e.preventDefault(); //If we are offline, say we're sorry and move on.. if(!online) { navigator.notification.alert("Maps can only be viewed online.", null, "Offline!"); return; } //Get the position from the data attribute var long = $(this).data("longitude"); var lat = $(this).data("latitude"); //Generate Google Static Map API link var link = "http://maps.googleapis.com/maps/api/staticmap?center="+lat+","+long+"&zoom=13&size=400x400&maptype=roadmap&markers=color:red%7Ccolor:red%7C"+lat+","+long+"&sensor=false"; window.open(link, "blank"); });

After blocking the normal link event, our code ensures the user is online. If they aren't, the user is notified and the handler exits. Next, we grab the location data from the HTML and create a link using the Static Map API. Even if this is your first time seeing the API, you should be able to take a good guess as to what the link is doing. Finally the link is opened using the traditional window.open API. Here's how the content looks in the iOS Simulator (Figure 1).

Figure 1. Content in the iOS Simulator.
Figure 1. Content in the iOS Simulator.

Add here is what you get when one of the “View on Map” links is clicked (Figure 2).

Figure 2. Screen after a "View on Map" link is clicked.
Figure 2. Screen after a "View on Map" link is clicked.

Notice how the InAppBrowser API creates the typical browser chrome automatically. There is also a "Done” button that dismisses the window. What is not obvious in the screenshot is the nice transition when both opening and closing the window.

Where to go from here

Hopefully by now you are beginning to see the power of mixing PhoneGap with Parse. By offloading data storage to Parse we have a simple way to keep user data backed up and accessible even if they lose the device. By using PhoneGap, you have access to the device connection status as well as the GPS location. You can take the sample code attached to this article and upload it to PhoneGap Build today and use it to create your own application!

Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License+Adobe Commercial Rights

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

More Like This

  • Getting started with Kendo UI Mobile
  • Using Parse.com with PhoneGap – Part 1: A marriage made in Awesome
  • Android Push Notifications with PhoneGap
  • Building PhoneGap applications powered by Database.com

Products

  • Adobe Creative Cloud
  • Creative Suite
  • Adobe Marketing Cloud
  • Acrobat
  • Photoshop
  • Digital Publishing Suite
  • Elements family
  • SiteCatalyst
  • For education

Download

  • Product trials
  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR

Support & Learning

  • Product help
  • Forums

Buy

  • For personal and professional use
  • For students, educators, and staff
  • For small and medium businesses
  • Volume Licensing
  • Special offers

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2013 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy | Cookies

Ad Choices

Reviewed by TRUSTe: site privacy statement