cmake导入so库_通过CMake方式生成动态库so文件

JNITest

通过CMake方式生成动态库so文件

简介 Java JNI的本意是Java Native Interface(Java本地接口),它是为了方便Java调用C、C++等本地代码所封装的一层接口。通过Java JNI,用户可以调用用C、C++所编写的本地代码 NDK是Android所提供的一个工具集合,通过NDK可以在Android中更加方便地通过JNI来访问本地代码。

优势 1.提高代码的安全性。由于so库反编译比较困难,因为NDK提高了Android程序的安全性。

2.可以很方便地使用目前已有的C/C++开源库

3.便于平台间的移植。

4.提高程序在某些特定情形下的执行效率,但是并不能提升Android程序性能

注:JNI和NDK开发所用到的动态库的格式是以.so为后缀的文件,JNI和NDK主要用于底层和嵌入式开发,在Android应用层开发中使用比较少。

JNI开发流程

1.在Android Studio配置NDK环境

打开SDKManager-tools下载NDK插件,下载后到SDK Location里面检查里面的NDK路径

2.在Java中声明native方法 创建一个类,叫做JNITest.java

package com.qinkl;

public class JNITest{

static{

System.loadLibrary("jni-test");

}

public static void main(String args[]){

JNITest jniTest = new JNITest();

System.out.println(jniTest.jniGet());

jniTest.jniSet("hello world");

}

public native String jniGet();

public native void jniSet(String str);

}

可以看到上面的代码中,声明了两个native方法:get和set(String),这两个就是需要在JNI中实现的方法。在JniTest的头部有一个加载动态库的静态代码块,其中jni-test是so库的标识,so库完整的名称为libjni-test.so,这是加载so库的规范

3.编译Java源文件得到class文件,然后通过javah命令导出JNI的头文件

进入cmd,(cd /d 任意目录),选择进入项目文件目录,具体的命令为

javac com/qinkl/JNITest.java

javah com.qinkl.JNITest

JDK10以前用:javah com.qinkl.JNITest

JDK10以后是没有提供javah的,要用javac代替javah命令:进入cmd,切换到文件所在的根目录,执行命令javac -encoding utf8 -h . JNITest.java

在当前目录下,会产生com_qinkl_JNITest.h的头文件,它是上述命令生成的,内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class com_qinkl_JNITest */

#ifndef _Included_com_qinkl_JNITest

#define _Included_com_qinkl_JNITest

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: com_qinkl_JNITest

* Method: jniGet

* Signature: ()Ljava/lang/String;

*/

JNIEXPORT jstring JNICALL Java_com_qinkl_JNITest_jniGet

(JNIEnv *, jobject);

/*

* Class: com_qinkl_JNITest

* Method: jniSet

* Signature: (Ljava/lang/String;)V

*/

JNIEXPORT void JNICALL Java_com_qinkl_JNITest_jniSet

(JNIEnv *, jobject, jstring);

#ifdef __cplusplus

}

#endif

#endif

说明

JNIEnv*:表示一个指向JNI环境的指针,可以通过它来访问JNI提供的接口方法

jobect:表示Java对象中的this

JNIEXPORT和JNICALL:他们是JNI中所定义的宏,可以在JNI.h这个头文件中查找到

4.实现JNI方法

JNI方法是指Java中声明的native方法,这里可以选择用c++和c来实现。

首先,在工程的主目录下创建一个名为jni的子目录,把之前生成的头文件com_qinkl_JNITest复制进来,接着创建test.cpp文件,内容如下:

#include "com_qinkl_JNITest.h"

JNIEXPORT jstring JNICALL Java_com_qinkl_JNITest_jniGet(JNIEnv *env,jobject thiz){

printf("invoke get in c++\n");

return (*env)->NewStringUTF(env,"Hello from JNI!");

}

JNIEXPORT void JNICALL Java_com_qinkl_JNITest_jniSet(JNIEnv *env,jobject thiz,jstring string){

printf("invoke set in c++\n");

char* str = (char*)(*env)->GetStringUTFChars(env,string,NULL);

printf("%s\n",str);

(*env)->ReleaseStringUTFChars(env,string,str);

}

5.生成so库

在gradle3.0以前生成的方式是,在根目录gradle.properties下面加上:

android.useDeprecatedNdk=true

然后在项目build.gradle的defaultConfig节点下,添加代码:

ndk{

moduleName "jni-test"//指定生成的so文件名

abiFilters "armeabi","armeabi-v7a","x86"//CPU的类型

}

这两步就可以运行生成so库了

但如果在gradle 3.0之后,已经不支持这样的生成方式了,会报错,内容如下

Error: Flag android.useDeprecatedNdk is no longer supported and will be removed in the next version of Android Studio.

在gradle3.0以上的构建方式:

1.首先先到SDKManager->SDK Tools,下载CMake和LLDB

2.在项目build.gradle的defaultConfig节点下,添加代码:

externalNativeBuild{

cmake{

cppFlags ""

//生成多个版本的so库

abiFilters 'armeabi-v7a','arm64-v8a'

}

}

3.在项目build.gradle的android节点下,添加代码

externalNativeBuild{

cmake{

path "CMakeLists.txt"//编译后so文件的名字

}

}

4.在项目app目录下新建CMakeLists.txt文件,内容如下

# For more information about using CMake with Android Studio, read the

#documentation: https://d.android.com/studio/projects/add-native-code.html

#Sets the minimum version of CMake required to build the native library.

#CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)

#Creates and names a library, sets it as either STATIC

#or SHARED, and provides the relative paths to its source code.

#You can define multiple libraries, and CMake builds them for you.

#Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.

# 设置so文件名称.

jni-test

# Sets the library as a shared library.

SHARED

# 设置这个so文件为共享.

# Provides a relative path to your source file(s).

# 设置这个so文件为共享.

src/main/jni/test.c)

#Searches for a specified prebuilt library and stores the path as a

#variable. Because CMake includes system libraries in the search path by

#default, you only need to specify the name of the public NDK library

#you want to add. CMake verifies that the library exists before

#completing its build.

find_library( # Sets the name of the path variable.

log-lib

# Specifies the name of the NDK library that

# you want CMake to locate.

log )

#Specifies libraries CMake should link to your target library. You

#can link multiple libraries, such as libraries you define in this

#build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.

# 制定目标库.

jni-test

# Links the target library to the log library

# included in the NDK.

${log-lib} )

5.点击build构建一下,可能会出现一下问题:

executing external native build for cmake

将gradle的版本3.1.2改成3.2.1,我这边就解决了,再点击build构建一下,就可以在app/build/cmake/debug/obj路径下看到生成的so库了,大功告成!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值