Shared C++ layer with Objective-C and Java using JNI – Tutorial – Part 1

Uncategorized

The instructions that follow below may be applicable to you if you are hitting some of these points

  • You are starting a new app that needs to work natively on iOS and Android, maybe even on Mac/PC desktops
  • Your iOS apps are getting converted to Android
  • You always wanted to write something in C++ , but were afraid
  • You are very brave and have an unbounded curiosity and patience

There are many files involved in this business. In order to have a successful share we must first establish the folder structure.

There are many choices on how to do this, but since the Android + JNI has a fairly rigid folder setup we are going to try to structure around Android JNI subfolder. At least in this sample project.

The rationale for such structure

  • Use Android’s default gradle config without making source changes to it
  • Avoid using symbolic links
  • Avoid having multiple copies of source code. So if you change the impl of one C++ file in iOS project the changes will get picked on Android side right away

 

The Folder Structure


ios-search is the iOS app (minus the shared code) and app is the Android + JNI + Shared C++ code

A you can see the majority of shared code is inside the JNI folder. Again it doesn’t have to be this way, but it makes it slightly easier.

 

The Database

The database file name is words.sqlite
It contains just one table called wordz which contains about 62,000 words. The database is completely unoptimized. I will cover sqlite3 search optimization in separate posts.

The Unit Test

The unit test is a simple command line program that invokes the same findWords routine that is invoked by iOS and Android apps. It just does it from the command line. This particular setup does not use gunit, but if I am to add unit testing framework to do the test assertion it would be gunit.

The command line test assumes the database is in the current working directory. In order for the words.sqlite get picked up by the XCode the working directory needs to be set for the scheme.
Choose ‘Edit Scheme’

And then set up a working directory to be the folder containing words.sqlite This is only needs to be done once.

The Data Store

The access to database is done though DataStoreImpl namespace which only contains one routine. The routine is a C style routine – it doesn’t belong to any class. You probably want to structure your code better, this is just an example.
The routine doesn’t return anything interesting. It returns values from the database by adding objects to a collection that is passed in.

 

This “results as items in a param” is a mini-trick to simplify the JNI code since in this example it is hand written.

Accessing Sqlite3 From Data Store

The sqlite3 is accessed using a wrapper called SQLiteCpp. There quite a few choices for accessing sqlite3 from C++ using wrappers, but I like SQLiteCpp the most. It’s clean, simple, just the way I like it. And it even has support for custom routines. This is something that I will use heavily in my future tutorials.

And just a few files to include

Pretty simple stuff.

That’s about it for the command line OS X unit test. Since since sqlite3 is not built from source in this case remember to include the apple’s prebuilt binary.

 

The iOS App

This one is also as simple as the command line unit test. The source files and includes are pretty much the same. The app is simple and should look something like this. As user types characters the call to findWords is made. The UITableView is reloaded with every findWords result. Again, the query itself is completely unoptimized and the table being queried is large. The performance is going to be suboptimal.

Paging Down

This is the fun part. Call to findWords only specify a small set of rows returned from the table. Additional data gets filled one page at a time as user scrolls to the bottom of the UITableView. As this happens there may be a tiny hiccup because of unoptimized nature of the query and table structure. You may want to add a spinning footer cell or some other indicator of acquiring another page. The paging logic is simple, clean, and reusable on Android with almost identical equivalent in Java.

In this example we are paging asynchronously 5 items at a time:

 

On sqlite3 side the paging down is accomplished by the use of “order by” and “limit” constructs. This is very efficient, even on unindexed, non-FTS table!
More fun is coming shortly. You are about to see an Android version which is almost identical to the iOS version in code constructs.

Next, Android version: http://codingsimplicity.com/shared-c-layer-with-android-using-jni-tutorial-part2/


Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /home/codingsi/public_html/wp-includes/comment.php on line 2996