深入了解Android NDK

Android NDK提供的组件:

  • Android NDK并不是一个单独的工具, 他是一个包含API、交叉编译器、链接程序、调试器、构建工具、文档和实例应用程序的综合工具集

主要的组件:

ARM、x86和MIPS交叉编译器
构建系统
Java原生接口头文件
C库
Math库
POSIX线程
最小的C++库
ZLib压缩库
动态链接库
Android日志库
Android像素缓冲区库
Android原生应用的APIS
OpenGL ES 3D图形库
OpenSL ES 原生音频库
OpenMAX  AL 最小支持

Android NDK的结构: 

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

ndk-build:该shell脚本是AndroidNDK构建系统的起始点

ndk-gdb:该shell脚本允许使用GUN调试器调试原生组件

ndk-stack:该shell脚本可以帮助分析原生组件崩溃时的堆栈追踪

build:该目录包括了Android NDK构建系统的所有模块

platforms:该目录包含了支持不同Android目标版本的头尾件和库文件,NDK构建系统会根据具体的Android版本自动的引用这些文档

samples:该目录包含了示例程序

sources:该目录包含了可供开发人员导入到现有的Android NDK项目中的一些共享模块

toolchains:该目录包含目前Android NDK支持的不同目标机体系结构的交叉编译器,目前支持ARM,X86, MIPS

构建系统(老方法)

构建系统是基于GUN Make的,该构件系统主要目的是使开发人员使用短的构建文档来描述Android应用

该构建系统处理了处理工具链,指定平台,CPU, ABI等细节

该构建系统是由多种GUN Makefile片段构成的

该系统的两个依赖文件:Android.mk, Application.mk

Android.mk文件:

Android.mk文件是一个向Android NDK构建系统描述NDK项目的GUN Makefile片段,是一个NDK项目的必备组件,在JNI目录中:

LOCAL_PATH := $(call my-dir) 
include $(CLEAR_VARS) 
LOCAL_MODULE:= native-lib 
LOCAL_SRC_FILES := native-lib.cpp 
LOCAL_LDLIBS := -fpic -fPIE -pie 
include $(BUILD_SHARED_LIBRARY)

命名规范: 变量名要大写

Android.mk文档必须要以LOCAL_PATH开头,使用这个变量来定位源文件

Application.mk文件:

Application.mk文件是Android NDK构建系统可选构建文件,他的目的是描述应用程序需要哪些模块,他也定义所有模块的通用变量

APP_STL := c++_static 
APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti 
APP_ABI := armeabi-v7a

APP_STL:默认情况下NDK构建系统使用的最小的STL运行库

APP_GNUSTL_FORCE_CPP_FEATURES :该变量表明所有模块都依赖具体的C++特性

APP_ABI:默认情况下,NDK构建你系统为armeabi ABI生成二进制文件

使用Android studio创建NDK项目

使用默认的Cmake编译:

  • 直接运行即可

使用ndk-build编译:

  • 这会用到我们刚才讲述的两个文件

  1. 首先在JNI目录下创建 Android.mk和Application.mk

Android.mk:
LOCAL_PATH := $(call my-dir) 
include $(CLEAR_VARS) 
LOCAL_MODULE:= native-lib 
LOCAL_SRC_FILES := native-lib.cpp 
LOCAL_LDLIBS := -fpic -fPIE -pie 
include $(BUILD_SHARED_LIBRARY)

Application.mk:
APP_STL := c++_static 
APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti 
APP_ABI := armeabi-v7a

2.修改app下的build.gradle文件:

externalNativeBuild {
//            cmake {
//                cppFlags ""
//            }
      ndk { 
           moduleName "native-lib"  
           abiFilters "armeabi-v7a" 
      }
}




externalNativeBuild {
//        cmake {
//            path "src/main/cpp/CMakeLists.txt"
//            version "3.10.2"
//        }
        ndkBuild {
            path "src/main/jni/Android.mk"  
        }
    }

3.编译执行即可

Java调用C方法:

首先在MainActivity中可以看到一个public native String stringFromJNI();方法,该方法是MainActivity.java 关联 so 库中方法, 它会默认去查找一个以Java包名+方法名的方法 就会去查找Java_com_wjx_android_ndksummary_MainActivity_stringFromJNI方法,而这个方法我们去native-lib.cpp文件中可以看到

C调用Java方法:

首先在MainActivity中声明以下方法:

String a = "w";
String b = "j";
String c = "x";
public String addStr(String a, String b, String c){
    return a + b + c;
}
public native String myAddStringFrom();

在JNI中声明:

/*
* Class:     com_wjx_android_ndksummary_MainActivity
* Method:    myAddStringFrom
* Signature: ()Ljava/lang/String;
*/

JNIEXPORT jstring JNICALL Java_com_wjx_android_ndksummary_MainActivity_myAddStringFrom
  (JNIEnv *, jobject);

在native-lib中加入:


extern "C"
JNIEXPORT jstring JNICALL
Java_com_wjx_android_ndksummary_MainActivity_myAddStringFrom(JNIEnv *env, jobject instance) {


    // TODO
    jclass clazz = (env)->GetObjectClass(instance);
    //获取java中a字段的Id
    jfieldID s_a_id= (env)->GetFieldID(clazz, "a", "java/lang/String");
    //获取a字段对应的值
    jobject s_a = (env)->GetObjectField(instance, s_a_id);
    //获取java中b字段的Id
    jfieldID s_b_id= (env)->GetFieldID(clazz, "b", "java/lang/String");
    //获取b字段对应的值
    jobject s_b = (env)->GetObjectField(instance, s_b_id);
     //获取java中c字段的Id
    jfieldID s_c_id= (env)->GetFieldID(clazz, "c", "java/lang/String");
    //获取c字段对应的值
    jobject s_c = (env)->GetObjectField(instance, s_c_id);
    //获取java中字符串相加的方法的ID, 后面的部分为参数的个数和返回类型
    jmethodID jmethodID1 = (env)->GetMethodID(clazz, "addStr",
                                              "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");

    //将返回结果接受并进行强制转换
    jstring result = static_cast<jstring>((env)->CallObjectMethod(instance, jmethodID1, s_a, s_b, s_c));
    return result;
}

 如果你对音视频开发感兴趣,觉得文章对您有帮助,别忘了点赞、收藏哦!或者对本文的一些阐述有自己的看法,有任何问题,欢迎在下方评论区讨论!

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值