Search code examples
javaandroidc++android-ndkjava-native-interface

Android NDK applicaiton throws an error - Unsatisfied Link Error


I am developing NDK based Android application. Right now I am studying using sample "HelloWorld" application. But it throws error each time. Please guide where it is wrong?

P.S.: All my cpp files are inside jni folder only.

In LogCat, while debugging it says;

08-19 14:52:59.340: W/dalvikvm(469): No implementation found for native Lcom/example/myfirstndkapp/MainActivity;.concateneMyStringWithCppString (Ljava/lang/String;)Ljava/lang/String;

Here is the base code:

MainActivity.java

package com.example.myfirstndkapp;

import android.support.v7.app.ActionBarActivity;

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.*;

public class MainActivity extends ActionBarActivity {

    static {
        System.loadLibrary("MyFirstNDKApp");
        }

    private native String concateneMyStringWithCppString(String myString);

    private EditText tvGetValue = null;
    private TextView tvSetValue = null;
    private Button btnCallCPPMethod = null;

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

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
        }

        String str = concateneMyStringWithCppString("OutputString");



        System.out.println("output : "+str);

        }
}

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := MyFirstNDKApp
LOCAL_SRC_FILES := CoreWrapper.cpp
LOCAL_SRC_FILES += Core.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_STL := gnustl_static
APP_ABI := all

Core.h and Core.cpp

//
//  Core.h
#ifndef __MyFistNDKApp__Core__
#define __MyFistNDKApp__Core__

#include <iostream>
const char* concateneMyStringWithCppString(const char* myString);
#endif /* defined(__MyFistNDKApp__Core__) */

//  Core.cpp

#include "Core.h"

const char* CPP_BASE_STRING = "cpp says hello world to %s";

const char* concateneMyStringWithCppString(const char* myString) {
    char* concatenedString = new char[strlen(CPP_BASE_STRING) + strlen(myString)];
    sprintf(concatenedString, CPP_BASE_STRING, myString);
    return concatenedString;
}

CoreWrapper.c

//  CoreWrapper.c

#include <string.h>
#include <jni.h>
#include "Core.h"

extern "C" {

JNIEXPORT jstring JNICALL com_example_myfirstndkapp_MainActivity_concateneMyStringWithCppString(JNIEnv* env, jobject thiz, jstring myString) {
    return env->NewStringUTF(concateneMyStringWithCppString(env->GetStringUTFChars(myString, 0)));
}

}

But while running it throws error on: concateneMyStringWithCppString line in MainActivity.java not even going inside. It says unrecognized one. Here is the error log:

enter image description here

While debugging inside that method: it navigates to UnsatisfiedLinkError class method:

public UnsatisfiedLinkError(String detailMessage) {
    super(detailMessage);
}

Solution

  • I found that CoreWrapper.h class should be autogenerated using javah command. So each time we need to update a java class file and re-generate this jni file.

    According to that jni generated header file, we require to create its cpp file where we can write our code logic.

    I found tutorial on this link very useful. It helped me to find out my mistake.

    Also it contains clear step by step information.

    Hope this helps others who is looking for such.