

.. _Android_Binary_Package_with_NDK:


Using OpenCV in C++ code with OpenCV4Android SDK
*********************************************

The Android way is writing all your code in Java. But sometimes, it is not enough and you need to go to the native level and write some parts of your application in C/C++.
This is especially important when you already have some computer vision code which is written in C++ and uses OpenCV, and you want to reuse it in your Android application.
In this case the only way is to use `JNI <http://java.sun.com/docs/books/jni/>`_ - a Java framework for interaction with native code.
It means, that you should add a Java class with native methods exposing your C++ functionality to the Java part of your Android application.

This tutorial describes a fast way to create and build Android applications containing OpenCV code written in C++. It shows how to build an application which uses OpenCV inside its JNI calls. Tutorial 3 and 4 from the OpenCV for Android SDK can be used as examples. OpenCV Sample "face-detect" also contain a call to C++ class.

Please note that before starting this tutorial you should go through all the steps, described in the tutorial :ref:`Android_Binary_Package`.

This tutorial was tested using Ubuntu 10.04 and Windows 7 SP1 operating systems.
However, it should also work on Mac OS X. 
If you encounter any error after thoroughly following these steps, feel free to contact us via `OpenCV4Android <https://groups.google.com/group/android-opencv/>`_ discussion group or OpenCV `Q&A forum <http://answers.opencv.org>`_ . We'll do our best to help you out.

Prerequisites: Setup Android NDK
================================

To compile C++ code for Android platform you need ``Android Native Development Kit`` (*NDK*).

You can get the latest version of NDK from the `download page <http://developer.android.com/sdk/ndk/index.html>`_. To install Android NDK just extract the archive to some folder on your computer. Here are `installation instructions <http://developer.android.com/sdk/ndk/index.html#installing>`_.

.. note:: Before start you can read official Android NDK documentation which is in the Android NDK archive, in the folder :file:`docs/`.

    The main article about using Android NDK build system is in the :file:`ANDROID-MK.html` file.

    Some additional information you can find in the :file:`APPLICATION-MK.html`, :file:`NDK-BUILD.html` files, and :file:`CPU-ARM-NEON.html`, :file:`CPLUSPLUS-SUPPORT.html`, :file:`PREBUILTS.html`.

Theory: Android application structure
=====================================

Usually code of an Android application has the following structure:

+ :file:`root folder of the project/`

  - :file:`jni/`

  - :file:`libs/`

  - :file:`res/`

  - :file:`src/`

  - :file:`AndroidManifest.xml`

  - :file:`project.properties`

  - :file:`... other files ...`

where:

+ the :file:`src` folder contains Java code of the application,

+ the :file:`res` folder contains resources of the application (images, xml files describing UI layout , etc),

+ the :file:`libs` folder will contain native libraries after a successful build,

+ and the :file:`jni` folder contains C/C++ application source code and NDK's build scripts :file:`Android.mk` and :file:`Application.mk`. 

  Written in Makefile language, these scripts control the C++ build process.


Also the root folder should contain the following files:

