Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
OpenCV Android Programming By Example

You're reading from   OpenCV Android Programming By Example Leverage OpenCV to develop vision-aware and intelligent Android applications.

Arrow left icon
Product type Paperback
Published in Dec 2015
Publisher
ISBN-13 9781783550593
Length 202 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Toc

Understanding how NDK works

Whether you had a clean installation using TADP or followed the manual setup steps, at this stage you should have all the needed components to develop vision-aware Android applications.

Before we move forward to our first example, let's first elaborate on how NDK works. It's always a good idea to familiarize yourself with the basics of Android NDK and be comfortable using it as it will be a cornerstone to our development of Android applications using OpenCV.

An overview of NDK

If you decided to compile the native part of your Android application using the command prompt, you must have used the ndk-build tool. The ndk-build tool is actually a script that launches different build scripts that are responsible for the following:

  • It automatically searches your project to decide on what to build
  • Once the search is done, the scripts start generating binaries and managing dependencies
  • It copies the generated binaries to your project path

Besides the ndk-build tool, there are a few other main components that you should be familiar with, including the following:

  • Java and native calls: Android applications are written in Java, and once the source code is compiled, it is transformed to bytecode so that the Android OS runs under the Dalvik or Android Runtime (ART) virtual machine.

    Note

    Note that the applications that execute the native code are tested only on a Dalvik virtual machine.

    When you are using methods implemented in native code, you should use the native keyword.

    For example, you could declare a function that multiplies two numbers and instructs the compiler that it is a native library:

    public native double mul(double x, double y);
  • Native shared libraries: NDK builds these libraries with an extension, .so. As the name suggests, these libraries are shared and linked in runtime.
  • Native static libraries: NDK also builds these libraries with an extension, .a; these kind of libraries are actually linked at the compile time.
  • Java Native Interface (JNI): As you write your Android application in Java, you need a way to channel your calls to the native libraries written in C/C++ and that's where the JNI comes in handy.
  • Application Binary Interface (ABI): It is the interface that defines how your application machine code should look as you can run your application on different machine architectures. By default, NDK builds your code for ARM EABI; however, you can also select it to be built for MIPS or x86.
  • Android.mk: Think of this file as a Maven build script or better, a make file, which instructs the ndk-build script about the definitions of the module and its name, the source files that you need to compile, and also the libraries that you need to link. It is very important to understand how to use this file and we will come back to it later for more details.
  • Application.mk: It is optional to create this file and it is used to list the modules that your application requires. This information can include ABIs to generate machine code for a specific target architecture, toolchains, and standard libraries.

With these components in mind, you can summarize the general flow of developing native applications for Android as follows:

  1. Decide which parts will be written in Java and which parts will be written in native C/C++.
  2. Create an Android application in Eclipse.
  3. Create an Android.mk file to define your module, list the native source code files to be compiled, and enumerate the linked libraries.
  4. Create Application.mk; this is optional.
  5. Copy your Anrdoid.mk file under the jni folder in your project path.
  6. Build the project using Eclipse. As we linked Eclipse to the installed NDK, the ndk-build tool will compile the .so, .a libraries, your Java code will be compiled to the .dex files, and everything will be packaged in one single APK file and ready to be installed.

A simple example of NDK

As you will be developing Android applications with native support, you will need to be familiar with the general structure of a typical Android application using NDK.

Usually, your Android application has the following folder structure. The project root folder has the following subdirectories:

  • jni/
  • libs/
  • res/
  • src/
  • AndroidManifest.xml
  • project.properties

Here, the NDK-related folders are as follows:

  • The jni folder will contain the native part of your application. In other words, this is the C/C++ source code with the NDK build scripts such as Android.mk and Application.mk, which are needed to build the native libraries.
  • The libs folder will contain the native libraries after a successful build.

    Note

    The NDK build system requires both the AndroidManifest.xml and project.properties files to compile the native part of your application. So, if any of these files are missing, you will need to compile your Java code first before compiling the C/C++ code.

Android.mk

In this section, I'll describe the syntax of the Android.mk build file. As mentioned before, Android.mk is actually a GNU makefile fragment that the build system parses to know what to build in your project. The syntax of the file allows you to define modules. A module is one of the following:

  • A static library
  • A shared library
  • A standalone executable

You already used ndk-build to build the hello-jni project, so let's take a look at the contents of this project Android.mk file:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

Now, let's go through these lines one by one:

  • LOCAL_PATH := $(call my-dir): Here, the script defines a variable called LOCAL_PATH and sets its value by calling the my-dir function, which returns the current working directory.
  • include $(CLEAR_VARS): In this line, the script includes another GNU makefile called CLEAR_VARS to clear all the local variables—variables starting with Local_XXX with the exception of LOCAL_PATH. This is needed because the build files are parsed in a single-make execution context where all the variables are declared as global.
  • LOCAL_MODULE := hello-jni: Here, the script defines a module called hello-jni. The LOCAL_MODULE variable must be defined and unique to identify each module in Android.mk.

    Note

    The build system will add the lib prefix and .so suffix to your defined modules. In the example case, the generated library will be named libhello-jni.so.

  • LOCAL_SRC_FILES := hello-jni.c: As the name suggests, you will list all the source files that you need be built and assembled in one module.

    Note

    You only list the source files and not the header files; it is the responsibility of the build system to compute the dependency for you.

  • include $(BUILD_SHARED_LIBRARY): Here we are including another GNU makefile, which will collect all the information that you defined after the last include command and decide what to build and how to build your module.
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image