目录
[一、先搞懂两个核心概念:JNI 和 NDK 到底是啥?](#一、先搞懂两个核心概念:JNI 和 NDK 到底是啥?)
[1. JNI:Java 和 C/C++ 的专属同声传译](#1. JNI:Java 和 C/C++ 的专属同声传译)
[2. NDK:安卓给翻译官配的全套工具包](#2. NDK:安卓给翻译官配的全套工具包)
[3. 两者的核心区别与联系](#3. 两者的核心区别与联系)
[二、为什么在 RK3576 上,JNI/NDK 是绕不开的坎?](#二、为什么在 RK3576 上,JNI/NDK 是绕不开的坎?)
[1. 底层硬件控制的唯一合法入口](#1. 底层硬件控制的唯一合法入口)
[2. 瑞芯微官方 SDK 的核心能力,全靠 JNI 调用](#2. 瑞芯微官方 SDK 的核心能力,全靠 JNI 调用)
[3. 嵌入式场景的极致性能需求](#3. 嵌入式场景的极致性能需求)
[4. 成熟开源库的无缝移植](#4. 成熟开源库的无缝移植)
[三、一张图讲透:RK3576 安卓开发的完整分层架构](#三、一张图讲透:RK3576 安卓开发的完整分层架构)
[1. 应用层(Application)](#1. 应用层(Application))
[2. 框架层(Android Framework)](#2. 框架层(Android Framework))
[3. ★ JNI 层(核心桥梁)](#3. ★ JNI 层(核心桥梁))
[4. 原生层(Native Layer)](#4. 原生层(Native Layer))
[5. 内核驱动层(Linux Kernel Driver)](#5. 内核驱动层(Linux Kernel Driver))
[6. 硬件层(Hardware)](#6. 硬件层(Hardware))
[五、新手必看:第一章就避开 90% 的人踩的坑](#五、新手必看:第一章就避开 90% 的人踩的坑)
[坑 1:上来就啃官方《JNI 规范》文档,直接劝退](#坑 1:上来就啃官方《JNI 规范》文档,直接劝退)
[坑 2:把 JNI 和 NDK 搞混,越学越乱](#坑 2:把 JNI 和 NDK 搞混,越学越乱)
[坑 3:好高骛远,上来就搞复杂开发](#坑 3:好高骛远,上来就搞复杂开发)
[本章总结 + 下章预告](#本章总结 + 下章预告)
前言
哈喽各位刚入坑瑞芯微 RK3576 安卓底层开发的兄弟们,我是你们的黒漂技术佬!
最近后台被兄弟们的私信炸穿了:"佬哥,我刚拿到 RK3576 开发板,上层写安卓 APP 溜得飞起,一碰到要控 GPIO、读 I2C、调官方的 RGA/NPU 库,直接两眼一抹黑 ------ 官方给的全是 C/C++ 代码,Java 根本调不动啊!"
懂了懂了!这几乎是所有嵌入式安卓新手的第一道坎。咱们做 RK3576 开发,核心就是玩硬件、榨干芯片性能,而JNI/NDK,就是安卓上层 Java 和底层硬件之间的唯一桥梁,不会这个,你连 RK3576 的核心能力的边都碰不到。
这个系列,佬哥我从零开始,保姆级带你从 JNI 基础语法,一路干到 RK3576 的底层驱动实战,全是我踩了无数坑总结出来的干货,不忽悠、不跳步、新手友好。
今天第一章,咱们不敲代码,先把底层逻辑彻底搞懂 ------ 什么是 JNI/NDK?为什么在 RK3576 上它是绕不开的坎?安卓从 APP 到硬件的完整流程到底是什么样的?搞懂这些,你后面的学习会事半功倍,再也不会越学越懵。
一、先搞懂两个核心概念:JNI 和 NDK 到底是啥?
很多新手入门第一个坑,就是把 JNI 和 NDK 搞混,以为是一个东西,越学越乱。今天佬哥我用「大白话 + 类比 + 专业定义」,给你彻底讲透,保证你一遍记住。
1. JNI:Java 和 C/C++ 的专属同声传译
【大白话翻译】JNI 全称Java Native Interface ,说白了就是Java 和 C/C++ 之间的专职同声传译员。
咱们都知道,安卓 APP 默认是用 Java/Kotlin 写的,咱们叫它 "Java 世界";但底层的驱动、硬件控制、高性能算法,全是 C/C++ 写的,咱们叫它 "原生世界"。Java 只会说 "中文",C/C++ 只会说 "英文",两边谁也听不懂谁,怎么办?
JNI 就是这个翻译官:Java 说一句 "我要把 GPIO3_A5 置成高电平,点亮 LED",JNI 把这句话翻译成 C/C++ 能懂的指令,传给底层;底层 C/C++ 读完传感器的温度数据,JNI 再把它翻译成 Java 能懂的格式,传回上层 APP,显示到屏幕上。
【专业定义】JNI 是 Java 官方定义的一套本地编程接口规范,它允许运行在 JVM(Java 虚拟机)中的 Java 代码,与用 C/C++ 等其他编程语言编写的本地代码,进行双向交互调用。
划重点:JNI 是一套通用规范,和安卓没有强绑定,纯 Java 后端开发也能用 JNI 调用 C/C++ 代码,只是咱们安卓开发用得最多。
2. NDK:安卓给翻译官配的全套工具包
【大白话翻译】NDK 全称Native Development Kit ,是安卓官方给咱们提供的C/C++ 开发工具包,也就是给上面那个同声传译员配的全套装备:专业术语词典、语法手册、交叉编译工具、调试器等等。
没有 NDK,你就算懂 JNI 的翻译规则,也没法在安卓里写、编译、调试 C/C++ 代码,更没法生成安卓系统能识别的.so动态库文件。
【专业定义】NDK 是安卓 SDK 的配套工具集,它能让开发者在安卓应用中使用 C/C++ 编写本地代码,将编译后的本地库打包到 APK 中,同时提供了针对 arm 架构的交叉编译、 native 代码调试、安卓系统平台库适配等全套能力。
3. 两者的核心区别与联系
再给大家一句话总结,再也不会搞混:
- JNI 是交互规则(交通规则),定义了 Java 和 C/C++ 怎么沟通、数据怎么转换;
- NDK 是实现工具(汽车),是安卓平台专门用来实现 JNI 规则、开发本地代码的工具包;
- 你要在安卓里做 JNI 开发,必须用 NDK,两者是配套使用的,但绝对不是一个东西。
二、为什么在 RK3576 上,JNI/NDK 是绕不开的坎?
很多兄弟会问:"我写普通安卓 APP,纯 Java 就够了,为啥非要学这个 JNI/NDK?"
那我告诉你,在瑞芯微 RK3576 的嵌入式安卓开发场景里,JNI/NDK 就是你吃饭的筷子,没有它,你连硬件的边都碰不到。核心原因有 4 个,全是咱们 RK3576 开发天天要碰的硬需求:
1. 底层硬件控制的唯一合法入口
RK3576 是工业级 SoC,咱们做嵌入式开发,核心就是操控硬件:GPIO 点灯、I2C 读温湿度传感器、SPI 驱动屏幕、PWM 调电机转速。
但这些硬件操作,安卓 Java 框架层根本没有开放直接的 API------ 毕竟安卓原生是给手机做的,手机厂商不可能让普通 APP 随便操控底层硬件。那怎么办?
唯一的路径,就是通过 JNI 调用 C/C++ 代码,去操作 Linux 内核驱动留下的/dev/设备节点,这是安卓应用层控制底层硬件的唯一合法方式。不会 JNI,你连个灯都点不亮。
2. 瑞芯微官方 SDK 的核心能力,全靠 JNI 调用
咱们拿到 RK3576 的官方 SDK,打开一看就懂了:芯片的核心能力,全是用 C/C++ 封装好的.so动态库。比如 2D 硬件加速的librga.so、NPU 推理的librknn_api.so、视频编解码的librockchip_mpp.so、摄像头驱动的librkcam.so,全是原生库。
这些库是瑞芯微官方针对 RK3576 的架构深度优化过的,性能拉满,你总不能自己用 Java 重写一遍吧?不会 JNI,这些官方给的核心能力,你一个都用不了,等于白瞎了 RK3576 的芯片性能。
3. 嵌入式场景的极致性能需求
RK3576 虽然是 6 核 A55+1 核 G52 的强性能 SoC,但咱们做嵌入式安卓,大多是工业场景、智能终端场景,对性能和延迟抠得极严。
比如实时图像处理、AI 推理、视频流解析,同样的逻辑,C/C++ 的执行效率比 Java 高 5-10 倍,内存占用也低得多。用 JNI 把核心运算逻辑放到原生层执行,才能把 RK3576 的性能彻底榨干,这是纯 Java 代码根本做不到的。
4. 成熟开源库的无缝移植
嵌入式开发里,很多经过十几年迭代的成熟开源工具库,全是 C/C++ 写的:比如图像处理的 OpenCV、音视频处理的 FFmpeg、网络通信的 libcurl。
用 NDK 可以直接把这些库交叉编译成 RK3576 的arm64-v8a架构能用的库,再通过 JNI 调用,不用自己用 Java 重造轮子,能节省 90% 的开发时间。
三、一张图讲透:RK3576 安卓开发的完整分层架构
很多新手入门就懵,核心原因就是没有建立整体的架构认知 ------ 不知道自己写的每一行代码,在整个安卓系统里处于什么位置,和硬件是怎么关联起来的。
今天佬哥我用一张分层架构图,给你把 RK3576 安卓开发的完整流程讲透,从上到下,从用户点击屏幕,到硬件做出响应,每一步都拆得明明白白。
plaintext
┌─────────────────────────────────────────────────┐
│ 应用层(Application) │ ← 咱们写的安卓APK,Java/Kotlin代码
├─────────────────────────────────────────────────┤
│ 框架层(Android Framework) │ ← 安卓系统Java API,Activity/Service等
├─────────────────────────────────────────────────┤
│ ★ JNI层(Java Native Interface)★ │ ← 核心桥梁,咱们系列的主角
├─────────────────────────────────────────────────┤
│ 原生层(Native Layer) │ ← C/C++代码,官方库、硬件控制逻辑
├─────────────────────────────────────────────────┤
│ 内核驱动层(Linux Kernel Driver) │ ← Linux内核驱动,/dev/设备节点
├─────────────────────────────────────────────────┤
│ 硬件层(Hardware) │ ← RK3576 SoC + 外设(LED/传感器/摄像头)
└─────────────────────────────────────────────────┘
接下来,咱们一层一层拆解,每一层是干嘛的、咱们要写什么代码,同时给大家用「智能工厂」做类比,保证你一遍就记住。
1. 应用层(Application)
【核心作用】用户直接交互的界面,也就是咱们写的安卓 APK。比如点灯的按钮、温湿度数据显示的 Activity、摄像头画面预览的界面,全在这一层。【咱们要做的】写 Java/Kotlin 代码,实现 UI 界面、业务逻辑,定义native方法,调用 JNI 层的接口。【工厂类比】工厂老板,只提需求:"我要按下按钮灯就亮,温度超过 30 度风扇就转",不管具体怎么实现。
2. 框架层(Android Framework)
【核心作用】安卓系统自带的 Java API 集合,咱们写 APP 天天用的 Activity、View、Button、系统服务,全是这一层提供的。它封装了安卓系统的所有基础能力,不用咱们直接和系统内核打交道。【咱们要做的】用官方提供的 API 写界面、处理用户交互,新手阶段不用修改这一层的代码。【工厂类比】总经理,把老板的需求拆解成可执行的任务,协调各个部门的资源。
3. ★ JNI 层(核心桥梁)
【核心作用】整个架构的绝对核心!Java 世界和 C/C++ 世界的唯一桥梁,也是咱们这个系列的主角。它负责把 Java 层的方法调用,翻译成 C/C++ 层能执行的指令;同时把 C/C++ 层的硬件数据、运算结果,转换成 Java 层能识别的格式,传回上层。【咱们要做的】写 JNI 接口函数,实现 Java 和 C/C++ 的双向交互,处理数据类型转换、内存管理、异常处理。【工厂类比】翻译兼部门经理,把老板的中文需求,翻译成车间能懂的英文指令,同时把车间的执行结果,翻译成中文汇报给老板。
4. 原生层(Native Layer)
【核心作用】C/C++ 代码的大本营。包括咱们自己写的 GPIO/I2C 硬件控制逻辑、瑞芯微官方提供的.so原生库、安卓系统自带的libc.so/liblog.so等基础库。这一层直接和内核驱动打交道,所有的硬件操作、高性能运算,全在这里执行。【咱们要做的】写 C/C++ 代码,实现硬件控制逻辑、调用官方原生库、处理运算逻辑,给 JNI 层提供可调用的函数。【工厂类比】车间主任,带着工人直接在生产线上干活,执行具体操作,直接对接生产设备。
5. 内核驱动层(Linux Kernel Driver)
【核心作用】RK3576 的安卓系统是基于 Linux 内核的,这一层就是 Linux 内核里的各种驱动程序:GPIO 驱动、I2C 驱动、SPI 驱动、RGA 驱动、NPU 驱动等等。驱动程序会给上层留一个「设备节点」,一般在/dev/目录下,比如/dev/gpiochip0、/dev/i2c-2,上层的原生代码就是通过操作这个设备节点,来控制硬件的。【咱们要做的】新手阶段不用自己写驱动,直接用 RK3576 SDK 里官方已经适配好的驱动,操作设备节点就行;进阶阶段可以自己修改、编写驱动。【工厂类比】生产设备的控制程序,直接控制机器运转,给车间主任提供操作机器的接口。
6. 硬件层(Hardware)
【核心作用】最底层的物理硬件,包括 RK3576 SoC 芯片本身,还有咱们外接的 LED 灯、温湿度传感器、摄像头、屏幕、电机等等外设,最终所有的指令,都会落到这一层,实现具体的硬件动作。【咱们要做的】根据原理图,把外设接到 RK3576 开发板的对应引脚上,给外设供电,保证硬件能正常工作。【工厂类比】生产线上的机器设备,最终干活的实体。
完整流程跑通示例
到这里,整个链路就彻底通了,咱们用「点亮 LED」举个例子,看每一步是怎么流转的:
- 用户点击应用层的「点亮 LED」按钮
- 框架层处理点击事件,调用 Java 代码里定义的
native void ledOn()方法 - JNI 层接收到调用,把 Java 的方法指令,翻译成 C/C++ 能执行的函数
- 原生层执行 C/C++ 代码,操作
/dev/gpiochip0设备节点,发送 GPIO 电平设置指令 - 内核驱动层接收到指令,配置 GPIO 寄存器,把对应引脚置为高电平
- 硬件层的 LED 灯接收到高电平,成功点亮
反过来,传感器数据读取也是一样的流程,只是方向反过来。搞懂了这个架构,你就知道咱们每一步要写什么代码、在哪个位置写、起什么作用,再也不会两眼一抹黑了。
四、新手前置认知:学这个系列需要啥基础?
很多兄弟看到这里会慌:"佬哥,我只会写简单的安卓 APP,C/C++ 只会个 HelloWorld,能学吗?"
放心,佬哥这个系列,就是纯纯的保姆级新手教程,门槛给你降到最低。
【必备基础(必须会)】
- 会写基础的安卓 Java 代码,知道 Activity 是什么,怎么写按钮的点击事件,能正常编译运行一个简单的 APK。
- 知道最基础的 Linux 命令,比如
cd、ls、cat,能正常用 adb 连接开发板。
【加分基础(不会也没关系,佬哥会讲)】
- 懂一点点 C/C++ 基础语法,知道变量、函数、指针是什么。
- 懂一点点 Linux 驱动的基础概念。
【硬件要求】
- 最好有一块 RK3576 开发板(比如野火、正点原子、瑞芯微官方 EVB 板),后面的硬件实战必须用。
- 没有开发板也没关系,前 3 章的基础内容,用安卓模拟器就能跑通,先把基础打牢,再买开发板也不迟。
【学习忠告】
技术这东西,看 100 遍不如自己跑一遍。每一章看完,一定要亲手跟着敲代码、跑 demo,收藏吃灰是学不会的,动手才是王道。
五、新手必看:第一章就避开 90% 的人踩的坑
佬哥我搞了这么多年安卓底层开发,见过太多新手刚入门就踩坑,直接劝退。今天第一章,就给大家把最常见的 3 个坑堵死,让你少走半年弯路。
坑 1:上来就啃官方《JNI 规范》文档,直接劝退
很多新手听别人说 "学 JNI 要看官方文档",直接去下了几百页的全英文《Java Native Interface Specification》,看了 3 页直接放弃。【正确姿势】官方文档是字典,不是入门教材,没人拿着字典学说话。先跟着系列搞懂整体流程,跑通 HelloWorld,建立整体认知之后,再回头看官方文档补细节。
坑 2:把 JNI 和 NDK 搞混,越学越乱
很多新手张口就来 "我学 JNI 开发"、"我学 NDK 开发",把两者当成一个东西,越学越懵。【正确认知】再强调一遍:JNI 是交互规则,NDK 是安卓的开发工具包,两者是配套的,但绝对不是一个东西,别再搞混了。
坑 3:好高骛远,上来就搞复杂开发
很多新手刚跑通一个 HelloWorld,就想直接搞 RK3576 的 NPU 推理、视频编解码,结果连 JNI 的基本数据类型转换都没搞懂,越搞越崩,直接放弃。【正确姿势】跟着系列的节奏,一步一步来:先搞懂基础概念 → 搭好环境 → 跑通 HelloWorld → 搞懂数据类型和方法调用 → 跑通 GPIO 点灯 → 再搞复杂的 RGA、NPU 开发。饭要一口一口吃,路要一步一步走,技术没有捷径。
本章总结 + 下章预告
【本章总结】
今天这一章,咱们给整个系列开了个好头,核心就 3 件事:
- 彻底搞懂了 JNI 和 NDK 的核心概念与区别:JNI 是 Java 和 C/C++ 的交互规则,NDK 是安卓的 C/C++ 开发工具包。
- 明确了在 RK3576 安卓开发中,JNI/NDK 的核心价值:硬件控制、官方库调用、性能优化、开源库移植,全靠它。
- 建立了 RK3576 安卓开发的完整架构认知,搞懂了从 APP 到硬件的完整流转链路,知道了 JNI 在其中的核心桥梁作用。
【下章预告】
下一章,佬哥给你们带来保姆级的环境搭建全教程:JDK 安装、Android Studio 安装配置、NDK 版本选择与环境配置、RK3576 官方 SDK 的目录解析,一步都不跳,每一步都有详细说明,保证你跟着就能搭好环境,跑通你的第一个 JNI 程序!
我是黒漂技术佬,专注给小白搞懂 RK3576 安卓底层、JNI/NDK、嵌入式开发的保姆级教程,跟着我,保证你不迷路、不踩坑!
兄弟们,看完本章有收获的,麻烦给佬哥点个赞、收个藏、关个注,有啥问题、想看啥内容,评论区直接留言,佬哥我挨个回复!