Use of prebuild static Library compiled with Android Toolchain

Just to continue with my last post in which I compiled two simple C++ files and archived as a static library. So make sure to open previous blog  in another tab because I will refer this in current post as well.

Now in this Post i will use the same static library in an Android project. Following are the simple steps.

Step 1: Create an Android Project

  • Create a new android project having name “CrossCompilation”.
  • Set the package name as “com.tmz.cc”
  • Create a default activity name “MainActivity”
  • Update the layout file “main.xml” and xml contains

<?xml version=”1.0″ encoding=”utf-8″?>
<GridLayout
xmlns:android=”http://schemas.android.com/apk/res/android&#8221;

android:layout_width=”match_parent”
android:layout_height=”match_parent”

android:useDefaultMargins=”true”
android:alignmentMode=”alignBounds”
android:columnOrderPreserved=”false”

android:columnCount=”4″
>

<TextView
android:text=”Cross Compiled Library Testing”
android:textSize=”16dip”

android:layout_columnSpan=”4″
android:layout_gravity=”center_horizontal”
/>

<TextView
android:text=”Native methods calls Results:”
android:textSize=”16dip”
android:layout_columnSpan=”4″
android:layout_gravity=”left”
/>

<TextView
android:text=”Test 1:”
android:layout_gravity=”right”
/>

<TextView
android:id = “@+id/test1Result”
android:text=”Press Button to get result”
android:ems=”10″
/>

<TextView
android:text=”Test 2:”
android:layout_column=”0″
android:layout_gravity=”right”
/>

<TextView
android:id = “@+id/test2Result”
android:text=”Press Button to get result”
android:ems=”10″
/>

<Space
android:layout_row=”4″
android:layout_column=”0″
android:layout_columnSpan=”3″
android:layout_gravity=”fill”
/>

<Button
android:text=”Call Native Methods”
android:layout_row=”4″
android:layout_column=”1″
android:id = “@+id/btnCallNative”
/>
</GridLayout>

  • Now Open the MainActivity.java file and following are its contents

package com.tmz.cc;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

private Button btnCallNative;
private TextView tvTest1Result;
private TextView tvTest2Result;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnCallNative = (Button)findViewById(R.id.btnCallNative);
tvTest1Result = (TextView)findViewById(R.id.test1Result);
tvTest2Result = (TextView)findViewById(R.id.test2Result);

btnCallNative.setOnClickListener(new View.OnClickListener(){
public void onClick(View view)
{
callNativeMethods();

}
});

//setContentView(R.layout.main);

}
private native int test1();
private native int test2();

public void callNativeMethods()
{
System.loadLibrary(“ccSharedLib”);
int a = test1();
int b = test2();
Integer res1= new Integer(a);
Integer res2 = new Integer(b);
tvTest1Result.setText(res1.toString());
tvTest2Result.setText(res2.toString());
System.out.print(a);
System.out.print(b);

}
}

Now we are done with Java side. Its time to add native side in our project.

Step 2: Add native code and pre-build binaries

  • Create a directory on root of project having name “jni”
  • Add two more directories in “jni” directory.

1)”include” (which contains the headers files of pre-build static library)  and put Test1.h and Test2.h in this directory which I created in the previous blog.  See previous blog 
2) “prebuild” (which contains the pre-build static library created in previous blog) and put the ccStaticLib.a in this directory See previous blog 

  • Add two files in “jni” directory

1) “Android.mk” and its contents are

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := ccStaticLibrary
LOCAL_SRC_FILES := prebuild/ccStaticLib.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := ccSharedLib
LOCAL_SRC_FILES := main-jni.cpp
LOCAL_STATIC_LIBRARIES := ccStaticLibrary
include $(BUILD_SHARED_LIBRARY)

2) “main-jni.cpp” and its contents are
#include <jni.h>
#include <stdio.h>

#include “include/test1.h”
#include “include/test2.h”

extern “C” {

jint
Java_com_tmz_cc_MainActivity_test1( JNIEnv*  env,
jobject  thiz)
{
jint temp = 0;
temp = test1(4,5);
return temp;
}

jint
Java_com_tmz_cc_MainActivity_test2( JNIEnv*  env,
jobject  thiz)
{
jint temp = 0;
temp = test2(4,5,6);
return temp;
}

}

We are done with the coding stuff.

Now we need to compile the project both the native side as well as the Java (Android side) and after compilation you can run this and see the native calls results by pressing the button on main layout.

Advertisements
Posted in Android, C-C++, Cross-Compilation, Development, java, Mobile | Tagged , , , | 3 Comments

