Using Ripple for PhoneGap Development

This post is more than 2 years old.

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 ( 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.


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.


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.


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


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.


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, 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 calls. I'm not exactly sure why, but it just did.

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

I tested this a few minutes ago with a 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 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.


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.


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, 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

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Mike Hostetler posted on 2/7/2013 at 3:00 AM

Awesome write-up! I love Ripple and think it's seriously underrated.

Comment 2 by Ville Karavirta posted on 2/8/2013 at 4:41 PM

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!

Comment 3 by Raymond Camden posted on 2/8/2013 at 5:58 PM

Glad you guys both like it. :)

Comment 4 by Vaughn posted on 2/14/2013 at 12:05 AM

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\chrome_dev_user

And I have disabled the Cross Domain Proxy in Ripple.

Comment 5 by Andy Idema posted on 5/6/2013 at 11: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.

Comment 6 by Raymond Camden posted on 5/6/2013 at 11:27 PM

It is a command line flag. On OSX it is: open -a /Applications/Google\ --args --allow-file-access-from-files --disable-web-security

Comment 7 by netalex posted on 5/16/2013 at 12:47 AM

hi, you say something about inAppBrowser: wich is the json we have to pass to ripple to use it? TNX

Comment 8 by Raymond Camden posted on 5/16/2013 at 9:28 PM

Eh? I don't get you. If you look at the docs for InAppBrowser, you will see it is just

Comment 9 by netalex posted on 6/13/2013 at 5:09 PM

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.

Comment 10 by Phonegap Application Developme posted on 8/22/2013 at 4:15 PM

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.

Comment 11 by Raymond Camden posted on 8/22/2013 at 5:49 PM

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.

Comment 12 by Sergio Morstabilini posted on 12/10/2013 at 9:56 PM

For those who don't follow Raymond's blog constantly:

Comment 13 by Danilo Cicognani posted on 5/27/2014 at 2:16 PM

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: FILE_NOT_FOUND.
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) {

function gotFileEntry(fileEntry) {

Anyone can help?

Comment 14 by Raymond Camden posted on 5/27/2014 at 2:28 PM

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.

Comment 15 by Danilo Cicognani posted on 5/27/2014 at 7:52 PM

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.

Comment 16 by Raymond Camden posted on 5/27/2014 at 7:54 PM

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?

Comment 17 by Dave posted on 8/18/2014 at 3:45 PM

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!)

Comment 18 by Raymond Camden posted on 8/18/2014 at 3:48 PM

Glad to help.

Comment 19 by Raymond Camden posted on 8/18/2014 at 3:49 PM

Btw - this post is old - be sure to check the Ripple is Reborn post.

Comment 20 by jasna posted on 11/13/2014 at 2:00 PM

really grt but i tried getting the device id as per
but its giving everything is undefined . Can you help me this...

Comment 21 by Raymond Camden posted on 11/13/2014 at 7:50 PM

Ensure you add the device plugin.