7

Folder structure

 app 
---main
    ---java
    ----jni
          -----Android.mk
          -----Application.mk
          ----- hello-jni.c
    ---res

in build.gradle

apply plugin: 'com.android.application'

android {
compileSdkVersion 21
buildToolsVersion "22.0.1"

defaultConfig {
    applicationId "com.example.hellojni"
    minSdkVersion 17
    targetSdkVersion 21
    sourceSets.main {
        jni.srcDirs = []
        jniLibs.srcDir 'src/main/libs'

    }

    ndk {
        moduleName "hello-jni"
        cFlags "-std=c++11 -fexceptions"
        ldLibs "log"
        stl "gnustl_shared"
        abiFilter "armeabi-v7a"
    }

    task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') {
        destinationDir file("$buildDir/native-libs")
        baseName 'native-libs'
        extension 'jar'
        from fileTree(dir: 'libs', include: '**/*.so')
        into 'lib/'
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn(nativeLibsToJar)
    }







    testApplicationId "com.example.hellojni.tests"
    testInstrumentationRunner "android.test.InstrumentationTestRunner"
}


buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
    }
}

dependencies {
    compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
}


}

in Android.mk

 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)

in hello-jni.c

include<com.example.hellojni.HelloJni.h>

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



 jstring
 Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                              jobject thiz )
{
  #if defined(__arm__)
    #if defined(__ARM_ARCH_7A__)
      #if defined(__ARM_NEON__)
        #if defined(__ARM_PCS_VFP)
          #define ABI "armeabi-v7a/NEON (hard-float)"
        #else
          #define ABI "armeabi-v7a/NEON"
        #endif
          #else
           #if defined(__ARM_PCS_VFP)
        #define ABI "armeabi-v7a (hard-float)"
         #else
        #define ABI "armeabi-v7a"
       #endif
     #endif
   #else
   #define ABI "armeabi"
  #endif
 #elif defined(__i386__)
   #define ABI "x86"
  #elif defined(__x86_64__)
   #define ABI "x86_64"
  #elif defined(__mips64)  /* mips64el-* toolchain defines __mips__ too */
   #define ABI "mips64"
  #elif defined(__mips__)
   #define ABI "mips"
  #elif defined(__aarch64__)
   #define ABI "arm64-v8a"
#else
     #define ABI "unknown"
  #endif

    return (*env)->NewStringUTF(env, "Hello from JNI !  Compiled with ABI " ABI ".");
}

in java

  public class HelloJni extends Activity
 {
      /** Called when the activity is first created. */
      @Override
         public void onCreate(Bundle savedInstanceState)
        {
        super.onCreate(savedInstanceState);


    TextView  tv = new TextView(this);
    tv.setText( stringFromJNI() );
    setContentView(tv);
}


public native String  stringFromJNI();


public native String  unimplementedStringFromJNI();


static {
    System.loadLibrary("hello-jni");
}
}

I am getting unsatisfied error

 java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.hellojni-2/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libhello-jni.so"
        at java.lang.Runtime.loadLibrary(Runtime.java:366)
        at java.lang.System.loadLibrary(System.java:989)
        at com.example.hellojni.HelloJni.<clinit>(HelloJni.java:64)
        at java.lang.reflect.Constructor.newInstance(Native Method)
        at java.lang.Class.newInstance(Class.java:1572)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1088)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2215)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2388)
        at android.app.ActivityThread.access$800(ActivityThread.java:148)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1292)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5312)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)

My local.properties

sdk.dir=F\:\\SDK
ndk.dir=C\:\\NDK

Its not generating .so files ..

3
  • 2
    NDK with Android Studio is still a moving target, but the obvious check is to see if you are getting .so files in your apk. Often it is easier to tell Android Studio to ignore it all, run ndk-build yourself, and drop the result wherever the latest version of Android Studio will find them. Commented May 18, 2015 at 4:54
  • @ChrisStratton how to run ndk-build myself? Commented May 18, 2015 at 4:55
  • See the ndk documentation of course. It is an executable or script located in the root of the ndk installation folder, which you can run from a command line or build automation tool. Commented May 18, 2015 at 14:41

1 Answer 1

4

You've got several mistakes in your build.gradle:

The nativeLibsToJar task was a relevant technique in early versions of the gradle android plugin, It shouldn't be used since at least 0.7 and it may lead to bugs, remove this task. Instead, if you put your .so files inside jniLibs/ABI directories (where ABI is armeabi-v7a, x86...), they will get properly integrated inside your APK.

Then, you have set:

jni.srcDirs = []
jniLibs.srcDir 'src/main/libs' 

It deactivates the built-in ndk integration from the gradle plugin and make gradle use libs from libs instead of from jniLibs. That's fine, but later you're defining your ndk module with a ndk {} block, which is useless then, remove it.

Once you've cleaned these parts, you can call ndk-build (or ndk-build.cmd if you're using Windows) from command line, from the root of your Android project. It will generate your .so files inside libs/ABI and they will get integrated into your APK since jniLibs.srcDir 'src/main/libs' told gradle to get these libs from libs.

You can check that your .so files get integrated by opening your APK as a zip file; Your .so files have to be present under lib/ABI.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.