Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块

一直想写一份技术文档,但由于自感能力有限而无从下笔,最近做了个关于Android平台下实现与C语言的通讯来操作蓝牙模块的项目,中间碰到了许多问题,也在网上查了许多资料,在完成主要功能后,也有一些人在网上问我一些问题,这里写下这篇文档算是一个阶段性的总结。如果反响好,后续将会发上Android Stub与新版Android HAL的学习文档。

由于蓝牙模块是串口通讯机制,使用C语言来访问,而Android的应用层采用Java,无法直接操作硬件。故使用JNI的技术实现主要功能。Android的JNI应该属于Android HAL的一部分,由于Android的HAL机制目前还没完全摸索透,所以这里的程序架构算是老版本的HAL机制。程序架构如下图。

一、 什么是JNI?

JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。(以上内容摘自百度百科)

二、 如何使用JNI?

1、在使用JNI之前,你要确保你的电脑中安装以下软件环境:

Android SDK :版本与你硬件测试环境版本相同,在Google的Android官网下载

Android NDK :用于编译C文件为.so的共享库,如果你是在Linux下进行开发而又具有Android的完全SDK,则不需要

Cygwin :用于编译C文件

Android 开发环境 :android开发环境的配置网上一大堆,这里不再赘述

2、程序中由于只用到Java调C,而不需要C调Java,所以在应用层调C的函数很简单,只需要在一个方法前加入native关键字(native的方法不能有方法体),然后将编译的共享库导入即可。

如下:

public class BluetoothJNI {

static{

System.loadLibrary("jni");

}

public native static int bluetoothOn(String strAT);

public native static void bluetoothOff(String strAT);

public native static String readSerial();

public native static void write(String strAT);

}

 

3、Eclipse在保存工程后,会自动把Java文件编译为class文件,我们使用javah命令把class文件编译成C头文件。如下:

 

执行此命令后将会在工程的bin目录下生成一个.h的C头文件。头文件中会生成对应Java native方法的函数声明。新建一个与头文件同名的C文件并实现所有函数。

 

4、由于Android的底层是基于Linux内核,所以一些Windows下的系统函数不可用,Linux下的串口通讯文章网上有很多,此处代码繁多,就不贴出来了。,我们在C文件中引入jni.h与刚生成的头文件以确保JNI能调用。注意:整个程序的核心部分便是在此处,C语言与蓝牙模块的串口通讯处,我在此处碰到的问题也是最多的。

三、编译C文件

1、在Android-ndk-r5b\samples\下新建目录Bluetooth\jni,将C文件与头文件复制过来,新建Makefile。如下:

LOCAL_PATH := $(call my-dir)

 

include $(CLEAR_VARS)

 

LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)

LOCAL_LDLIBS := -lm -llog

 

LOCAL_MODULE    := jni

LOCAL_SRC_FILES := com_android_semisky_bluetooth_util_BluetoothJNI.c

 

include $(BUILD_SHARED_LIBRARY)

2、打开Cygwin bash shell,进入Bluetooth目录,执行ndk-build进行编译。

 

3、将libs/armeabi下生成的libjni.so文件拷入到Android工程的libs/armeabi目录下。安装apk到开发板,执行程序。

四、可能出现的问题

1、串口读写权限的问题

网上的方法是在Java中获取su账号来改权限或者在init.rc中添加命令来修改权限最后编译成img烧录进开发板,而这两种方法我都没成功,最后没办法在dos下执行shell命令来修改

2、C文件的串口读写问题

我不知道是我的程序有问题还是蓝牙模块的问题,在蓝牙模块返回数据稍大的时候,会出现数据有时返回有时不返回的情况。

3、乱码问题

蓝牙返回的数据时而出现乱码,未解决。

4、串口号的问题

如果你open的时候返回的fd小于1,确保你的开发板串口号是否正确,协议是否正确,权限是否修改。

5、最大大大的问题

读取串口代码段的算法问题,优化问题,不然数据会返回不正常。

时间: 2024-12-12 14:31:46

Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块的相关文章

怎么用C#语言实现串口通讯

