Jorgen's blog Jorgen's blog
首页
  • 平台架构
  • 混合式开发记录
  • 推送服务
  • 数据分析
  • 实时调度
  • 架构思想

    • 分布式
  • 编程框架工具

    • 编程语言
    • 框架
    • 开发工具
  • 数据存储与处理

    • 数据库
    • 大数据
  • 消息、缓存与搜索

    • 消息队列
    • 搜索与日志分析
  • 前端与跨端开发

    • 前端技术
    • Android
  • 系统与运维

    • 操作系统
    • 容器化与 DevOps
  • 物联网与安全

    • 通信协议
    • 安全
    • 云平台
收藏
  • 关于我
  • 终身学习
  • 关于时间的感悟
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

jorgen

Love it, make mistakes, learn, keep grinding.
首页
  • 平台架构
  • 混合式开发记录
  • 推送服务
  • 数据分析
  • 实时调度
  • 架构思想

    • 分布式
  • 编程框架工具

    • 编程语言
    • 框架
    • 开发工具
  • 数据存储与处理

    • 数据库
    • 大数据
  • 消息、缓存与搜索

    • 消息队列
    • 搜索与日志分析
  • 前端与跨端开发

    • 前端技术
    • Android
  • 系统与运维

    • 操作系统
    • 容器化与 DevOps
  • 物联网与安全

    • 通信协议
    • 安全
    • 云平台
收藏
  • 关于我
  • 终身学习
  • 关于时间的感悟
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 平台架构
  • 技术选型
  • 开发脚手架
  • UI规范
  • 开发规范
  • 代码分支管理模型
  • 需求分析与管理
  • 权限设计
  • 树形组织设计
  • 协议设计
  • 指令交互
  • OTA
  • 规则引擎
  • 数据流转
  • 报告生成与导出
  • 监控设备接入
  • 时序数据库
  • 平台监控
  • 云⛈
  • 接口设计
  • 安全传输
  • CI&CD
  • 缓存
  • 消息处理引擎
  • 性能调优🔥
  • 线上事故🔥
  • 混合式开发记录
    • 🏁 Capacitor 使用 JNI 的方式集成安卓底层 SDK
      • 🛠️ 实施过程
      • 🔥敲黑板
      • 🚀 拓展
      • 🔥 遇到的难题 & 解决办法
    • 🎯 理解与感悟
    • 🎭 结尾:送自己一句话
  • 推送服务
  • 机器人通信协议
  • 数据分析
  • flink模板工程
  • 实时调度
  • 机器人模块化设计
  • STM32入门
  • 开发日志
Jorgen
2024-08-08
目录

混合式开发记录

这次的 JNI 方案,算是一次挺有趣的探索,折腾了一番,总算把 Capacitor 和安卓底层打通了。希望这篇文章能帮到同样在踩坑的朋友们!🚀

# 🏁 Capacitor 使用 JNI 的方式集成安卓底层 SDK

在 Capacitor 这类跨平台框架中,如何与安卓底层 SDK 交互?这是我在开发过程中遇到的一个现实问题。

这次的需求是:让地面端程序能够获取遥控器的遥感按键数据。刚开始,我尝试了各种方式,比如在网上查到的 joystick 方式,兴冲冲地试了一番,结果——行不通 😑。

遥控器

后来,我反编译了遥控器的 APK(Jdax (opens new window) 大法好!),发现它是通过 UART 串口 读取通道值的。好,那就走 UART!🔍 串口

研究了一下,发现 Google 以前的一个项目android-serialport-api (opens new window)可以作为参考,于是决定用 JNI + UART 来搞定这个问题。


# 🛠️ 实施过程

  1. JNI 层:实现 UART 读取

    • 使用 termios 配置串口参数
    • 通过 open()、read() 读取数据
    • 提供 JNI_OnLoad() 方法,供 Java 层调用
  2. Java 层:封装 JNI 调用

    • 通过 System.loadLibrary() 加载 so 库
    • 用 native 方法封装 C 层的 UART 读取逻辑
  3. Capacitor Plugin:桥接到前端

    • 在 Capacitor 中创建一个自定义插件
    • 通过 @PluginMethod 提供前端调用
    • 通过 bridge.getActivity() 获取上下文,调用 Java 层的 JNI 方法

