Wednesday 1 February 2017

Generate .SO file by using NDK and use it in Android APP

Hello Guys !!! Hope You all are doing well.

Today I am going to Discuss how to generate .So file  by using NDK and how to use this file  as library in Android App by using Android Studio.

Obvious question  What is SO File??
Right I am giving brief detail...
In Android we are able to use C, C++ code known as a Native code for java. Android NDK  compiles this code into .so files. just like jar file in java to use it as library.  As per  Android NDK site below is  brief detail 

Application Binary Interface (ABI): The ABI defines exactly how your app's machine code is expected to interact with the system at runtime. The NDK builds .so files against these definitions. Different ABIs correspond to different architectures: The NDK includes ABI support for ARMEABI (default), MIPS, and x86. For more information, see ABI Management.

Now, I hope Guys I can proceed further.  Second Question How to create .SO file from Native Code?
  Here  I am describing it as a Step by Step procedure.

Step 1 Create a Folder (Let say hello-jni/jni)
I am using Ubuntu machine so let say under the u dir I have created one hello-jni folder and then one more jni folder. Then add three files inside this jni folder. Android.mk, Application.mk and hello-jni.c

Step 2 Modify content of MK file
Now open one by one 2 MK file. First open Android.mk file and copy paste following code in it.

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
Open Application.mk file and copy paste follwoing code
APP_CFLAGS += -Wno-error=format-security
APP_ABI := all
# APP_ABI := armeabi armeabi-v7a x86 

Step 3 Modify Native Code
Open hello-jni.c file and copy paste following code in it.
#include <string.h>
#include <jni.h>

JNIEXPORT jstring JNICALL 
Java_softsolution_sks_com_myhellojni_MainActivity_getStringFromJNI(JNIEnv *env, jobject thisObj) {
   return (*env)->NewStringUTF(env, "Hello from native code!");
}

jstring
Java_softsolution_sks_com_myhellojni_MainActivity_getJniString(JNIEnv* env, jobject thiz){
    return (*env)->NewStringUTF(env, "Hello from JNI! Saurabh");
}

JNIEXPORT jint JNICALL 
Java_softsolution_sks_com_myhellojni_MainActivity_getIntSqure(JNIEnv* env, jobject obj,jint value) {
    return value * value;
}

JNIEXPORT jboolean JNICALL 
Java_softsolution_sks_com_myhellojni_MainActivity_getBooleanMethod(JNIEnv* env,jobject obj, jboolean unsignedChar) {
    return !unsignedChar;
}
Step 4 Generate .SO file by using NDK Build
This is the last step to generate .so file for your native code by using NDK Build command. After Generation this SO file, You can use it as lib in Your Android Studio Project.
 Open Your terminal(Ubuntu) and reached till your hello-jni folder.

As for Example u/hello-jni/jni . Then set Path variable for your NDK . Here I am assuming that You had downloaded NDK and kept it in u Dir.

export PATH=$PATH:/u/android-ndk-r14-beta1
 SYSROOT=u/android-ndk-r14-beta1/platforms/android-21/arch-arm/
After it run build command  
 ndk-build
That's it, It will generate .SO file for all ABI. Now Copy these ABI(.So file) and use it in your Android App. I am going to explain it below.

Using .So file in Android Studio 
With Latest Android Studio version(2.2.3), You are able to directly developed your app with NDK. 
But here i am discussing how you can use generated .so file in Android studio. 
  
Step 1 Create one new Project (or module in your existing Project) 
Let create one new Project/Module myhellojni in Android Studio. Then create a folder inside src main  as for example
 /src/main/jniLibs Then copy all your .so file with folder and paste it inside jniLibs like below.

Step 2 Add jniLibs path in build.gradle 

add below given path in hello-jni/build.gradle file under android{...} tag

sourceSets.main {
    jniLibs.srcDir 'src/main/libs'}


Step 3  Use Native Method in MainActivity 
Now you can use native method inside your app activity. As for example

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    static {
        Log.d(TAG,"Loads lib started..");
        System.loadLibrary("hello-jni");
        Log.d(TAG,"Load libs finished");
    }

    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv = (TextView)findViewById(R.id.hello_txt);
        tv.setText(" hi "+getStringFromJNI());
    }

    public native String getStringFromJNI();
}


That's it.  Hope you guys Enjoy it.

Happy Coding!!!

Thanks
Saurabh

Note:- Please proved your comment and suggestion for my post. It will energize me.

12 comments:

  1. Very helpful post. It help me a lot but I am getting error in building my NDk sample project.
    I have ask it here https://stackoverflow.com/questions/51100111/how-to-resolve-android-ndk-build-command-faild
    Can you please help me to solve it? Thanks.

    ReplyDelete
  2. Very useful information that you have shared and it is very useful to me.Thanks for sharing the information with us.

    best mobile app development company in chennai

    ReplyDelete
  3. At the point where we have to write command in terminal that is ndk-build.Error is showing "Andriod NDK:could not fid application project directry !".how to solve this issue

    ReplyDelete
  4. How to remove libc++.so dependency from raghu.so
    my make file is something like this
    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)

    LOCAL_MODULE := raghu


    LOCAL_SRC_FILES += raghu.c

    #LOCAL_PRELINK_MODULE := false
    LOCAL_SHARED_LIBRARIES := libcutils

    LOCAL_MODULE_OWNER :=
    LOCAL_PROPRIETARY_MODULE := true
    include $(BUILD_SHARED_LIBRARY)
    when i am using objdump -p raghu.so | grep NEEDED
    NEEDED libc++.so
    NEEDED libc.so
    NEEDED libm.so
    NEEDED libdl.so
    can you please help me how to remove dependency of libc++.so and raghu.c is ajust simple hello world program

    ReplyDelete
  5. can it possible we make .so files from jar file

    ReplyDelete
  6. java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.vmukti.ndktest.MainActivity.stringFromJNI()


    getting this error any solution?

    ReplyDelete
    Replies
    1. I had the same problem, at least in my case was that the signature of the c method must fit your package.

      For example, in this c code : Java_softsolution_sks_com_myhellojni_MainActivity_getStringFromJNI fits the package softsolution.sks.com.myhellojni.MainActivity class. You must adjust for your package.

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Can anyone please share the android sample project please..

    ReplyDelete

Build a Custom Kernel Module for Android

Hi Guys!!!Hope you are doing well !!!. Today I will describe how you can write a custom kernel module(Hello world) for Android and load it a...