////bool XmlTextReader.Read(): 读取流中下一个节点,当读完最后一个节点再次调用该方法该方法返回false//XmlNodeType XmlTextReader.NodeType: 该属性返回当前节点的类型// XmlNodeType.Element 元素节点// XmlNodeType.EndElement 结尾元素节点// XmlNodeType.XmlDeclaration 文档的第一个节点// XmlNodeType.Text 文本节点//bool XmlTe

Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型

Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面也讲了许多,也提到了多级指针的概念,那具体我们怎么去操作呢 #include <stdio.h> #include <stdlib.h> main(){ int i = 3; //一级 int* p = &i; //二级,保存一级指针 int** w = &p; //三

Android For JNI(一)——JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序,使用C启动JAVA程序

Android For JNI(一)--JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序 当你的Android之旅一步步的深入的时候,你其实会发现,很多东西都必须去和framework或者底层打交道,还有就是混合编程之类的,以及新语言,新特性,各种牛人研究的黑科技,应接不暇,技术更新迭代太快了,我们要赶紧加快步伐了,今天就开始来入坑了--JNI,这个坑是必须要进的,啥也不说了,老司机,带我! 一.什么是JNI? Java Native Interface(java本地接口)

Android For JNI(六)——交叉编译,NDK概述以及文件结构,编写自己的第一个JNI工程

Android For JNI(六)--交叉编译,NDK概述以及文件结构,编写自己的第一个JNI工程 终于回到我们的 android了,我们先要配置这个NDK的环境,但是之前,我们还要了解一下基本的术语 一.交叉编译 在一个平台下编译出另一个平台可以执行的二进制程序 CPU平台:ARM X86 MIPS(指令集) 系统平台:windows linux mac 原理:模拟另一个平台的特性去编译程序 源代码-->预编译-->编译-->链接-->可执行程序 工具链:一个工具使用自动调用下

jni封装-Android Studio JNI封装问题

问题描述 Android Studio JNI封装问题 大家好,在下有一问题请教: 别人给了一个C语言编译的动态库和头文件(libxxx.so,xxx.h),我想在Android Studio中NDK开发时用JNI封装这个库,然后再生成一个libyyy.so给Android Java调用.我已经在linux下用yyy.c和Makefile实现了我的想法(即通过libxxx.so经过JNI封装生成libyyy.so给Android Java调用),我想为了方便,能否直接在Android Studi

Android在JNI中使用ByteBuffer的方法

  Android在JNI中使用ByteBuffer的方法 本文实例讲述了Android在JNI中使用ByteBuffer的方法.分享给大家供大家参考.具体如下: 一.ByteBuffer 定义 在NIO中,数据的读写操作始终是与缓冲区相关联的(读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区) 缓冲区是定长的,基本上它只是一个列表,它的所有元素都是基本数据类型.ByteBuffer是最常用的缓冲区,它提供了读写其他数据类型的方法,且信道的读写方

Android For JNI(四)——C的数组,指针长度,堆内存和栈内存,malloc,学生管理系统

Android For JNI(四)--C的数组,指针长度,堆内存和栈内存,malloc,学生管理系统 好几天每写JNI了,现在任务也越来越重了,工作的强度有点高,还有好几个系列的博客要等着更新,几本书还嗷嗷待哺的等着我去看,github上的两个散漫的开源,基础入门的视频也在录制,还要学习新的知识, 都是一种挑战,不知道为何,最近懒散了,看来还得再加把劲,今天我们继续延伸一下C的一些小知识 一.数组 C的数组和JAVA也是类似的,我们写一段小程序 #include <stdio.h> #inc

Android通过JNI调用驱动程序(完全解析实例)

  [置顶] Android通过JNI调用驱动程序(完全解析实例)            要达到的目的:android系统中,用JAVA写界面程序,调用jni中间库提供的接口,去操作某个驱动节点,实现read,writer ioctl等操作!这对底层驱动开发人员是很重要的一个调试通道,也是android 系统下提供一些特殊功能接口的方法! 本文前提:我们假设已经写了一个驱动程序,它是控制LED的亮灭的,并且创建了一个节点:/dev/vib,也就是通过open这个vib节点,可以read/writ

Android studio JNI如何混合编译C和C++啊求大神告知

问题描述 Android studio JNI如何混合编译C和C++啊求大神告知 最近小弟在学习Android studio的开发(毕设)之前完全没接触过Android这边有一个别的大神写的程序包但是小弟无法完整导入最新的Android studio,导入后只有Java和Android部分.C和C++部分都不见了.请问如何完整导入并创造完整的关联呢?