JNI folder in Android Studio
Asked Answered
S

8

20

I am trying make helloy-jni app in Android Studio and I have exception

06-27 13:17:19.099  12714-12714/com.example.testjni2           E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.ExceptionInInitializerError
    at java.lang.Class.newInstanceImpl(Native Method)
    at java.lang.Class.newInstance(Class.java:1319)
    at android.app.Instrumentation.newActivity(Instrumentation.java:1071)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2166)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2299)
    at android.app.ActivityThread.access$700(ActivityThread.java:154)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5306)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
    at dalvik.system.NativeStart.main(Native Method)
    Caused by: java.lang.UnsatisfiedLinkError: Couldn't load hello-jni from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.example.testjni2-1.apk,libraryPath=/data/app-lib/com.example.testjni2-1]: findLibrary returned null
    at java.lang.Runtime.loadLibrary(Runtime.java:365)
    at java.lang.System.loadLibrary(System.java:535)
    at com.example.testjni2.MainActivity.<clinit>(MainActivity.java:9)
    ... 15 more

My structure project looks like this

TestJni2Project

I added my build.gradle line:

   compile files('libs/armeabi/libhello-jni.so')

But this don't helped. I read Gradle and Android Gradle plugin, but I don't find information about working with jni folder

I am thinking what it file dependencies, but it isn't working

My hello-jni.c file includ

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

My MainActivity file include

public class MainActivity extends Activity {
    static {
        System.loadLibrary("hello-jni");
    }
    public native String  stringFromJNI();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String text = stringFromJNI();
        Log.i("MainActivity", text);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

My Android.mk file containts

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

Tell me, please, where I could make a mistake.

Android Studio 0.1.7 OS - Windows 7 x64

Scranton answered 27/6, 2013 at 10:2 Comment(4)
did builded using NDK toolsLink
I created .so library used Cygwin Terminal and NDK command /cygdrive/c/Users/%USER_NAME%/android-ndk/android-ndk-r8e/ndk-build is this not enough?Scranton
its enough for adding libLink
How did you solve it?Schneider
S
8

The gradle build system does not support bundling native libraries at the moment. Check https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J for some custom tasks you'd need to add to your build.gradle.

Note that this is a temporary workaround until gradle supports building native projects.

Skewer answered 27/6, 2013 at 16:34 Comment(1)
Gradle now supports this natively. See my answer bellow.Swagsman
S
75

Nowadays there is an easier method than the accepted answer.

All you have to do is create a folder called "jniLibs" under your /src/main directory (ie, /app/src/main/jniLibs) and place your .so files there. It will look like this:

app
   |
   src
      |
     main
        |
        jniLibs
            |
            armeabi
            |   |
            |   your_lib_compiled_for_armeabi.so
            |
            armeabi-v7a
            |   |
            |   your_lib_compiled_for_v7a.so
            |
            x86
            |   |
            |   your_lib_compiled_for_x86.so

Your .so files should be picked up now.

Swagsman answered 8/4, 2015 at 7:43 Comment(9)
It should be app/src/main/jniLibsCtn
@Ctn - yep you saved the days - .so arch dirs have to to go under app/src/main/jniLibs - kudos!Isleana
Maybe you have to change your answer as Mussa said. My test is on Android Studio 1.5.Woald
just adding .so files of all pross architecture without adding any configuration in gradle file ?Afternoon
This is awesome, you make my day.Lilian
I am getting this error "java.lang.UnsatisfiedLinkError: Bad JNI version returned from JNI_OnLoad in "/mypath/libfile.so": -4" , I can't show real file name here !!Bobsledding
Yeah, this isn't working for me. I'm using the latest stable gradle and Android Studio.Graffito
What do we do for x64?Timothee
So no need for compile files('.../libhello-jni.so')?Schneider
S
16

There is other way to import so to the android project.

  1. create the lib dir and armeabi dir like this, and copy so to it.
    |-project
    |--lib
    |----armeabi
    |------libhello-jni.so
  2. zip the dir lib.
  3. put the zip to the libs dir of project, and change .zip to .jar.
  4. add code to the dependencies part of build.gradle.
    compile fileTree(dir:'libs', include:'lib.jar')
Swamper answered 26/7, 2013 at 6:17 Comment(0)
T
13

add this to your build.gradle:

sourceSets {
    main {
        jniLibs.srcDir 'jniLibs'
    }
}

underneath:

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
Truism answered 31/7, 2015 at 1:12 Comment(1)
Where is the doc about jniLibs?Woald
H
11

You can add pre built *.so files in Android Studio using gradle 0.7.2+. First create the jniLibs at this location /app/src/main/ location and copy the all the folder with *.so files (armeabi, armeabi-v7a, mips, x86) in the jniLibs.

As Xavier said same here https://groups.google.com/forum/#!msg/adt-dev/nQobKd2Gl_8/ctDp9viWaxoJ

Hershberger answered 18/3, 2014 at 18:37 Comment(0)
S
8

The gradle build system does not support bundling native libraries at the moment. Check https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J for some custom tasks you'd need to add to your build.gradle.

Note that this is a temporary workaround until gradle supports building native projects.

Skewer answered 27/6, 2013 at 16:34 Comment(1)
Gradle now supports this natively. See my answer bellow.Swagsman
T
1

There is a new way to work with *.so files on gradle 0.7.3 Please check out this link How to change libs directory in Gradle?

Teryn answered 22/1, 2014 at 14:44 Comment(0)
C
1

Since it is annoying to change the content of jniLibs everytime I modify my JNI implementation file. I used this path in my build.gradle file:

build/intermediates/stripped_native_libs/debug/out/lib

Thus add this to your build.gradle inside android{}:

sourceSets {
    main {
        jniLibs.srcDir 'build/intermediates/stripped_native_libs/debug/out/lib'
    }
}

If you are using kotlin:

sourceSets {
        named("main") {
            jniLibs.srcDir("build/intermediates/stripped_native_libs/debug/out/lib")
        }
    }

Now after modifying your cpp files, to build the apk, you only have to do:

  • "Build" / "Clean Project"
  • "Build" / "Build Bundle(s)/APK(s)" / "Build APK(s)"
Corollaceous answered 11/5 at 18:7 Comment(0)
W
0

For those who don't want to manually create the jniLibs directory, here is the official doc of where put native libs .

The official doc is Android Plugin DSL Reference. See the version of your gradle android plugin version which can be found in Android Studio.

sourceSets stores the information for resources to compile the app.

jniLibs of sourceSets is for JNI libs.

Woald answered 3/9, 2016 at 18:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.