android studio继续深入ndk打包so库和jar Api

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%;

编译后的目录如下:

android studio继续深入ndk打包so库和jar Api_第1张图片

上一篇文章中在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一下:

android studio继续深入ndk打包so库和jar Api_第2张图片

上面配置好并sync后到界面右上角gradle中查找makeJar并双击:

android studio继续深入ndk打包so库和jar Api_第3张图片

然后就生成了相应的jar包:

android studio继续深入ndk打包so库和jar Api_第4张图片

可以看到我们生成的jar,下一步就是测试我们的jar和so是否可用,新建一个项目,并配置gradle:

sourceSets {
    main {
        //jni库的调用会到资源文件夹下libs里面找so文件
        jniLibs.srcDirs = ['libs']
    }
}

把刚才得到的jar和so放置到如下目录:

android studio继续深入ndk打包so库和jar Api_第5张图片

在activity中引用代码:

TextView info = (TextView) findViewById(R.id.info);
info.setText("info:" + JniUtil.getInfo());
运行后正常,到此结束。


你可能感兴趣的:(android)