Play2 – starter project for iOS and Android using Dninni and Gyp


If you’ve ever ventured outside a small project that shares code between iOS and Android you would have realized that the JNI part of the share is the most tedious and at times painful. Hand-coding JNI by hand is a real pain, a lot of things go wrong: unbalanced releases, uninitialized fields, tweaking signatures as you progress with development, etc. This takes a lot of time which we are trying to save in the first place. If these sound familiar it’s likely you are sharing, or trying to share, a real object model across platforms, not just a collection of strings…

Play2 is a superset of Play1c. It offers automatic project and makefile generation using gyp and automatic JNI layer generation using Djinni.

The Play2 starter template for iOS, Android and command line is a good idea if you are hitting multiple point on this list

  • Your data model and business logic is no-trivial. You have a hierarchy of objects that need to be persisted and queried. A good example is the Spotify app. Lots of different entities
  • You are not afraid of tons of related scripts. There is a lot of dependencies. Djinni IDLs, makefiles, and Gyp definition files are involved. It’s fragile
  • You are seriously vested into testing your non-UI layer as command line unit tests. Play2 comes with gtest integration

Getting started

Latest instructions are updated on github

iOS app
  1. Run make ios to generate objective-c proxies used by the actual app.
  2. The actual app is located in app-ios/app folder.
  3. The iOS app in app-ios should run, pick the target called ‘app’ It should just load and run. Pull to refresh to see numbers change! Updated numbers will show up in blue!

Android app
  1. Make sure you have Android NDK installed on your mac. Make sure its folder is in PATH. Something like this: export PATH=$PATH:/Users/yevgeny/android-ndk-r10d export ANDROID_NDK=/Users/yevgeny/android-ndk-r10d
  2. Run ndk-build and you should see this error Android NDK: Could not find application project directory!
    This is what you want. Run make android to build the example android application
  3. Run make androidNdk to build JNI libraries. This will produce the shared shared libraries needed by the Android app.
  4. Run make androidJava to build Android app using gradle. The app is located in app-android folder. You can open this project in Android Studio by choosing app-android/app folder and importing it as gradle project.

Next steps

Now what? Well, it’s time to make the app yours. Remove the .git subfolder and commit into your source repository.

A good idea is to start with the ingest process.

Locate numbers.json in the root of the project and rename it to something meaningful to you. Replace the contents of numbers.json with your own starer json model that you would be pulling from the server. Yes, your data model will likely include multiple jsons, calls, tables, etc., just do more of the same.

The numbers.sqlite should also get renamed by now. Alter the DB schema to add tables, indices, etc. If this is app’s first version to go out it’s perfectly fine to bundle the DB structure as an empty database file and then copy it into runtime directory.
Upgrades are different, more on this later. If the database is brand new and will be versioned in the future go ahead and set its initial version using this SQL command:
PRAGMA user_version = 1

Unit tests first

No, I am not a TDD junkie. But in this case it makes sense. It’s now time to start updating our initial unit test which used to work off numbers.json and numbers.sqlite. And now it will work with your own model.

When running inside XCode remember to edit the scheme called test and set up custom working directory to point to the location where your json and sqlite files are located – in the root of the project.

As you develop your own json parsing routines in XCode it gets tedious sometimes. A tip. make your locals auto

And watch them in debugger like this:

Next step is Djinni

At this point you are iterating though some useful json objects. From a hardcoded json for now. So far so good… The database is all ready with a fresh new table or tables, yeah!
We now need a data structure to hold these objects. There is already a structure to hold them, it’s called Item. You probably want to rename and expand this structure for your project. Since this structure gets regenerated in iOS and in Java let’s change and add some properties first and deal with renaming it separately once the whole thing compiles.

The Djinni IDLs are located in ./djinni subfolder. And Item object is defined in item.djinni

Go ahead and add/remove properties. The data types are document here. In Play2, the item is the same time of structure that will be returned from certain finder calls, but your milage may vary.

In terminal run make djinni and make sure you don’t get any errors. That updated the C++ , Objective-C and JNI bindings. Because the djinni file was a record type

 the Djinni changed the Item’s constructor which means nothing will compile anymore. But compile errors are better than runtime errors so keep plowing though and add/change parameters and fix signatures!

At this point the test XCode target should compile and run. You can remove other test in this target – just delete files or alter them to make them meaningful to your model. Or you can do this later.


Next step is play_objc target in XCode. You should set up the same custom working directory for this target as described above for test target.  This target is important if your app is fetching anything from the internet.

You can defer this for later but you will need the original number.json and numbers.sqlite for this unit test to succeed. Otherwise the unit tests will fail due to missing files which you’ve just renamed.


So you got some unit tests going, hopefully you are pulling some data from the network and saving it locally in sqlite3 database. You should have at least one “finder” method working. You are now ready to move to the clients of this code, which is iOS and Android apps. Yeah!


Again, the iOS app is in ./app-ios/app folder and you need to run make ios to regenerate the iOS bindings.