# 🔥敲黑板

Android开发中使用.aar文件和.so库,以及JNI调用的相关知识点:

  1. .aar文件:

    • .aar文件是Android库项目的二进制分发格式。
    • 包含编译后的代码、资源文件、AndroidManifest.xml、ProGuard规则等。
    • 用于模块化代码和资源,便于复用和管理。
    • 可以通过Gradle依赖管理引入项目中。
  2. .so文件:

    • .so文件是动态链接库,包含C/C++编写的原生代码。
    • 用于性能提升、代码保护和复用现有库。
    • 需要根据不同CPU架构提供对应的.so文件。
  3. JNI(Java Native Interface):

    • JNI是Java代码和原生代码之间的桥梁。
    • 允许Java/Kotlin代码调用C/C++代码。
    • 需要在Java/Kotlin中声明native方法,并在C/C++中实现这些方法。
  4. 引入.aar文件:

    • 通过Gradle的dependencies块引入.aar文件。
    • 可以直接指定.aar文件的路径或使用Maven仓库。 aar文件
  5. 引入.so文件:

    • 将.so文件放入src/main/jniLibs/目录下对应的架构子目录中。
    • 配置build.gradle文件以确保.so文件被正确打包到APK中。 lib
  6. 打包.aar文件:

    • 通过Gradle构建系统打包.aar文件。
    • 配置build.gradle文件,使用com.android.library插件。
    • 构建完成后在build/outputs/aar/目录下找到.aar文件。
  7. 直接使用.so文件:

    • 将构建好的.so文件复制到新项目的jniLibs目录下。
  8. 实现JNI调用:

    • 在Java/Kotlin中声明native方法。
    • 在C/C++中实现native方法,使用JNI函数。
  9. 配置CMake或ndk-build:

    • 配置CMakeLists.txt或Android.mk文件以编译C/C++代码。
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
        serialport

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        src/main/jni/SerialPort.c)

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

target_link_libraries( # Specifies the target library.
        serialport

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  1. 调用Native方法:
    • 在Java/Kotlin代码中加载.so库并调用native方法。

# 🚀 拓展

明白了JNI对安卓底层调用的原理,再回头看 Capacitor 插件的实现,发现其实也是类似的思路。只不过 Capacitor 插件是通过 @PluginMethod 注解,将 Java 方法暴露给前端调用,而 JNI 是通过 native 关键字,将 C 方法暴露给 Java 调用。 后续FPV插件、RTK等插件的开发,也参考了这种思路,通过 JNI 调用安卓底层 SDK,实现更多功能。

# 🔥 遇到的难题 & 解决办法

问题 🤔 解决方案 ✅
串口权限受限,无法访问 UART 申请 android.permission.READ/WRITE_EXTERNAL_STORAGE,并运行 chmod 666 放开权限
读取的数据乱码 设置正确的 波特率,确保串口参数匹配
JNI 层内存泄漏 使用 RAII 处理资源,close() 及时释放文件描述符

# 🎯 理解与感悟

  1. 别盲目尝试,先搞清楚原理再动手!

    • joystick 方案就是个教训,得先弄明白遥控器的工作方式。
  2. 反编译有时候是个捷径!

    • Jdax 让我快速找到了正确的 UART 方案。
  3. Capacitor + JNI 是一个很好的组合

    • 既能保证跨平台开发的灵活性,又能调用安卓底层能力。

# 🎭 结尾:送自己一句话

“所有的困难,都是为了让你学会解决它。” 😆

#混合式开发#Capacitor
上次更新: 2025/03/09, 15:45:50
线上事故🔥
推送服务

← 线上事故🔥 推送服务→

最近更新
01
STM32入门
03-09
02
ADB调试
03-09
03
微信小程序学习记录
02-09
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Jorgen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式