Twitter: raymondcamden


Address: Lafayette, LA, USA

Using Ripple for PhoneGap Development

02-06-2013 30,373 views Mobile, Development, JavaScript 19 Comments

Ripple has been around for a while now, but only recently have I really noticed how freaking cool it is. I thought it might be helpful for my readers if I wrote up an introduction guide to Ripple and how you can more effectively use it. This will be a reflection of the issues and cool things I've run into personally and as always, I'd love to hear your opinions as well.

First and foremost, what in the heck is Ripple? Ripple is an open source project in incubation status at Apache (http://incubator.apache.org/projects/ripple.html). Its aim is to allow your browser to emulate a mobile device. Currently it has support for both Blackberry WebWorks and PhoneGap. For this blog entry I'll just be focusing on PhoneGap.

It works via a Chrome extension, which means, obviously, it is Chrome only. You can get the plugin by either searching in Chrome's online store or by simply clicking here.

Once installed, your Chrome browser will get a new icon up by the URL:

The extension works with any HTTP-based URL, even your local server. You aren't required to upload your files to a public host. As a test, you can simply point to an HTML file on your local server and then click the Ripple icon.

Click to enable Ripple and the page is reloaded with the Ripple emulator UI. Note - Ripple will (should) remember this setting. If you return to the page later it automatically loads Ripple. Just click the icon again to disable Ripple for that site. (Note - I'm not 100% sure on how long this 'sticks' - you may see something different.)

There's a heck of a lot going on here. Each of the boxes surrounding your app allow for various configuration/testing options, but if you want to focus on just your app you can click the little arrows above the device simulator to hide them.

You can selectively close them as well. (I.e., keep the right one open but close the left.)

For the most part the UI here should be self-explanatory. I'll go through it anyway to provide some additional context.

Devices

The devices pod allows you to select from a pretty large set of options. What's cool is that this integrates fully with PhoneGap's Device API. If you run the example code for the API and toggle between different devices, you see the right results in Ripple. Here are some examples.

Platforms

To be honest, I never need to touch this. You can select PhoneGap 1.0.0 if you really want to, but honestly, I just leave it at the default. It always seems to default to PhoneGap 2.0.0 for me.

Information

Never use it. I suppose it is useful, but I'd just click the header to minimize it.

Accelerometer

This allows you to test motion-enabled applications. You can either click on the little device and move your mouse or just click the Shake button. Everything described in the PhoneGap Accelerometer API should work fine here. I blogged an example application of the accelerometer last month that made use of Ripple.

Settings

Again, should be obvious. Tooltips and Themes simply provide some UI options to Ripple itself. However, the Cross Domain Proxy is a very important one.

One of the issues you run into when using your desktop browser for mobile development is the inability of your Ajax code to make cross domain requests. This is a browser security issue and is pretty darn well out of your control. There are options though. In Chrome, you can start the browser with a flag to bypass that restriction. Another option is to just use JSON/P. Finally, if the remote service uses CORS, then you can just use the API without worry.

Ripple allows you to use remote APIs directly by simply using a proxy service. So when your code requests foo.com/fancy.api, Ripple intercepts this, makes a request for the data from its own server, and proxies the result back to you.

For the most part this just works, but I've run into two situations now where it caused problems.

First - I did some testing a while ago against an API where everything worked fine in Chrome by itself (when using the flag to allow cross domain calls), but failed in Ripple. Why? I forgot that the API had employed remote IP rules. It worked fine from my IP, but not the remote IP. To fix that, I simply asked my friend to temporarily remove the IP rules.

Second - Ripple's proxy completely borked Parse.com calls. I'm not exactly sure why, but it just did.

Luckily, there is an easy fix for that. Parse.com can work with CORS, and Ripple now lets you disable the proxy.

I tested this a few minutes ago with a Parse.com demo and as soon as I disabled it, it worked fine in Ripple.

Device & Network Settings

This allows you to set the connection type as well as simulate lag. Again, this is fully compliant with PhoneGap's Connection API. My latest article for the Adobe Developer Connection (Using Parse.com with PhoneGap – Part 2: The phone strikes back) discusses using the Connection API to enable/disable UI items based on network availability. It works great with Ripple.

Geo Location

You wouldn't normally need any help with Geolocation since it works just fine in Chrome, but Ripple lets you emulate different locations. This is incredibly helpful during testing.

Config

If you are using config.xml files for your PhoneGap app, then Ripple will attempt to read and parse the XML file. Here is an example.

Events

Finally, the Event section lets you simulate various events. This is not a complete list of events supported by the PhoneGap Events API. As an example, the battery events are missing. But you could easily go into your console and trigger those events by hand if you need to.

What Else?

So to be honest, one of the reasons I avoided Ripple in the past is because I believed that's all Ripple supported. But that's not the case. For example, Ripple supports the PhoneGap Camera API. It works by simply asking you to upload a picture instead. Here is an example of what you would see if your app requests the device camera.

Hitting Select File gives you a regular browser based file selector. Once you select a file, you even get a preview, much like a real device.

Another feature that works is notification - partially. You can fire off a notification.alert but the title and button value attributes are not used. The callback worked, but fired immediately, not after I closed the alert. Vibration worked by simply shaking the simulator (which would be a pretty incredible vibration in real life I think).

Beep did not, but it brings up something cool. So what happens when you call an API not supported by Ripple?

As you can see, Ripple noticed the problem but provided you a quick way to handle it. You can type in a JSON result to 'fake' the result you expected.

How about the Compass API? Yep, it works too. If you modify settings under Geo Location you will see them reflected in calls to the compass API. Again - I had just assumed that panel was for one feature. It never occurred to me that it would work with the compass.

How about the Contact API? Create works just fine, although it isn't obviously storing a new contact on your desktop. Search fails, but again, Ripple handles it nicely, letting you paste in a JSON response.

How about the File API? This is one I haven't played with yet. Chrome supports the File System API, so some parts should "just work", but I'd be surprised if the File Transfer portion works at all. (Then again, every time I think Ripple can't do something it surprises me.)

Globalization does not seem to be supported at all currently. Ditto for Capture and Media. I didn't even try Splashscreen since it involves native settings as well.

Since the InAppBrowser API uses window.open, this will just plain work, but I'd imagine the various events will not be supported.

And finally, Storage is just WebSQL so it will work fine in Chrome.

I'll wrap this up with one pretty crucial tip. When using Ripple, you do want to include a script tag that points to a copy of cordova.js. Unlike PhoneGap Build, this will be a real file on your file system. It is crucial that you use the Android version, not iOS. I lost time today trying to debug a very odd issue. My deviceready event was firing twice (and by the way, did I mention Ripple handles firing this for you automatically). The culprit turned out to be the iOS cordova.js file. Very odd, but luckily it was easy enough to get around.

As a last tip, you can find links to the source and support forums at http://ripple.tinyhippos.com/.

19 Comments

  • Commented on 02-06-2013 at 4:00 PM
    Awesome write-up! I love Ripple and think it's seriously underrated.
  • Commented on 02-08-2013 at 5:41 AM
    Awesome write-up indeed, thanks so much! This sentence "Ripple supports the PhoneGap Camera API" made me install it immediately. So useful in my current app project!
  • Commented on 02-08-2013 at 6:58 AM
    Glad you guys both like it. :)
  • Vaughn #
    Commented on 02-13-2013 at 1:05 PM
    Great writeup. I'm also using Ripple debug hybrid Android development in Phonegap. I'd just like to add that I start a less secure copy of Chrome to bypass the Same Origin Policy issues.

    To do this I start chrome.exe with the following args:
    chrome.exe --allow-file-access-from-files --enable-extensions --disable-web-security --user-data-dir=D:\tmp\chromedevuser

    And I have disabled the Cross Domain Proxy in Ripple.
  • Andy Idema #
    Commented on 05-06-2013 at 2:22 PM
    Hi Ray. You say "In Chrome, you can start the browser with a flag to bypass that restriction." Can you please explain how to do that? Thanks.
  • Commented on 05-06-2013 at 2:27 PM
    It is a command line flag. On OSX it is: open -a /Applications/Google\ Chrome.app --args --allow-file-access-from-files --disable-web-security
  • netalex #
    Commented on 05-15-2013 at 3:47 PM
    hi, you say something about inAppBrowser: wich is the json we have to pass to ripple to use it? TNX
  • Commented on 05-16-2013 at 12:28 PM
    Eh? I don't get you. If you look at the docs for InAppBrowser, you will see it is just window.open.
  • netalex #
    Commented on 06-13-2013 at 8:09 AM
    it was just that in some test i've got that "i haz cheesburger" pop up also for inAppBrowser but it was my mistake, now it's fixed, sorry.
  • Commented on 08-22-2013 at 7:15 AM
    I am using Ripple to analyze a PhoneGap program which I am developing. However, using Ripple l to replicate PhoneGap activities does not seem to fire them.
  • Commented on 08-22-2013 at 8:49 AM
    Unfortunately, Ripple has been broken with PG since 2.7. I do not have a status update on it yet. When it works again, I will post.
  • Commented on 12-10-2013 at 10:56 AM
    For those who don't follow Raymond's blog constantly: http://www.raymondcamden.com/index.cfm/2013/11/5/R...
  • Commented on 05-27-2014 at 5:16 AM
    I'm trying to use File API with Ripple.
    After getting access to filesystem, I try to create a new file, but I always get an error: FILENOTFOUND.
    The same code works without problems in devices or in emulators (android or ios).
    I googled very much and done so may tests: nothing worked.
    Here is a sample code:

    document.addEventListener("deviceready", onDeviceReady, false);
    function onDeviceReady() {
       navigator.webkitPersistentStorage.requestQuota(1024*1024, function(grantedBytes) {   // This requestQuota seams to be a specific need for Chrome, on device and emulator is not needed
          window.requestFileSystem(LocalFileSystem.PERSISTENT, grantedBytes, gotFS, fail);
       }, function(e) {
          console.log('Error', e);
       });
    }

    function gotFS(fileSystem) {
       fileSystem.root.getFile("readme.txt", {create: true, exclusive: false}, gotFileEntry, fail);   // Here is where the error occur and fail will be called
    }

    function fail(error) {
       console.log(error);
    }

    function gotFileEntry(fileEntry) {
       ...
    }

    Anyone can help?
  • Commented on 05-27-2014 at 5:28 AM
    That looks right to me - but have you tried testing outside of Ripple completely? Remove deviceready and just use a regular DOMContentLoaded event and see if Chrome is responding to the FS requests correctly there.
  • Commented on 05-27-2014 at 10:52 AM
    It doesn't work also on Chrome, after changing something to reflect specific Chrome interface, I got the same error.
    Is there a simple working example I can try to understand?
    I don't know what's wrong.
  • Commented on 05-27-2014 at 10:54 AM
    Frankly if it works on the device and not Chrome, then you may be better off just shimming it when you test w/ Ripple. By shim I mean fake. When you tested with Chrome, you did test via a real URL, not a file:// url, right?
  • Dave #
    Commented on 08-18-2014 at 6:45 AM
    Thanks for this post. Really helped me with a cross domain issue I had just run into. I just noticed your photo in the comments and realised this is not the first time one of your posts has helped me out. :) Good stuff and thanks (more than once!)
  • Commented on 08-18-2014 at 6:48 AM
    Glad to help.
  • Commented on 08-18-2014 at 6:49 AM
    Btw - this post is old - be sure to check the Ripple is Reborn post.

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty