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++代码

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

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代码

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

CMakeLists.txt配置

cmake_minimum_required(VERSION 3.10.2)

# Declares and names the project.

#项目名称,也就是我安卓项目的名字
project("ffmpegtest") # 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. # 方式一(验证不通过)
# 引入FFmpeg的库文件,设置内部的方式引入,指定库的目录是 -L 指定具体的库-l
# 这种方式方便快捷
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L../../../libs/${CMAKE_ANDROID_ARCH_ABI}") #设置ffmpeg库所在路径的变量
set(FF ${CMAKE_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI})
add_library(avcodec SHARED IMPORTED) #三个参数,第一个,库名称;第二个,SHARED动态库或STATIC静态库;第三个,IMPORTED或xx.cpp
set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${FF}/libavcodec.so) #来源,此处是添加外部引入的库libs/libavcodec.so->avcodec add_library(avformat SHARED IMPORTED)
set_target_properties(avformat PROPERTIES IMPORTED_LOCATION ${FF}/libavformat.so) add_library(avutil SHARED IMPORTED)
set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${FF}/libavutil.so) add_library(swscale SHARED IMPORTED)
set_target_properties(swscale PROPERTIES IMPORTED_LOCATION ${FF}/libswscale.so) add_library(swresample SHARED IMPORTED)
set_target_properties(swresample PROPERTIES IMPORTED_LOCATION ${FF}/libswresample.so) add_library(avfilter SHARED IMPORTED)
set_target_properties(avfilter PROPERTIES IMPORTED_LOCATION ${FF}/libavfilter.so) add_library( native-lib
SHARED
${CMAKE_SOURCE_DIR}/src/main/cpp/native-lib.cpp)#来源是从native-lib.cpp文件编译 find_library( log-lib log )
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})

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

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})

NDK&JNI开发总结的更多相关文章

  1. AndroidStudio如何配置NDK/JNI开发环境

    参考文章: http://www.th7.cn/Program/Android/201509/550864.shtml http://www.open-open.com/lib/view/open14 ...

  2. 【android 开 发 】 - Android studio 下 NDK Jni 开发 简单例子

    Android 开发了一段时间,一方面 ,感觉不留下点什么.有点对不起自己, 另一方面,好记性不如烂笔头,为了往后可以回头来看看,就当做是笔记,便决定开始写博客.废话不多说 ! 今天想搞一搞 ndk ...

  3. Android studio 下 NDK Jni 开发 简单例子

    1. 创建一个新的工程 2. 创建一个新的类 JniText.java  点击Build--Make Project  后     选中工程 点击F4键 sdk location 中 Android ...

  4. Android Studio上NDK/JNI开发环境问题

    基础环境: 操作系统 —— Windows 7 Android Studio —— 1.5.1(android-studio-bundle-141.2456560-windows.exe) NDK — ...

  5. NDK Jni 开发(1)

    1. 学习地址 http://my.oschina.net/lifj/blog/177087 http://www.cnblogs.com/devinzhang/archive/2012/02/29/ ...

  6. Android游戏开发实践(1)之NDK与JNI开发03

    Android游戏开发实践(1)之NDK与JNI开发03 前面已经分享了两篇有关Android平台NDK与JNI开发相关的内容.以下列举前面两篇的链接地址,感兴趣的可以再回顾下.那么,这篇继续这个小专 ...

  7. Android游戏开发实践(1)之NDK与JNI开发01

    Android游戏开发实践(1)之NDK与JNI开发01 NDK是Native Developement Kit的缩写,顾名思义,NDK是Google提供的一套原生Java代码与本地C/C++代码&q ...

  8. Android游戏开发实践(1)之NDK与JNI开发02

    Android游戏开发实践(1)之NDK与JNI开发02 承接上篇Android游戏开发实践(1)之NDK与JNI开发01分享完JNI的基础和简要开发流程之后,再来分享下在Android环境下的JNI ...

  9. 史上最易懂的Android jni开发资料--NDK环境搭建

    谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwin才能使用NDK.而在NDKr7开始,Google的Windows版的NDK提供 ...

随机推荐

  1. Ordering Cows

    题意描述 好像找不到链接(找到了请联系作者谢谢),所以题目描述会十分详细: Problem 1: Ordering Cows [Bruce Merry, South African Computer ...

  2. 2018-12-5 及 codeforces round 525v2

    突然发现五天没记录了,这五天学习完全没有按着正常规划进行,先罗列一下吧. 机器学习视频第一周的全部看完了. 算法导论看了几页. 参加了一次CF.rating只加了20,看来提高实力才是最关键的. C+ ...

  3. 想学 iOS 开发高阶一点的东西,从何开始?

    前言 如果你正在学习 iOS, 或者正在从事IOS开发? 还是一个一个迷茫的待就业大学生,或是公司的到一个半老员工? 现在到了开发的一个阶段了,基本的东西很熟了,想着提高技术? 学习难一点的东西,不知 ...

  4. 2020最常见的200+Java面试题汇总(含答案解析)

    前言 2020年快要结束了,很多朋友问题,有没有整理今年的一些面试题,最近抽时间整理了一份Java面试题.或许这份面试题还不足以囊括所有 Java 问题,但有了它,我相信足以应对目前市面上绝大部分的 ...

  5. project--客户信息管理系统

    软件设计分析 该软件有三个模块组成:Customer  CustomerList  CustomerView Customer 为实体对象,用来封装客户信息: CustomerList 为 Custo ...

  6. Spider--补充--Re模块_2

    # @ Author : Collin_PXY # Python 正则表达式的应用(二) # 正则表达式之所以让人头疼,很大程度是因为表达式里有大量的符号及它们的组合,还有很多匹配模式,想要记住比较困 ...

  7. C# + Matlab 实现计件工时基于三层BP神经网络的拟合--真实项目

    工序工时由该工序的工艺参数决定,有了工时后乘以固定因子就是计件工资.一般参考本地小时工资以及同类小时工资并考虑作业的风险等因素给出固定因子 采用的VS2010 , Matlab2015a 64,  开 ...

  8. 庐山真面目之四微服务架构Consul集群和Nginx版本实现

    庐山真面目之四微服务架构Consul集群和Nginx版本实现 一.简介      在上一篇文章<庐山真面目之三微服务架构Consul版本实现>中,我们已经探讨了如何搭建基于单节点Consu ...

  9. 在linux下,为什么 i386 ELF可执行文件默认从地址(.text)0x08048000开始分配。 而 x64是0x400000

  10. MVCC(转)

    什么是 MVCC MVCC (Multiversion Concurrency Control) 中文全程叫多版本并发控制,是现代数据库(包括 MySQL.Oracle.PostgreSQL 等)引擎 ...