内容简介:在Android开发中我们经常要把一些比较看重安全或者计算效率的东西通过JNI调用C/C++代码来实现,如果需要实现的功能简单或者你的C/C++代码能力比较强,但是目前还是有很多功能强大的第三方库的,比如openssl、FFmpeg等,调用这些第三方实现显然比重复造轮子实际的多。本教程适合将原始的动态库(.so),即没有包含JNI方法因而java无法直接调用的库链接到自己的C/C++代码中,然后提供调用。添加链接外部静态库和动态库的流程差不多,用
在Android开发中我们经常要把一些比较看重安全或者计算效率的东西通过JNI调用C/C++代码来实现,如果需要实现的功能简单或者你的C/C++代码能力比较强,但是目前还是有很多功能强大的第三方库的,比如openssl、FFmpeg等,调用这些第三方实现显然比重复造轮子实际的多。
本教程适合将原始的动态库(.so),即没有包含JNI方法因而 java 无法直接调用的库链接到自己的C/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 ) 复制代码
链接静态库
## libpng动态库的设置 add_library( # Sets the name of the library. png # Sets the library as ashared library. STATIC # Provides a relative pathto your source file(s). IMPORTED) set_target_properties( png PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libpng.a) 复制代码
链接静态库
## 引入libssl动态库 add_library(ssl SHARED IMPORTED) set_target_properties( ssl PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libssl.so) 复制代码
添加链接外部静态库和动态库的流程差不多,用 STATIC
和 SHARED
来区分
${CMAKE_SOURCE_DIR}
是CMake 中预定义的常量,指当前工程的 CMake 文件所在路径,其他比较有用的常量:
-
CMAKE_CURRENT_SOURCE_DIR
: 指当前 CMake 文件所在的文件夹路径 -
CMAKE_CURRENT_LIST_FILE
: 指当前 CMake 文件的完整路径 -
PROJECT_SOURCE_DIR
:指当前工程的路径
最后将所有库链接起来就行了:
target_link_libraries( # Specifies the target library. native-lib png openssl ssl android # Links the target library to the log library # included in the NDK. ${log-lib} ) 复制代码
实战:引入openssl库供android使用
openssl 是一款强大的加解密库,提供了RSA、AES、MD5等常用的加密算法,网上也有很多编译openssl动态库和静态库的方法。 项目的文件结构目录如下:
- 拷贝openssl的so文件到lib文件夹下
- 拷贝openssl的头文件到cpp的include目录
- 编写cmake文件
# 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. cmake_minimum_required(VERSION 3.4.1) #配置加载头文件 include_directories(./src/main/cpp/include) file(GLOB mian_src "src/main/cpp/*.cpp") # 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. cipher # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). ${mian_src} ) #动态方式加载 add_library(openssl SHARED IMPORTED ) add_library(ssl SHARED IMPORTED ) #引入第三方.so库 set_target_properties(openssl PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcrypto.so) set_target_properties(ssl PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libssl.so) # 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. cipher openssl ssl android # Links the target library to the log library # included in the NDK. ${log-lib} ) 复制代码
- 编写代码调用openssl头文件里面提供的方法:
extern "C" JNIEXPORT jstring JNICALL Java_org_hik_arraytest_MainActivity_md5(JNIEnv *env, jobject instance, jbyteArray src_) { Log_d("MD5->信息摘要算法第五版"); jbyte *src = env->GetByteArrayElements(src_, NULL); jsize src_Len = env->GetArrayLength(src_); char buff[3] = {'\0'}; char hex[33] = {'\0'}; unsigned char digest[MD5_DIGEST_LENGTH]; MD5_CTX ctx; MD5_Init(&ctx); Log_d("MD5->进行MD5信息摘要运算"); MD5_Update(&ctx, src, src_Len); MD5_Final(digest, &ctx); strcpy(hex, ""); Log_d("MD5->把哈希值按%%02x格式定向到缓冲区"); for (int i = 0; i != sizeof(digest); i++) { sprintf(buff, "%02x", digest[i]); strcat(hex, buff); } Log_d("MD5->%s", hex); Log_d("MD5->从jni释放数据指针"); env->ReleaseByteArrayElements(src_, src, 0); return env->NewStringUTF(hex); } 复制代码
- java里调用jni方法
public class MainActivity extends AppCompatActivity { String TAG = "my_openssl"; static { System.loadLibrary("cipher"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i(TAG, "MD5信息摘要->" + md5("1111".getBytes()).toUpperCase()); } /** * MD5编码 */ public native String md5(byte[] src); } 复制代码
结果如下:
遇到的错误:
java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib64/libcrypto.so" needed or dlopened by "/system/lib64/libnativeloader.so" is not accessible for the namespace "classloader-namespace" 复制代码
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcrypto.so" not found 复制代码
在app的 build.gradle
中指定第三方so文件目录,不然生成apk文件的时候不会包含这些so文件。
sourceSets { main { jniLibs.srcDirs = ['libs'] } } 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Making Things See
Greg Borenstein / Make / 2012-2-3 / USD 39.99
Welcome to the Vision Revolution. With Microsoft's Kinect leading the way, you can now use 3D computer vision technology to build digital 3D models of people and objects that you can manipulate with g......一起来看看 《Making Things See》 这本书的介绍吧!