NDK 之生成so库

Android Studio 配置 NDK(一)

什么是ndk, 简单的讲就是ndk可以让你调用到c/c++方法来实现一些比较安全的功能,例如你完全可以将Android程序的数据 通过c/c++原来编写存储, 然后通过jni方式调用方法,而且在实现的时候, 也可以各种加密,让后程序的数据更加安全。

最近想给项目应用增量更新,所以就折腾了一下ndk。

和以往的ndk开发方式不太一样。

1.现在查到的资料大部分套路都是需要先通过javah文件方式生成.h文件, 然后写对应的实现文件.c /. cpp,最终配置文件android.mk, Application.mk,放在jni目录下, 执行ndk-build命令,最终生成可用的.so库

2.使用官方提供的gradle-experimental插件(gradle的版本和插件版本要对应),照着官方文档在gradle中一顿配置后, 编写native 方法,alter+enter键,最终还是未出来。

最终发现, 其实现在的android studio都是很智能,配置好模块,make project的时候自动帮你编译生成.so库文件, 基本上不用配置什么,最终还是能很容易的就编出hello world。这里只是简单的讲一下ndk建立项目的一些初步问题, 高手请绕道。

1.新建立一个项目:
2.配置gradle

 android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.caldremch.myapplication"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        ndk{
            moduleName = "cade"

            //abiFilters "x86","armeabi-v7a" //这里填写两个abi cpu架构,如果什么都不写,则默认支持所有平台
        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.建立一个类 ,包含native方法,此时会有看到方法是红色的, 这很正常的

public class JNITest {

    static {
        System.loadLibrary("cade"); //这里的cade跟gradle配置的modulename一致
    }

    public native String getAA(); //native方法

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4.切刀Java目录 ,输入命令.javah -d ../jni 包名.类名(例如com.cade.utils.JNITest)
,生成.h文件, 编写对应的.c文件

这里写图片描述


hello.c文件为:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <string.h>
#include "hello.h" //这里注意, 如果刚才没有改文件名,那么这里就不是hello.h了

jstring Java_com_caldremch_myapplication_JNITest_getAA
  (JNIEnv * env, jobject clazz)
  {

    return (*env)->NewStringUTF(env, "测试成功没有");

  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

准备工作已经差不多了, 接下里还要在gradle.properties文件中加上一句:


android.useDeprecatedNdk=true //不加有可能导致编译不成功
  • 1
  • 2
  • 1
  • 2

执行编译:菜单栏 build—》make project(��图标)

在MainActivity中引测试

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = (TextView) findViewById(R.id.text);
        textView.setText(new JNITest().getAA());
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接下来我们看看到底.so库在哪里生成了?

这里写图片描述

看到结果了吧。

这里说几点:
1.配置不让gradle自动编译,自己编译,那么在build.gradleandroid节点下设置

//    sourceSets.main{
//            jni.srcDirs = []//设置禁止gradle生成Android.mk
//            jniLibs.srcDirs = ['src/main/jniLibs']//设置目标的so存放路径
//    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

2.如果一个项目中,有多个引用的.so库, 请注意一点, 一定让它们支持的cpu abi数量和类型 一样。不然会报错 java.lang.UnsatisfiedLinkError
例如在一同一个项目中有ndk模块

   ndk {
            moduleName = 'module1'

            abiFilters "x86","armeabi-v7a"
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在另一个依赖项目:

   ndk {
            moduleName = 'module2'

            abiFilters "x86","armeabi-v7a"
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

如果它们 abiFilters不一样,数量或者类型有别, 那么将导致错误。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章