Android编写.so入门介绍

Android开发中,我们经常会用到.so文件。原因有很多,比如部分方法不想暴露,如加密规则。比如部分秘钥需要存储,哪怕最简单的一个加盐的String。我们使用.so调用获取这个String,也比直接明文写在代码中要来的安全。所以就需要我们安卓开发的同学,要知道简单的.so怎么编写。今天为大家带来一篇,如何通过Native方法,从.so中获取一个字符串(可以存储秘钥哦)。

Native开发,那就需要对应的NDK的环境。使用Android Studio开发的同学就会很简单了。当然,我一开始也不会,也是通过搜网上的代码,只是因为网上的代码有些生硬,不容易理解。我硬是弄了一下午,可能水平也不够,那我就写的简单一点。

一、配置Android NDK location

打开local.properties

Android编写.so入门介绍

如果页面已经包含了ndk.dri 以及sdk.dir 那就说明你已经配置过NDK的路径了(忽略下面的步骤,直接到第二步)

Android编写.so入门介绍

如果你没有配置过,那就打开配置SDK以及JDK的地方。最下面这个就是NDK。从网上下载NDK,配置好环境。

Android编写.so入门介绍

二、配置gradle.properties(如下图)

Android编写.so入门介绍

打开这个页面可以看到

Android编写.so入门介绍

这里需要重点说明一下。

一般情况下配置的是

android.useDeprecatedNdk=true

如果出现以下错误

Error:Execution failed for task ':app:compileDebugNdk'.
> Error: Flag android.useDeprecatedNdk is no longer supported and will be removed in the next version of Android Studio.  Please switch to a supported build system.
  Consider using CMake or ndk-build integration. For more information, go to:
   https://d.android.com/r/studio-ui/add-native-code.html#ndkCompile
   To get started, you can use the sample ndk-build script the Android
   plugin generated for you at:
   /Users/Xiaonima/MyJniTest/app/build/intermediates/ndk/debug/Android.mk
  Alternatively, you can use the experimental plugin:
   https://developer.android.com/r/tools/experimental-plugin.html
  To continue using the deprecated NDK compile for another 60 days, set 
  android.deprecatedNdkCompileLease=1516073275899 in gradle.properties

说明你的Android studio的版本是3.0以上的,提示说你的NDK有问题了,这个应该是过期了,英语不好,没仔细看。

注释掉android.useDeprecatedNdk=true

加上这个配置

android.deprecatedNdkCompileLease=1511832698813

三、开始编写我们的Native方法

到了这里,环境已经搭配好,我们开始正在写需要调用的方法。这里就以最简单的,通过Native方法获取一个字符串。

创建一个类。先写好需要加载的.so(我们最终创建好以后的.so名)。以及写上你需要调用的Native方法名。

Android编写.so入门介绍

我这边就是最简单的,加载我这个.so 然后静态的native方法。

类创建完,以及定义好方法以后。Build --> Make Project

Android编写.so入门介绍


四、通过terminal控制台编译

如果顺利的同学到了这个时候可以在这里查看到这个.class 的文件

Android编写.so入门介绍


这个时候说明我们的定义Native方法成功了。然后我们就需要通过控制台命令,生成对应的.h文件。

首先我们需要知道,我们目前处在最外层的文件夹。同时,我们需要生成一个.h的文件到main的jni 的文件夹下。

这个时候我们先 cd app/src/main 这个时候先到指定的main路径下 执行javah -d jni -classpath (之前带你们查看的那个.class文件的路径)

如 下图: 一直到debug 为止 然后再加上包名 和对应的.class的文件名(后缀不要)

说明一下,如果不成功,可能是你的sdk 没有配置环境变量,这里不详细讲解。不会的同学,可以上网搜索。

Android编写.so入门介绍

五、创建对应的.c文件

如果到了这里都没有问题的同学,这个时候会发现我们的main目录下多了一个jni的目录,点开目录可以看到我们之前通过控制台生成的.h文件。

我们不用去管这个生成的对应的.h文件。我们直接在下方创建一个.c的文件。

Android编写.so入门介绍


#include "com_jni_xiaonima_myapplication_NativeUtils.h"
/**
 * 上边的引用一定要和.h的文件名加后缀,
 * 下面的方法名一定要和.h文件中的方法名称一样
 */
JNIEXPORT jstring JNICALL Java_com_jni_xiaonima_myapplication_NativeUtils_getStringFromNative
            (JNIEnv *env, jobject obj) {
        return (*env)->NewStringUTF(env, "小尼玛其乐无穷");
}

直接贴出代码,容易复制。认真看我的注释。

这个地方就是 通过Native方法 获取返回值,具体不要问我代码怎么写,C代码我也不会。

六、最后配置一下生成 .so

如果你一直到了这里,那么我即将要恭喜你,终于到了最后了。打开app下对应的build.gradle。

在我写注释的地方配置你需要支持的.so文件。

Android编写.so入门介绍

//ndk编译生成.so文件
ndk {
    moduleName "xnmjni"         //生成的so名字
    abiFilters "armeabi", "armeabi-v7a", "x86"  //输出指定三种abi体系结构下的so库。
}

贴出代码,方便复制。

七、生成.so文件。

终于走到最后一步了。

我们配置好了上面的build.gradle 以后,使用Rebuild。不知道在哪里的同学需要打头了。

这个时候我们可以在如下图位置,发现生成了刚刚配置的对应的.so文件。直接复制出来,放到对应的目录下。jni目录路径如果你没有指定过。

那就有默认的规则,统一在main目录下,新建一个jniLibs。一定不要命名错误,文件位置也千万不要错误。否则会加载失败。

Android编写.so入门介绍


Android编写.so入门介绍


总结:  生成完了.so 那么对应的jni里面的c代码就不需要了。你可以删除,可以保存到别的地方。总之,你开心就好。

一般自己动手操作个2 - 3遍就能熟练掌握生成.so的方法。当然如果要具体写C代码的实现,那么就需要继续学习一下C代码了。

文中有任何错误,请指正,接收一切批评。

最后再说明一点,生成的.so 会在名字前面加上lib***.so(说明一下,不要管这个lib 以及这个后缀)我们在调用的时候就是这个***就可以了。