经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
NDK&JNI开发总结
来源:cnblogs  作者:鸡毛落一地  时间:2020/12/8 8:44:51  对本文有异议

NDK&JNI开发总结

简介

附个不错的博客 https://www.jianshu.com/p/87ce6f565d37

在Android Framework中,需要提供一种媒介或 桥梁,将Java层(上层)与C/C++层(下层)有机的联系起来,使得他们互相协调完成某些任务。而充当这种媒介的就是Java本地接口(JNI,Java Native Interface)。JNI提供一些列的接口,允许Java类与C/C++等本地编辑语言(在JNI中,这些语言被称为 本地语言)编写的应用 程序、模块 、库进行交互操作。比如,在Java类中使用C语言库中的函数或在C语言中使用 Java类库,都需要借助JNI。
Android NDK是一个开发工具集,提供一系列工具快速开发C/C++的动态库,并能自动将 .so/.dll 和 Java 应用一起打包到Apk;
NDK提供工具可以方便JNI调用C/C++,而且提供了交叉编译器可以修改.mk文件生成特定CPU平台的动态库,并能将so和java应用一起打包到apk中;简单说就是JNI负责Java与C/C++进行互相操作,NDK提供工具方便在Android平台使用JNI;

JNI的优点

  • 可以调用c/c++代码,效率和性能好
  • JNI编译的so库反编译难度更大

java调用c/c++代码

  1. extern "C"
  2. JNIEXPORT jstring JNICALL
  3. native_test_ffmpeg(JNIEnv *env,jobject thiz){
  4. return env->NewStringUTF("native_test_ffmpeg");
  5. }
  6. //nativeTest是java的native方法名,native_test_ffmpeg是c/c++的实现方法,"()Ljava/lang/String;"代表此方法输入参数为空,输出参数为String
  7. static JNINativeMethod g_methods[] = {
  8. {"nativeTest","()Ljava/lang/String;",(void*)native_test_ffmpeg}
  9. };
  10. //把c/c++方法和java方法关联起来,不需要按照“Java_包名_类名_方法名”规则来生成方法
  11. jint JNI_OnLoad(JavaVM *vm, void *reserved) {
  12. JNIEnv *env = NULL;
  13. vm->GetEnv((void**)&env,JNI_VERSION_1_6);
  14. jclass pJclass = env->FindClass(JNI_CLASS_PATH);
  15. env->RegisterNatives(pJclass,g_methods,sizeof(g_methods)/sizeof(g_methods[0]));
  16. return JNI_VERSION_1_6;
  17. }

signature说明

输入参数在"()"内,输出参数在"()"外,多个参数顺序存放,数组用"["标识。例如:
([Student;)[Student; => Student[] xxx(Student[]){}
(I)S => short xxx(int i){}

基本数据类型对应符号如下:
boolean Z
byte B
char C
short S
int I
long L
float F
double D
void V
java类对应:
L包路径/类名

c/c++调用java代码

  1. extern "C"
  2. JNIEXPORT jstring JNICALL
  3. Java_com_example_ffmpegtest_MainActivity_stringFromJNI2(JNIEnv *env, jobject thiz) {
  4. //step1 找到类
  5. jclass sJclass = env->FindClass(JNI_CLASS_PATH_2);
  6. //step2 找到方法
  7. jmethodID method_init_id = env->GetMethodID(sJclass, "<init>", "()V");//找到构造方法
  8. jmethodID method_set_id = env->GetMethodID(sJclass, "setYear", "(I)V");//找到构造方法
  9. jmethodID method_get_id = env->GetMethodID(sJclass, "getYear", "()I");//找到构造方法
  10. //step3 new object
  11. jobject obj = env->NewObject(sJclass, method_init_id);
  12. //step4 调用相应方法
  13. env->CallVoidMethod(obj,method_set_id,18);
  14. jint year = env->CallIntMethod(obj, method_get_id);
  15. char temp[] = {0,};
  16. sprintf(temp,"%d",year);
  17. std::string helloF = "hello ffmpeg from C++, year =";
  18. helloF.append(temp);
  19. return env->NewStringUTF(helloF.c_str());
  20. }

CMakeLists.txt配置

  1. cmake_minimum_required(VERSION 3.10.2)
  2. # Declares and names the project.
  3. #项目名称,也就是我安卓项目的名字
  4. project("ffmpegtest")
  5. # Creates and names a library, sets it as either STATIC
  6. # or SHARED, and provides the relative paths to its source code.
  7. # You can define multiple libraries, and CMake builds them for you.
  8. # Gradle automatically packages shared libraries with your APK.
  9. # 方式一(验证不通过)
  10. # 引入FFmpeg的库文件,设置内部的方式引入,指定库的目录是 -L 指定具体的库-l
  11. # 这种方式方便快捷
  12. #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L../../../libs/${CMAKE_ANDROID_ARCH_ABI}")
  13. #设置ffmpeg库所在路径的变量
  14. set(FF ${CMAKE_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI})
  15. add_library(avcodec SHARED IMPORTED) #三个参数,第一个,库名称;第二个,SHARED动态库或STATIC静态库;第三个,IMPORTED或xx.cpp
  16. set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${FF}/libavcodec.so) #来源,此处是添加外部引入的库libs/libavcodec.so->avcodec
  17. add_library(avformat SHARED IMPORTED)
  18. set_target_properties(avformat PROPERTIES IMPORTED_LOCATION ${FF}/libavformat.so)
  19. add_library(avutil SHARED IMPORTED)
  20. set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${FF}/libavutil.so)
  21. add_library(swscale SHARED IMPORTED)
  22. set_target_properties(swscale PROPERTIES IMPORTED_LOCATION ${FF}/libswscale.so)
  23. add_library(swresample SHARED IMPORTED)
  24. set_target_properties(swresample PROPERTIES IMPORTED_LOCATION ${FF}/libswresample.so)
  25. add_library(avfilter SHARED IMPORTED)
  26. set_target_properties(avfilter PROPERTIES IMPORTED_LOCATION ${FF}/libavfilter.so)
  27. add_library( native-lib
  28. SHARED
  29. ${CMAKE_SOURCE_DIR}/src/main/cpp/native-lib.cpp)#来源是从native-lib.cpp文件编译
  30. find_library( log-lib log )
  31. find_library( android-lib android )
  32. include_directories(${CMAKE_SOURCE_DIR}/libs/includes)
  33. target_link_libraries( #目标库
  34. native-lib
  35. # 把ffmpeg的动态库以来进来
  36. avformat
  37. avcodec
  38. avutil
  39. avfilter
  40. swscale
  41. swresample
  42. ${log-lib}
  43. ${android-lib})

项目名称,也就是我安卓项目的名字

project("ffmpegtest")

三个参数,第一个,库名称;第二个,SHARED动态库或STATIC静态库;第三个,IMPORTED(外部引入)或xx.cpp(从CPP编译)

add_library( native-lib SHARED ${CMAKE_SOURCE_DIR}/src/main/cpp/native-lib.cpp)
add_library(avcodec SHARED IMPORTED)

来源,此处是添加外部引入的库libs/libavcodec.so->avcodec

set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${FF}/libavcodec.so)

添加依赖的库

find_library( android-lib android )

依赖库文件路径

include_directories(${CMAKE_SOURCE_DIR}/libs/includes)

把动态库链接到一个库,第一个参数目标库,后面参数都是要链接的库

target_link_libraries( #目标库
native-lib
# 把ffmpeg的动态库以来进来
avformat
avcodec
avutil
avfilter
swscale
swresample
${log-lib}
${android-lib})

原文链接:http://www.cnblogs.com/yidijimao/p/14077775.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号