Retrieve Your cordova app’s localStorage Data Directly From iOS Device

Use Case

If WiFi fails, your ajax call fails and your backup re-submit code fails, you may need a last ditch solution of physically grabbing your form data from inside your PhoneGap app, off of an individual iOS device.

Prerequisites

Make sure the app is coded to save data locally using HTML5 localStorage API.

Once the localStorage functionality is tested and working, and you have your PhoneGamp / cordova app running on an iPad, you can use PhoneView to access the file system on your the iPad.

Install DB Browser for SQLite on your Mac. Under the hood, cordova saves your localStorage data as a simple SQLite database.

Retrieve the Data

  1. Connect your device to your Mac and open PhoneView Demo
  2. Go to Apps in the main nav on the left.
  3. Click on Settings in the top nav icons bar and you’ll see this dialog window:
    sc1
  4. Check the “Show Entire Disk in Disk Mode” and “Show All Apps in Apps Mode (Developers Only)” boxes. You’ll get a warning confirmation popup, which you should accept by clicking OK.
  5. You’ll now see your custom cordova app listed under Apps:
    screen-shot-2016-10-25-at-4-10-00-pm

  6. The folders you want is yourApp/Library/Caches/ and yourApp/Documents/Backups/. The file should be called something like “file__0.localstorage” in /Library/Caches or “localstorage.appdata.db” in /Documents/Backups. It’s essentially a SQLite file, and can be opened using an app that lets you view SQLite files.
  7. To open it, you need to first copy the Library folder to your Mac.
  8. Click the Library folder to to select it
  9. Click on Copy from iPhone button in the top icons navbar
  10. Choose a location to save it on your machine.
  11. Launch DB Browser for SQLite
  12. Open your recently copied “file__0.localstorage” or “localstorage.appdata.db” files from your Mac in DB Browser for SQLite
  13. Click on the Browse Data tab towards the top of the interface
  14. You should see your localStorage Key / Value pairs listed as a SQL table:
  15. If you stored your Values as Arrays, your actual data may be stored as a BLOB data type and not plain text
  16. Select your BLOB value in the table and look at the right side of the interface, under Edit Database Cell
  17. Make sure the Mode is set to “Binary”
  18. You should be able to see your data with very bad kerning
  19. Click the “Export” button above the cell content area
  20. Save your file as .txt and open the .txt in any text editor, like SublimeText, to access your data as plain text.

Testing Your MAMP HTML5 Content on Android Emulators

Seeing your MAMP localhost site inside a web browser in an Android Emulator

On OS X your local IP is usually http://127.0.0.1:8080, which is what’s pulled up by http://localhost:8080.
Inside an Android Emulator instance or AVD, that same IP and localhost don’t work.
Android docs point us to this number instead:

http://10.0.2.2:8080 

Seeing MAMP Virtual Hosts from inside the Android Emulator

According to this post, you need to login into the Emulator’s shell:

$adb -e shell

Then edit the Emulator’s /etc/hosts/ file to point to your http://mySite.localhost

# echo '10.0.2.2      prototypes.localhost' >> /etc/hosts

First time I tried this, I got this error:

root@android:/ # echo '10.0.2.2 prototypes.localhost' >> /etc/hosts
/system/bin/sh: can't create /etc/hosts: Read-only file system

Then I found a great step by step tutorial on the subject from http://dillieodigital.wordpress.com. His post reminded me to check that my emulator exists, has been started up and is running properly via “./android list avd”, “./adb devices”, “./adb kill server”, “./adb start server” and “./adb -s emulator-5554 remount”.

I tried his “Option 1”, pulling the Emulator’s /etc/hosts file, editing it off my Desktop and pushing it back to the Emulator but it didn’t work:

# ./adb -s emulator-5554 pull /etc/hosts /Users/your.name/Desktop
# ### edit hosts file ### 
# ./adb -s emulator-5554 push /Users/your.name/Desktop/hosts /etc/

“Option 2” from the above quoted tutorial worked fine for me, like so:

# ./adb -s emulator-5554 shell
# echo '10.0.2.2   prototypes.localhost' >> /etc/hosts
# exit

Now, if I ever get that “can’t create /etc/hosts: Read-only file system” error from the Emulator’s shell, I have to “exit” of the Emulator’s shell and remount again:

"./adb -s emulator-5554 remount" 

Then, “Option 2” works fine for me again.

Notes on Unity3D and SVN

Unity documentation has a brief page on the subject.

  1. Follow the above instructions & create a repo for your Unity project in svn.
  2. Once you have your local Working Copy set up & opened in the Unity IDE, Unity will generate a Library folder next to your Assets.
  3. DO NOT ever version the Library folder. Leave it unversioned. If you’re using an SVN client like Cornerstone on OS X, select the Library folder, Ctrl+click it & choose Ignore. This way you’ll never have to see those files popup in the Unversioned view or accidentally include them in a Commit. If you’re using command line, set Library to be ignored via Terminal, as you probably already know how.

