android studio 初步JNI开发
android studio在原有项目中使用cmake构建JNI
android studio用Javah创建.h头文件和编译运行
android studio继续深入ndk打包so库和jar Api
在AS的terminal中可以使用指令直接编译so库,如下:
D:\wangpeng\android\workstudio\TestJni\jnilib\src\main\jni>ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.
Android NDK: WARNING: APP_PLATFORM android-14 is higher than android:minSdkVersion 1 in D:/wangpeng/android/workstudio/TestJn
i/jnilib/src/main/AndroidManifest.xml. NDK binaries will *not* be comptible with devices older than android-14. See https://a
ndroid.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.
[arm64-v8a] Compile++ : jnido <= jnido.cpp
[arm64-v8a] StaticLibrary : libstdc++.a
[arm64-v8a] SharedLibrary : libjnido.so
[arm64-v8a] Install : libjnido.so => libs/arm64-v8a/libjnido.so
[armeabi-v7a] Compile++ thumb: jnido <= jnido.cpp
[armeabi-v7a] StaticLibrary : libstdc++.a
[armeabi-v7a] SharedLibrary : libjnido.so
[armeabi-v7a] Install : libjnido.so => libs/armeabi-v7a/libjnido.so
[x86] Compile++ : jnido <= jnido.cpp
[x86] StaticLibrary : libstdc++.a
[x86] SharedLibrary : libjnido.so
[x86] Install : libjnido.so => libs/x86/libjnido.so
[x86_64] Compile++ : jnido <= jnido.cpp
[x86_64] StaticLibrary : libstdc++.a
[x86_64] SharedLibrary : libjnido.so
[x86_64] Install : libjnido.so => libs/x86_64/libjnido.so
执行此命令可能会遇到'ndk-build' 不是内部或外部命令,也不是可运行的程序的问题,只需要配置下环境变量就行了。
变量名:NDK_HOME
变量值:D:\wangpeng\android\sdk\ndk-bundle
path;%NDK_HOME%;
编译后的目录如下:
上一篇文章中在gradle中配置了.mk文件的路径,通过mk文件配置编译的参数:
externalNativeBuild {
ndkBuild {
path file("src\\main\\jni\\Android.mk")
}
}
AS提供了另一种配置的方法:
defaultConfig { minSdkVersion 14 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ndk { moduleName"jnido" ldLibs "log", "z", "m" abiFilters "armeabi", "armeabi-v7a", "x86" } }
这样就可以去掉之前的那个配置了,但是如果想用ndk-build指令的话,.mk文件需要保留。
到此为止我们是已经基本能够使用ndk的功能了,也能编译出so库了。但是遗憾的是这个so库的通用性并不大,为什么呢?
还记得cpp函数名吗?函数名是和Java层的包名紧密结合的,如果A项目的so库拿到B项目中用是肯定有问题的,毕竟他们的包名是不同的!这样我们就需要提供so相匹配的jar API。
首先gradle中添加如下配置:
def SDK_NAME = "jmido"; def SDK_VERSION = "_V222"; def sdkDestinationPath = "build"; def zipFile = file('build/intermediates/bundles/default/classes.jar') task deleteBuild(type: Delete) { delete sdkDestinationPath + SDK_NAME + SDK_VERSION + ".jar" } task makeJar(type: Jar) { from zipTree(zipFile) from fileTree(dir: 'src/main',includes: ['assets/**']) baseName = SDK_NAME + SDK_VERSION destinationDir = file(sdkDestinationPath) } makeJar.dependsOn(deleteBuild, build)
需要注意那个zipFile的地址是否存在,如果不存在rebuild一下:
上面配置好并sync后到界面右上角gradle中查找makeJar并双击:
然后就生成了相应的jar包:
可以看到我们生成的jar,下一步就是测试我们的jar和so是否可用,新建一个项目,并配置gradle:
sourceSets { main { //jni库的调用会到资源文件夹下libs里面找so文件 jniLibs.srcDirs = ['libs'] } }
把刚才得到的jar和so放置到如下目录:
在activity中引用代码:
TextView info = (TextView) findViewById(R.id.info); info.setText("info:" + JniUtil.getInfo());运行后正常,到此结束。