* :file:`AndroidManifest.xml` file presents essential information about application to the Android system
  (name of the Application, name of main application's package, components of the application, required permissions, etc).

  It can be created using Eclipse wizard or :command:`android` tool from Android SDK.

* :file:`project.properties` is a text file containing information about target Android platform and other build details.

  This file is generated by Eclipse or can be created with *Android* tool included in Android SDK.

.. note:: Both files (:file:`AndroidManifest.xml` and :file:`project.properties`) are required to compile the C++ part of the application, since NDK build system relies on them. If any of these files does not exist, compile the Java part of the project before the C++ part.

.. _NDK_build_cli:


Theory: Building application with C++ native part from command line
===================================================================

Here is the standard way to compile C++ part of an Android application:

#. Open console and go to the root folder of an Android application

   .. code-block:: bash

        cd <root folder of the project>/

   .. note:: Alternatively you can go to the :file:`jni` folder of the Android project. But samples from OpenCV4Android SDK are configured for building from the project root level (because of relative path to the OpenCV library).

#. Run the following command

   .. code-block:: bash

        <path_where_NDK_is_placed>/ndk-build

   .. note:: On Windows we recommend to use ``ndk-build.cmd`` in standard Windows console (``cmd.exe``) rather than the similar ``bash`` script in ``Cygwin`` shell.

   .. image:: images/ndk_build.png
      :alt: NDK build
      :align: center

#.   After executing this command the C++ part of the source code is compiled.

After that the Java part of the application can be (re)compiled (using either *Eclipse* or *Ant* build tool).

.. note:: Some parameters can be set for the :command:`ndk-build`:

    **Example 1**: Verbose compilation

    .. code-block:: bash

        <path_where_NDK_is_placed>/ndk-build V=1

    **Example 2**: Rebuild all

    .. code-block:: bash

        <path_where_NDK_is_placed>/ndk-build -B


.. _Android_NDK_integration_with_Eclipse:


Theory: Building application with C++ native part from *Eclipse*
================================================================

There are several possible ways to integrate compilation of C++ code by Android NDK into Eclipse compilation process.
We recommend the approach based on Eclipse :abbr:`CDT(C/C++ Development Tooling)` Builder.

.. important:: Make sure your Eclipse IDE has the :abbr:`CDT(C/C++ Development Tooling)` plugin installed. Menu :guilabel:`Help -> About Eclipse SDK` and push :guilabel:`Installation Details` button.

.. image:: images/eclipse_inst_details.png
  :alt: Configure builders
  :align: center

To install the `CDT plugin <http://eclipse.org/cdt/>`_ use menu :guilabel:`Help -> Install New Software...`,
then paste the CDT 8.0 repository URL http://download.eclipse.org/tools/cdt/releases/indigo as shown in the picture below and click :guilabel:`Add...`, name it *CDT* and click :guilabel:`OK`.

.. image:: images/eclipse_inst_cdt.png
  :alt: Configure builders
  :align: center

``CDT Main Features`` should be enough:

.. image:: images/eclipse_inst_cdt_2.png
  :alt: Configure builders
  :align: center


.. important:: OpenCV for Android 2.4.2 package contains sample projects pre-configured to use CDT Builder. It automatically builds JNI part via ``ndk-build``.

#. Define the ``NDKROOT`` environment variable containing the path to Android NDK in your system (e.g. **"X:\\Apps\\android-ndk-r8"** or **"/opt/android-ndk-r8"**).

#. | CDT Builder is already configured for **Windows** hosts,
   | on **Linux** or **MacOS** a small modification is required:
   
   Open `Project Properties` of the projects having JNI part (`face-detection`, `Tutorial 3` and `Tutorial 4`),
   select :guilabel:`C/C++ Build`   in the left pane,
   remove **".cmd"** and leave ``"${NDKROOT}/ndk-build"`` in the :guilabel:`Build command`   edit box and click :guilabel:`OK`.

     .. image:: images/eclipse_cdt_cfg4.png
        :alt: Configure CDT
        :align: center

#. Use menu :guilabel:`Project` -> :guilabel:`Clean...`  to make sure that NDK build is invoked on the project build:

    .. image:: images/eclipse_ndk_build.png
        :alt: Select resources folder to refresh automatically
        :align: center

Theory: The structure of :file:`Android.mk` and :file:`Application.mk` scripts
==============================================================================

The script :file:`Android.mk` usually has the following structure:

.. code-block:: make

        LOCAL_PATH := $(call my-dir)

        include $(CLEAR_VARS)
        LOCAL_MODULE    := <module_name>
        LOCAL_SRC_FILES := <list of .c and .cpp project files>
        <some variable name> := <some variable value>
        ...
        <some variable name> := <some variable value>

        include $(BUILD_SHARED_LIBRARY)

This is the minimal file :file:`Android.mk`, which builds C++ source code of an Android application. Note that the first two lines and the last line are mandatory for any :file:`Android.mk`.

Usually the file :file:`Application.mk` is optional, but in case of project using OpenCV, when STL and exceptions are used in C++, it also should be created. Example of the file :file:`Application.mk`:

.. code-block:: make

        APP_STL := gnustl_static
        APP_CPPFLAGS := -frtti -fexceptions
        APP_ABI := armeabi-v7a

Sometimes ``ndk-build`` fails with an `"undefined reference to std::basic_string<...>"` error message. Then one more additional code line in the :file:`Android.mk` can help:

.. code-block:: make

        APP_PLATFORM := android-9

Practice: Build samples from OpenCV4Android SDK
===============================================

OpenCV4Android SDK includes 3 samples having JNI resources:

* *Tutorial 3 (Advanced) - Add Native OpenCV*

  This sample illustrates how you can use OpenCV in C++ without OpenCV Java API.

* *Tutorial 4 (Advanced) - Mix Java+Native OpenCV*

  This sample shows how you can mix OpenCV Java API and native C++ code.

* *Sample - face-detection*

  This sample illustrates usage of both simple OpenCV face detector via Java API and advanced detection based face tracker via JNI and C++.

.. important:: Before OpenCV **2.4.2** for Android these projects were not configured to use CDT for building their native part , so you can do it yourself.

Practice: Create an Android application, which uses OpenCV
==========================================================

To build your own Android application, which uses OpenCV from native part, the following steps should be done:

#. The archive with OpenCV4Android SDK should be downloaded and extracted to some folder (e.g. :file:`C:\\Work\\OpenCV4Android\\OpenCV-2.4.0`).

#. You can use an environment variable to specify the location of OpenCV package or just hardcode full or relative path in the :file:`jni/Android.mk` of your projects.

#.  The file :file:`jni/Android.mk` should be written for the current application using the common rules for the file.

    For detailed information see the Android NDK documentation from the Android NDK archive, in the file
    :file:`<path_where_NDK_is_placed>/docs/ANDROID-MK.html`

#. The line

   .. code-block:: make

           include C:\Work\android-opencv\OpenCV-2.4.0\share\OpenCV\OpenCV.mk

   should be inserted into the :file:`jni/Android.mk` file **after** the line

   .. code-block:: make

        include $(CLEAR_VARS)

#. Several variables can be used to customize OpenCV stuff, but you **don't need** to use them when your application uses the `async initialization` via the `OpenCV Manager` API.
   
   Note: these variables should be set **before**  the ``"include .../OpenCV.mk"`` line:

   .. code-block:: make

        OPENCV_INSTALL_MODULES:=on

   Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them into the APK.

   .. code-block:: make

        OPENCV_CAMERA_MODULES:=off

   Skip native OpenCV camera related libs copying to the project ``libs`` folder.

   .. code-block:: make

        OPENCV_LIB_TYPE:=STATIC

   Perform static link with OpenCV. By default dynamic link is used and the project JNI lib depends on ``libopencv_java.so``.

#. The file :file:`Application.mk` should exist and should contain lines

   .. code-block:: make

        APP_STL := gnustl_static
        APP_CPPFLAGS := -frtti -fexceptions

   Also the line

   .. code-block:: make

                 APP_ABI := armeabi-v7a

   is recommended for the applications targeting modern ARMs

#. Either use :ref:`manual <NDK_build_cli>` ``ndk-build`` invocation or :ref:`setup Eclipse CDT Builder <Android_NDK_integration_with_Eclipse>` to build native JNI lib before Java part [re]build and APK creation.