Making fonts in AS3 is fun

The instructions that come with the FIVe3D font making utility are pretty clear overall but on OS X 10.4 it can be confusing to find which WindowSWF folder to use. Is it /Applications/Adobe Flash CS4/en/Configuration/WindowSWF/ ? Or is it /Applications/Adobe Flash CS4/Common/First Run/WindowSWF/ ?

Actually, the place to put “Make a new typography file.swf” is here: /Users/youruserhandle/Library/Application Support/Adobe/Flash CS4/en/Configuration/WindowSWF/.

I used a font called Roadkill. When the font was created, the Flash CS4 Output window said: ‘”Roadkill.as” is in the current folder.’

Since my hard drive is partitioned, it wasn’t immediately clear what was meant by “current folder” in this case. The font.fla file I used to create Roadkill.as via the font-making utility was on the 2nd partition, i.e. not on the main partition.

It turns out “current folder” meant the top most directory on the main partition on my OS X machine, right next to Users, Developer, Library, Applications, System.

Adding MySQL to $PATH Environment Variable on OS X

Update, 09.10.2012: This just worked for me for adding Android’s adb tool to my environment path on OS X 10.6.8. The first time I tried I got an error because I wrote “export $PATH=” instead of “export PATH=”.

Earlier this year I took some Java courses. I learned a ton from what was on the syllabus. It was exciting to see stuff like Generics in the Collections framework in JDK 1.5 and compare it to how Actionscript didn’t have that option until very recently, when the Vector class was added to AS3 for Flash Player 10.

One thing that caught me by surprise was that all software installation instructions for class materials were for Windows only (may be I was naive to expect otherwise). The professor was good but he wasn’t a Mac guy and he was super busy at his day job. A few of us OS X guys had to do extra work on our own on top of all the regular class work, just to get Eclipse, Tomcat & MySQL working on our systems. As painful as it was to spend extra days on things like “Why do I have to spend days on learning UNIX when my Java homework is due tomorrow?!!!” OR “Why do I keep getting a 404 Error for Servlets but not for JSP?! !@##$#^$%^$%^!!”… in the end, I think we ended up as slightly better developers, with a little bit more experience, because we all had to teach ourselves a little Terminal and OS X UNIX commands on the spot.

At the very least, I can always say, “Hey, at least I taught myself how to add “mysql” to the $PATH Environment Variable on OS X:

  1. launch Terminal (assuming it’s a bash shell)
  2. write ‘echo $PATH’ to see what your path is now
  3. if ‘mysql’ isn’t in there, write in the path to where you installed it via this command:
    ‘export PATH=/Users/your_user_name/your_path_to_mysql/mysql/bin:$PATH >> ~/.bash_profile’
  4. that should add it to your bash_profile
  5. write ‘echo $PATH’ again, you should see ‘mysql’ in there

Note: this is for installing MySQL as a stand alone app for use with J2EE/Java projects. If you’re just trying to do some PHP on a development machine, it’s easier to use a wysiwyg LAMP package like MAMP or XAMPP.

More on the $PATH environment variable here.

The same technique can be used to add the open source Flex SDK compiler, MXMLC, to your $PATH environment variable on OS X.

How to set up Connector/J in Eclipse

Connector/J is a “Type IV JDBC driver for MySQL.”

Assumptions

You have downloaded & installed MySQL 5.1, Connector/J for 5.1 (the JDBC driver for MySQL) from mysql.com, Tomcat 5.5 or 6, Eclipse 3.4 for Java EE. I’m assuming this is a Dynamic Web Project in Eclipse with Tomcat 6 as the Target Runtime. I did this successfully on OS X 10.5 (Leopard) & on Windows XP.

The Steps:

  1. Select your project folder in Eclipse’s Project Explorer (just click on it so it’s highlighted).
  2. Open project properties. There’re several ways to do this. For example, you can go to Project > Properties in Eclipse’s top menu.
  3. Click on Java Build Path. Click “Add External Jars.” Navigate to where you unzipped Connector/J on your hard drive. Choose the .jar file (in my case mysql-connector-java-5.1.7-bin.jar) & click Open. It’ll now show up under JARs and class folders in the build path.
  4. Click on Java EE Module dependencies in the menu on the left.
  5. Check the checkbox next to the Connector/J path under JAR/Module. Hit Apply and OK.
    Run a skeleton test Servlet to see if it works:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestJDBC extends HttpServlet {

    public void init(){
        try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            System.out.println("JDBC driver loaded");
        } catch (ClassNotFoundException e) {
            System.out.println(e.toString());
        } //Eclipse may auto-force some extra catch blocks here
     }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("Check the Console tab in" +
		" Eclipse... it should say \"JDBC driver loaded\"");
    }

}