Android studio 版本: Android Studio 2.0 Beta 6.0 Gradle 版本:gradle-2.10 NDK 版本:android-ndk-r10e
创建一个空项目 ![](Android studio 下使用JNI/project.png)
打开Setting 在 Setting中设置NDK的路径: ![](Android studio 下使用JNI/setNDK.png)
添加Native代码,以及LoadLibrary,由于这里还没生成这些所以还是显示错误的,但是不要管它。 ![](Android studio 下使用JNI/native.png)
点击Build-> make project 编译项目: ![](Android studio 下使用JNI/makepro.png) 这时候会在,[项目名]/app/build/intermediates/classes/debug/com/idealist/testjniusage 下产生编译出来的class文件 进入到[项目名]/app/src/main 目录下,运行如下javah命令: ![](Android studio 下使用JNI/path.png) javah -d jni -classpath /home/ jimmy/Dev/ sdk_m/sdk/ platforms/android-23/ android.jar:/home/ jimmy/Dev/ sdk_m/sdk/ extras/android/ support/v7/ appcompat/libs/ android-support-v4.jar:/home/ jimmy/Dev/ sdk_m/sdk/ extras/android/ support/v7/ appcompat/libs/ android-support-v7-appcompat.jar:/home/ jimmy/GitHub_Opensrc/ TestJNIUsage/app/ build/intermediates/ classes/debug/ com.idealist.testjniusage.MainActivity
这时候会在项目目录树下产生一个jni的文件夹,如下图所示: ![](Android studio 下使用JNI/protree.png)
打开生成的头文件可以看到如下内容:
#include <jni.h> #ifndef _Included_com_idealist_testjniusage_MainActivity #define _Included_com_idealist_testjniusage_MainActivity #ifdef __cplusplus extern "C" {#endif #undef com_idealist_testjniusage_MainActivity_BIND_ABOVE_CLIENT #define com_idealist_testjniusage_MainActivity_BIND_ABOVE_CLIENT 8L #undef com_idealist_testjniusage_MainActivity_BIND_ADJUST_WITH_ACTIVITY #define com_idealist_testjniusage_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L #undef com_idealist_testjniusage_MainActivity_BIND_ALLOW_OOM_MANAGEMENT #define com_idealist_testjniusage_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L #undef com_idealist_testjniusage_MainActivity_BIND_AUTO_CREATE #define com_idealist_testjniusage_MainActivity_BIND_AUTO_CREATE 1L #undef com_idealist_testjniusage_MainActivity_BIND_DEBUG_UNBIND #define com_idealist_testjniusage_MainActivity_BIND_DEBUG_UNBIND 2L #undef com_idealist_testjniusage_MainActivity_BIND_IMPORTANT #define com_idealist_testjniusage_MainActivity_BIND_IMPORTANT 64L #undef com_idealist_testjniusage_MainActivity_BIND_NOT_FOREGROUND #define com_idealist_testjniusage_MainActivity_BIND_NOT_FOREGROUND 4L #undef com_idealist_testjniusage_MainActivity_BIND_WAIVE_PRIORITY #define com_idealist_testjniusage_MainActivity_BIND_WAIVE_PRIORITY 32L #undef com_idealist_testjniusage_MainActivity_CONTEXT_IGNORE_SECURITY #define com_idealist_testjniusage_MainActivity_CONTEXT_IGNORE_SECURITY 2L #undef com_idealist_testjniusage_MainActivity_CONTEXT_INCLUDE_CODE #define com_idealist_testjniusage_MainActivity_CONTEXT_INCLUDE_CODE 1L #undef com_idealist_testjniusage_MainActivity_CONTEXT_RESTRICTED #define com_idealist_testjniusage_MainActivity_CONTEXT_RESTRICTED 4L #undef com_idealist_testjniusage_MainActivity_MODE_APPEND #define com_idealist_testjniusage_MainActivity_MODE_APPEND 32768L #undef com_idealist_testjniusage_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING #define com_idealist_testjniusage_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L #undef com_idealist_testjniusage_MainActivity_MODE_MULTI_PROCESS #define com_idealist_testjniusage_MainActivity_MODE_MULTI_PROCESS 4L #undef com_idealist_testjniusage_MainActivity_MODE_PRIVATE #define com_idealist_testjniusage_MainActivity_MODE_PRIVATE 0L #undef com_idealist_testjniusage_MainActivity_MODE_WORLD_READABLE #define com_idealist_testjniusage_MainActivity_MODE_WORLD_READABLE 1L #undef com_idealist_testjniusage_MainActivity_MODE_WORLD_WRITEABLE #define com_idealist_testjniusage_MainActivity_MODE_WORLD_WRITEABLE 2L #undef com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_DIALER #define com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_DIALER 1L #undef com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_DISABLE #define com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_DISABLE 0L #undef com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL #define com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L #undef com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL #define com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L #undef com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_SHORTCUT #define com_idealist_testjniusage_MainActivity_DEFAULT_KEYS_SHORTCUT 2L #undef com_idealist_testjniusage_MainActivity_RESULT_CANCELED #define com_idealist_testjniusage_MainActivity_RESULT_CANCELED 0L #undef com_idealist_testjniusage_MainActivity_RESULT_FIRST_USER #define com_idealist_testjniusage_MainActivity_RESULT_FIRST_USER 1L #undef com_idealist_testjniusage_MainActivity_RESULT_OK #define com_idealist_testjniusage_MainActivity_RESULT_OK -1L #undef com_idealist_testjniusage_MainActivity_HONEYCOMB #define com_idealist_testjniusage_MainActivity_HONEYCOMB 11L #undef com_idealist_testjniusage_MainActivity_MSG_REALLY_STOPPED #define com_idealist_testjniusage_MainActivity_MSG_REALLY_STOPPED 1L #undef com_idealist_testjniusage_MainActivity_MSG_RESUME_PENDING #define com_idealist_testjniusage_MainActivity_MSG_RESUME_PENDING 2L JNIEXPORT jstring JNICALL Java_com_idealist_testjniusage_MainActivity_getNativeString (JNIEnv *, jobject) ;#ifdef __cplusplus } #endif #endif
创建对应的源码文件如下: 很简单就是返回一个Hello From JNI!字符串。
#include <jni.h> #include <android/log.h> #ifndef LOG_TAG #define LOG_TAG "ANDROID_LAB" #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) #endif #ifndef _Included_com_idealist_testjniusage_MainActivity #define _Included_com_idealist_testjniusage_MainActivity #ifdef __cplusplus extern "C" {#endif JNIEXPORT jstring JNICALL Java_com_idealist_testjniusage_MainActivity_getNativeString (JNIEnv * env, jobject jObj) { return (*env)->NewStringUTF (env,"Hello From JNI!" ); } #ifdef __cplusplus } #endif #endif
点击运行按钮,这时候很有可能会出现如下的错误: ![](Android studio 下使用JNI/ndkbug.png) 这个问题很简单其实上面已经给出解决方案了,就是在gradle.property这个文件下添加如下配置: ![](Android studio 下使用JNI/fixed.png)
6.修改Module 下的 gradle.build
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.1" defaultConfig { applicationId "com.idealist.testjni" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" // 这里是新增加的 ndk { moduleName "Testjni" // 这个是LoadLibary 参数相同的名字 ldLibs "log" , "z" , "m" abiFilters "armeabi" , "armeabi-v7a" , "x86" // ldLibs "log" , "z" , "m" // 链接时使用到的库,对应LOCAL_LDLIBS // cFlags 编译gcc的flag,对应LOCAL_CFLAGS } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt' ), 'proguard-rules.pro' // 这里是新增加的,用于支持JNIdebug的 ndk { debuggable = true } } debug { // 这里是新增加的,用于支持JNIdebug的 debuggable = true jniDebuggable = true } } } dependencies { compile fileTree(dir: 'libs' , include: ['*.jar' ]) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.0' compile 'com.android.support:design:23.1.0' }
点击运行。 在手机上就可以看到如下的界面了:
![](Android studio 下使用JNI/result.png)
可能长期被eclipse虐惯的人会问了,不用写mk吗?是不用写了,其实在bradle.build上面已经做了类似的工作,这个mk文件会根据你的配置在output 目录下生成,包括各个平台的库文件都会在这个目录下生成,如下图所示: ![](Android studio 下使用JNI/output.png)
下面是生成的mk文件内容: ![](Android studio 下使用JNI/mk.png)
Demo可以在如下地址进行下载:Demo Github