赞
踩
最近在帮助项目的大神测试编译出来的安卓动态库,需要用到jni,但是使用ndk去编译有太麻烦(还是懒),毕竟库太多了。然后以前听说android studio被谷歌搞得可以使用cmake
去编译源码库,于是乎,就更新了许久未用的android studio。在这个过程中真的是很恶心。使用jni动态注册函数时,总是注册不过,最后就是用android studio原声的
native-lib.cpp通过静态注册的方式搞定。
在CmakeList.txt文件中需要最一些配置更改。
这个是项目打开时原版本的CmakeList.txt在这个基础上加上自己所需要的静态库
- cmake_minimum_required(VERSION 3.4.1)
-
- #将静态库的头文件添加进来
- include_directories(
- ${CMAKE_SOURCE_DIR/src/main/include} #头文件多的话可以继续往下加
- ${CMAKE_SOURCE_DIR/src/main/include/..}
-
- ${CMAKE_SOURCE_DIR/src/main/include/...}
-
- 。。。。
- )
- add_library( # 自己的库名字
- native-lib
-
- # 将自己的库编译成动态库
- SHARED
-
- # 自己的cpp源码所在的路径即jni源码的路径
- src/main/cpp/native-lib.cpp )
-
- #添加自己所需的静态库 库多的话,可以使用下面的方式添加
- add_library( event #库名字 去掉了 lib 与 .a
- STATIC #必须的
- IMPORTED #必须的
- )
- set_target_properties(
- event
- PROPERTIES IMPORTED_LOCATION
- ${CMAKE_SOURCE_DIR}/libs/libevent.a #库在的路径,以cmakeList.txt所在的路径起
- )
-
- #添加自己所需的静态库 库多的话,可以使用下面的方式添加
- add_library( event #库名字 去掉了 lib 与 .a
- STATIC #必须的
- IMPORTED #必须的
- )
- set_target_properties(
- event
- PROPERTIES IMPORTED_LOCATION
- ${CMAKE_SOURCE_DIR}/libs/libevent.a #库在的路径,以cmakeList.txt所在的路径起
-
- )
-
-
-
- find_library( log-lib log ) target_link_libraries( native-lib #我自己的需要生成的动态库 event #将所需的库和自己要生成的动态库连接起来,多的话一次向下追加 x264 faac ${log-lib} )
-
- 在native-lib.cpp文件中写上的是关于自己的jni函数,将所需头文件包含进来,就可以通过jni函数调用静态库的函数。
-
-
-
- #include <jni.h>
- #include <string>
- #include <stdio.h>
-
- #include "ares.h"
- #include "faac.h"
- #include "uuid.h"
- #include "turbojpeg.h"
- #include "x264.h"
-
-
- void insertSort(int *data,int len);
- //调用libcares的例子
- extern "C"
- JNIEXPORT jint JNICALL Java_com_skylight_testlibs_JNIHeader_AreasLibInit(JNIEnv *env, jobject )
- {
- jint result=ares_library_init(1);
- return result;
- }
- //调用libuuid的例子
- extern "C"
- JNIEXPORT jint JNICALL Java_com_skylight_testlibs_JNIHeader_UuidIsNull(JNIEnv *env, jobject)
- {
- const uuid_t uu= {0};
- jint result=uuid_is_null(uu);
- return result;
- }
-
- //调用libturbojpeg的例子
- extern "C"
- JNIEXPORT jint JNICALL Java_com_skylight_testlibs_JNIHeader_TJAlloc(JNIEnv *env, jobject )
- {
- unsigned char* c= tjAlloc(128);
- const char* result=(const char*)c;
- if (c == NULL)
- {
- return -1;
- } else{
- return 0;
- }
-
- }
- //调用libx264库的例子
- extern "C"
- JNIEXPORT jint JNICALL Java_com_skylight_testlibs_JNIHeader_X264PictureAlloc(JNIEnv *env, jobject )
- {
- x264_picture_t *ipic= nullptr;
- x264_picture_init( ipic );
- jint result= x264_picture_alloc( ipic, 32, 512, 256 );
- return result;
- }
- //调用faac库的函数例子
- extern "C"
- JNIEXPORT jint JNICALL Java_com_skylight_testlibs_JNIHeader_FaacEncClose(JNIEnv *env, jobject )
- {
- jint result=-2;
- unsigned long nSampleRate = 44100;
- unsigned int nChannels = 2;
- unsigned int nPCMBitSize = 16;
- unsigned long nInputSamples = 0;
- unsigned long nMaxOutputBytes = 0;
- faacEncHandle hEncoder = {0};
- faacEncHandle handle= faacEncOpen(nSampleRate, nChannels, &nInputSamples, &nMaxOutputBytes);
- if (handle == NULL)
- {
- result= -1;
- } else{
- result= 0;
- }
- return result;
- }
-
- //调用insertSort函数
- extern "C"
- JNIEXPORT void JNICALL Java_com_skylight_testlibs_JNIHeader_insertSortArray(JNIEnv *env, jobject obj,jintArray array)
- {
- jint *data=env->GetIntArrayElements(array,NULL);
- jsize len=env->GetArrayLength(array);
- insertSort(data,len);
- env->ReleaseIntArrayElements(array,data,0);
- }
- //排序
- void insertSort(int *data,int len)
- {
- int temp = 0;
- int i = 1;
- int j = 0;
- for (; i < len; i++)
- {
- temp = data[i];
- j = (i - 1);
- for (; j >= 0; j--)
- {
- if (data[j] > temp)
- {
- data[j + 1] = data[j];
- }
- else
- {
- break;
- }
- }
- data[j + 1] = temp;
- }
- }
-
-
- 在java层的代码就很简单了直接写上native方法就行可以了。
-
-
- public class JNIHeader
- {
- static {
- System.loadLibrary("native-lib");
- }
- public native void insertSortArray(int[] data);
- public native int AreasLibInit();
- public native int UuidIsNull();
- public native int TJAlloc();
- public native int X264PictureAlloc();
- public native int FaacEncClose();
- }
-
- 在build.gradle中还需要加入以下配置,在defaultConfig中加入下面的配置,
-
-
- externalNativeBuild {
- cmake {
- arguments '-DANDROID_PLATFORM=android-23',
- '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=gnustl_static'
- }
- }
-
- ndk {
- abiFilters 'armeabi-v7a' // armeabi-v7a 这里需要过滤一下处理器类型
- }
-
- 在defaultConfig的下面加入这个配置
-
- sourceSets {
- main {
- jniLibs.srcDirs = ['libs']
- }
- }
-
- 这样就可以使用cmake在android studio中调用静态库的函数了
- android studio在调用动态库时和调用静态库的方式略有不同,不知道别人是
- 怎么解决的,目前我的android studio碰到调用动态库的问题如下:
- 1、在src/main/目录下新建一个文件夹jniLibs,在该文件夹中需要建立区分ABI的类型的文件夹
- -->即armeabi-v7a armeabi-arm 等子文件夹,最终的目录会是
- ------>src
- ---------->main
- --------------->jniLibs
- ----------------------->armeabi-v7a(armeabi-arm)等
- 路径会是--->src/main/jniLibs/armeabi-v7a 或者对应的ABI
- 2、将自己所要调用的动态库.so文件放置在上述目录中 例如(src/main/jniLibs/armeabi-v7a/xxxx.so)
- 3、在CmakeList.txt文件中添加动态库
- add_library( 库名 SHARED IMPORTED )
-
- set_target_properties( 库名 PROPERTIES
- IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/lib库名.so )
- 注:ANDROID_ABI就是ABI类型--->armeabi-v7a或者对应的
-
- 4、在java代码中加载动态库
- System.loadLibrary("库名");
- 建议:将调用的动态库放在native-lib库的上面。先加载三方动态库
-
- 5、在target_link_libraries()中将动态库添加进去
去编译源码库,于是乎,就更新了许久未用的android studio。在这个过程中真的是很恶心。使用jni动态注册函数时,总是注册不过,最后就是用android studio原声的
native-lib.cpp通过静态注册的方式搞定。
在CmakeList.txt文件中需要最一些配置更改。
这个是项目打开时原版本的CmakeList.txt在这个基础上加上自己所需要的静态库
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。