Compile C/C++ ARM binary (Static Library) for Android using Standalone toolchain

This post is intended for those who wants to compile and reuse their existing C/C++ code or who wants to compile an open source code for their Android applications. The idea came into my mind after putting time and effort for compiling and using an open source library CS-MAP in Android application. Hopefully this will help you to save a lot of time and efforts.

Android NDK provides set of tools for compiling and using C and/or C++ source files and generate the native ARM binaries (static, shared and executable) on Linux, OS X and Windows, which can be further used in Android application through Java Native Interface (JNI) calls.
I will explain how we can use the standalone cross-compilers for creating ARM binary (a static library) from C++ source files.

Step 1: Extract the standalone cross-compiler toolchain.

  • Install ANDROID-NDK from http://developer.android.com/sdk/ndk/index.html
  • Add an environment variable NDK and add path of NDK root directory as its value.
  • Run the script for extracting android NDK standalone toolchain binaries and other stuff.                                                                                                                                $NDK/build/tools/make-standalone-toolchain.sh –platform=android-14 –install-dir = /cygdrive/e/android/standalone-14

The above script creates a directory name “standalone-14” in “E:\android\” directory of my Window box

Note: As I am extracting the toolchain on Windows Box, so I passed the /cygwin/e/android/standalone-14 in my install directory path. For Linux and OS X one need to customize the above command accordingly.

Step 2: Identify the C/C++ Sources for compilation

  • Create a project directory having name “StaticLibraryTest
  • Create a source directory having name “src” in StaticLibraryTest directory which contains the C/C++ source files
  • Test1.cpp

// Contents of Test1.cpp
#include "Test1.h"
int  test1(int  x, int  y){
int temp = 44;
return (x + y )+ temp ;
}

  • Test2.cpp

// Content of Test2.cpp
#include "Test2.h"
int  test2(int  x, int  y, int z){
int temp = 9;
return (x * y) - temp + z;
}

  • Create a header directory having name “include” in StaticLibraryTest directory which contains the C/C++ header files
    • Test1.h

// Contents of Test1.h
#ifndef TEST1_H
#define TEST1_H
extern int test1(int  x, int  y);
#endif /* TEST1_H */

  • Test2.h

// Contents of Test2.h
#ifndef TEST2_H
#define TEST2_H
extern int test2(int  x, int  y, int z);
#endif /* TEST2_H */

Step 3: Create a make file for building the source and create static library

  • Create a file having name “make-static-library.mak” in “src” directory. This directory also contains the C/C++ source files. The content of make script are given below.


# This variable contains the path of bin directory which contains all the gnu tools required for compilation
# I have extracted the standalone toolchain for Android platform 14 in "e:\android\standalone-14"
ANDROID_NDK_BIN:=/cygdrive/e/android/standalone-14/bin
# Compilation Tools
CC := $(ANDROID_NDK_BIN)/arm-linux-androideabi-gcc
CPP := $(ANDROID_NDK_BIN)/arm-linux-androideabi-g++
AR := $(ANDROID_NDK_BIN)/arm-linux-androideabi-ar
# Compiler flags
# Specify all the flags below which you want to use for your compilation, For this simple example, we only need to specify the include directory path
CFLAGS          := -I../include
# Rule for making C++ object file
.cpp.o:
$(CPP) $(CFLAGS) -c  $<
# Rule for making C object file
.c.o:
$(CC) $(CFLAGS) -c  $<
STATIC_LIB_SRC = Test1.cpp \
Test2.cpp
STATIC_LIB_OBJ = Test1.o \
Test2.o
OUT = ccStaticLib.a
$(OUT): $(STATIC_LIB_OBJ)
$(AR) -crs $(OUT) $(STATIC_LIB_OBJ)

Step 4: Compilation using the make script

  • Open the console (Cygwin for Windows) and change the directory to the “src” directory which contains the C/C++ source files (Test1.cpp and Test2.cpp) and the make file (make-static-library.mak)
  • Execute the following command to compile the sources and generate the static library from these sources. “make –f make-static-library.mak

This will create the static library in the src directory name “ccStaticLib.a”. I have added the “cc” (Cross Compiler) as prefix in the name of static Library generated from make script.

Now static library “ccStaticLib.a” (ARM Binary for Android) is created and our next mission is to use this static library in Android project.

In my upcoming post I will share how we can use this in an Android project.

Updated code part to monospace font as suggested by Venkatesh Shukla.

Posted in Android, C-C++, Cross-Compilation, Mobile | Tagged , , , , , , | 25 Comments