- 浏览: 1313998 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (132)
- android Launcher (15)
- 收藏夹 (3)
- UI设计 (28)
- J2EE (2)
- android网络编程 (8)
- 项目经理是熬出来的 (8)
- Android图像处理 (5)
- 系统层开发 (12)
- 数据库 (2)
- 程序员是熬出来的 (2)
- Android技巧 (11)
- 地图相关 (2)
- Android底层 (9)
- Android疑难杂症 (4)
- 开发工具 (4)
- 知识梳理 (8)
- 源码阅读 (7)
- Media媒体库 (5)
- 调试技术 (3)
- Android蓝牙 (3)
- 动画特效 (5)
- jni (3)
- 串口通信 (1)
- Android优化 (3)
- 架构设计 (1)
- Android Test (1)
- 翻译系列 (0)
最新评论
-
我说123木头人雪雪:
...
Android截屏并对图片做高斯模糊处理 -
ysc123shift:
没有源码。
Android截屏并对图片做高斯模糊处理 -
我de专属doll:
你那个Jni库是自己编译的还是有现成的呢?
Android media媒体库分析之:分类别统计媒体文件大小 -
zhunanfengfeimeng:
想做项目经理?这些工具必须了解 -
ls0609:
一个带人脸识别的智能照相机demohttp://blog.cs ...
Android 调用相机,获取的图片太小
在Android串口通信:基本知识梳理(http://gqdy365.iteye.com/admin/blogs/2188846)的基础上,我结合我项目中使用串口的实例,进行总结;
Android使用jni直接进行串口设备的读写网上已经有开源项目了,本文是基于网上的开源项目在实际项目中的使用做的调整和优化;
Google串口开源项目见:https://code.google.com/p/android-serialport-api/
下面是我项目中的相关代码及介绍:
1、SerialPort.cpp
在编译时注意修改const char* kClassName = "com/jerome/serialport/SerialPort";为你Java层与jni对应得包名;
2、Android.mk
如果要修改生成so文件的名称,请修改LOCAL_MODULE := serial_port
3、SerialPort.java
4、SerialPortUtil.java
5、使用方法:
a、配置ndk开发环境,具体百度一下;
b、工程根目录下新建jni文件夹,将Android.mk和SerialPort.cpp放进去;
c、ndk中进入jni目录,编译生成so文件,默认so生成在libs/armeabi下;
d、新建com.jerom.serialport目录,将SerialPort和SerialPortUtil放进去;
f、在你要使用的地方初始化SerialPortUtil,实现回调接口OnDataReceiveListener即可接受数据;
总结:
1、串口发送实质就是向串口设备(类似于文件操作)写入字节流,串口读取也是一样;
2、主要jni与Java native得对应;
完成的jni部分已经都贴出来了,你要自己编译一下,生成SO文件才能用,其他代码都是我项目相关的代码,没办法分享;
SerialPortUtil.java,这个文件代码贴进去有错误,我主要是通过串口向gprs发送数据,有没有相关的代码啊
跟GPRS通信的没有现成的代码,不过jni串口通信这一块可以共用
完成的jni部分已经都贴出来了,你要自己编译一下,生成SO文件才能用,其他代码都是我项目相关的代码,没办法分享;
SerialPortUtil.java,这个文件代码贴进去有错误,我主要是通过串口向gprs发送数据,有没有相关的代码啊
完成的jni部分已经都贴出来了,你要自己编译一下,生成SO文件才能用,其他代码都是我项目相关的代码,没办法分享;
Android使用jni直接进行串口设备的读写网上已经有开源项目了,本文是基于网上的开源项目在实际项目中的使用做的调整和优化;
Google串口开源项目见:https://code.google.com/p/android-serialport-api/
下面是我项目中的相关代码及介绍:
1、SerialPort.cpp
/* * Copyright 2009 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdlib.h> #include <stdio.h> #include <jni.h> #include <assert.h> #include <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <jni.h> #include "android/log.h" static const char *TAG = "serial_port"; #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args) #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args) #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args) static speed_t getBaudrate(jint baudrate) { switch (baudrate) { case 0: return B0; case 50: return B50; case 75: return B75; case 110: return B110; case 134: return B134; case 150: return B150; case 200: return B200; case 300: return B300; case 600: return B600; case 1200: return B1200; case 1800: return B1800; case 2400: return B2400; case 4800: return B4800; case 9600: return B9600; case 19200: return B19200; case 38400: return B38400; case 57600: return B57600; case 115200: return B115200; case 230400: return B230400; case 460800: return B460800; case 500000: return B500000; case 576000: return B576000; case 921600: return B921600; case 1000000: return B1000000; case 1152000: return B1152000; case 1500000: return B1500000; case 2000000: return B2000000; case 2500000: return B2500000; case 3000000: return B3000000; case 3500000: return B3500000; case 4000000: return B4000000; default: return -1; } } /* * Class: cedric_serial_SerialPort * Method: open * Signature: (Ljava/lang/String;)V */ JNIEXPORT jobject JNICALL native_open(JNIEnv *env, jobject thiz, jstring path,jint baudrate) { int fd; speed_t speed; jobject mFileDescriptor; LOGD("init native Check arguments"); /* Check arguments */ { speed = getBaudrate(baudrate); if (speed == -1) { /* TODO: throw an exception */ LOGE("Invalid baudrate"); return NULL; } } LOGD("init native Opening device!"); /* Opening device */ { jboolean iscopy; const char *path_utf = env->GetStringUTFChars(path, &iscopy); LOGD("Opening serial port %s", path_utf); // fd = open(path_utf, O_RDWR | O_DIRECT | O_SYNC); fd = open(path_utf, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); LOGD("open() fd = %d", fd); env->ReleaseStringUTFChars(path, path_utf); if (fd == -1) { /* Throw an exception */ LOGE("Cannot open port %d",baudrate); /* TODO: throw an exception */ return NULL; } } LOGD("init native Configure device!"); /* Configure device */ { struct termios cfg; if (tcgetattr(fd, &cfg)) { LOGE("Configure device tcgetattr() failed 1"); close(fd); return NULL; } cfmakeraw(&cfg); cfsetispeed(&cfg, speed); cfsetospeed(&cfg, speed); if (tcsetattr(fd, TCSANOW, &cfg)) { LOGE("Configure device tcsetattr() failed 2"); close(fd); /* TODO: throw an exception */ return NULL; } } /* Create a corresponding file descriptor */ { jclass cFileDescriptor = env->FindClass("java/io/FileDescriptor"); jmethodID iFileDescriptor = env->GetMethodID(cFileDescriptor,"<init>", "()V"); jfieldID descriptorID = env->GetFieldID(cFileDescriptor,"descriptor", "I"); mFileDescriptor = env->NewObject(cFileDescriptor,iFileDescriptor); env->SetIntField(mFileDescriptor, descriptorID, (jint) fd); } return mFileDescriptor; } /* * Class: cedric_serial_SerialPort * Method: close * Signature: ()V */ JNIEXPORT jint JNICALL native_close(JNIEnv * env, jobject thiz) { jclass SerialPortClass = env->GetObjectClass(thiz); jclass FileDescriptorClass = env->FindClass("java/io/FileDescriptor"); jfieldID mFdID = env->GetFieldID(SerialPortClass, "mFd", "Ljava/io/FileDescriptor;"); jfieldID descriptorID = env->GetFieldID(FileDescriptorClass, "descriptor", "I"); jobject mFd = env->GetObjectField(thiz, mFdID); jint descriptor = env->GetIntField(mFd, descriptorID); LOGD("close(fd = %d)", descriptor); close(descriptor); return 1; } static JNINativeMethod gMethods[] = { { "open", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;",(void*) native_open }, { "close", "()I",(void*) native_close }, }; /* * 为某一个类注册本地方法 */ static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return JNI_FALSE; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE; } /* * 为所有类注册本地方法 */ static int registerNatives(JNIEnv* env) { const char* kClassName = "com/jerome/serialport/SerialPort"; //指定要注册的类 return registerNativeMethods(env, kClassName, gMethods, sizeof(gMethods) / sizeof(gMethods[0])); } /* * System.loadLibrary("lib")时调用 * 如果成功返回JNI版本, 失败返回-1 */ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { return -1; } assert(env != NULL); if (!registerNatives(env)) { //注册 return -1; } //成功 result = JNI_VERSION_1_4; return result; }
在编译时注意修改const char* kClassName = "com/jerome/serialport/SerialPort";为你Java层与jni对应得包名;
2、Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) TARGET_PLATFORM := android-3 LOCAL_MODULE := serial_port LOCAL_SRC_FILES := SerialPort.cpp LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)
如果要修改生成so文件的名称,请修改LOCAL_MODULE := serial_port
3、SerialPort.java
package com.jerome.serialport; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class SerialPort { private static final String TAG = "SerialPort"; /* * Do not remove or rename the field mFd: it is used by native method close(); */ private FileDescriptor mFd; private FileInputStream mFileInputStream; private FileOutputStream mFileOutputStream; public SerialPort(File device, int baudrate) throws SecurityException, IOException { mFd = open(device.getAbsolutePath(), baudrate); if (mFd == null) { throw new IOException(); } mFileInputStream = new FileInputStream(mFd); mFileOutputStream = new FileOutputStream(mFd); } public InputStream getInputStream() { return mFileInputStream; } public OutputStream getOutputStream() { return mFileOutputStream; } private native FileDescriptor open(String path, int baudrate); public native int close(); static { System.loadLibrary("serial_port"); } }
4、SerialPortUtil.java
package com.jerome.serialport; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; /** * 串口操作类 * * @author Jerome * */ public class SerialPortUtil { private String TAG = SerialPortUtil.class.getSimpleName(); private SerialPort mSerialPort; private OutputStream mOutputStream; private InputStream mInputStream; private ReadThread mReadThread; private String path = "/dev/ttyMT1"; private int baudrate = 115200; private static SerialPortUtil portUtil; private OnDataReceiveListener onDataReceiveListener = null; private boolean isStop = false; public interface OnDataReceiveListener { public void onDataReceive(byte[] buffer, int size); } public void setOnDataReceiveListener( OnDataReceiveListener dataReceiveListener) { onDataReceiveListener = dataReceiveListener; } public static SerialPortUtil getInstance() { if (null == portUtil) { portUtil = new SerialPortUtil(); portUtil.onCreate(); } return portUtil; } /** * 初始化串口信息 */ public void onCreate() { try { mSerialPort = new SerialPort(new File(path), baudrate); mOutputStream = mSerialPort.getOutputStream(); mInputStream = mSerialPort.getInputStream(); mReadThread = new ReadThread(); isStop = false; mReadThread.start(); } catch (Exception e) { e.printStackTrace(); } initBle(); } /** * 发送指令到串口 * * @param cmd * @return */ public boolean sendCmds(String cmd) { boolean result = true; byte[] mBuffer = (cmd+"\r\n").getBytes(); //注意:我得项目中需要在每次发送后面加\r\n,大家根据项目项目做修改,也可以去掉,直接发送mBuffer try { if (mOutputStream != null) { mOutputStream.write(mBuffer); } else { result = false; } } catch (IOException e) { e.printStackTrace(); result = false; } return result; } public boolean sendBuffer(byte[] mBuffer) { boolean result = true; String tail = "\r\n"; byte[] tailBuffer = tail.getBytes(); byte[] mBufferTemp = new byte[mBuffer.length+tailBuffer.length]; System.arraycopy(mBuffer, 0, mBufferTemp, 0, mBuffer.length); System.arraycopy(tailBuffer, 0, mBufferTemp, mBuffer.length, tailBuffer.length); //注意:我得项目中需要在每次发送后面加\r\n,大家根据项目项目做修改,也可以去掉,直接发送mBuffer try { if (mOutputStream != null) { mOutputStream.write(mBufferTemp); } else { result = false; } } catch (IOException e) { e.printStackTrace(); result = false; } return result; } private class ReadThread extends Thread { @Override public void run() { super.run(); while (!isStop && !isInterrupted()) { int size; try { if (mInputStream == null) return; byte[] buffer = new byte[512]; size = mInputStream.read(buffer); if (size > 0) { if(MyLog.isDyeLevel()){ MyLog.log(TAG, MyLog.DYE_LOG_LEVEL, "length is:"+size+",data is:"+new String(buffer, 0, size)); } if (null != onDataReceiveListener) { onDataReceiveListener.onDataReceive(buffer, size); } } Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); return; } } } } /** * 关闭串口 */ public void closeSerialPort() { sendShellCommond1(); isStop = true; if (mReadThread != null) { mReadThread.interrupt(); } if (mSerialPort != null) { mSerialPort.close(); } } }
5、使用方法:
a、配置ndk开发环境,具体百度一下;
b、工程根目录下新建jni文件夹,将Android.mk和SerialPort.cpp放进去;
c、ndk中进入jni目录,编译生成so文件,默认so生成在libs/armeabi下;
d、新建com.jerom.serialport目录,将SerialPort和SerialPortUtil放进去;
f、在你要使用的地方初始化SerialPortUtil,实现回调接口OnDataReceiveListener即可接受数据;
总结:
1、串口发送实质就是向串口设备(类似于文件操作)写入字节流,串口读取也是一样;
2、主要jni与Java native得对应;
评论
8 楼
严健严健
2016-11-02
非常感谢!!!!!!!!!
7 楼
manlan123
2016-10-12
请问 sendBuffer sendCmds 里面传入的数据是什么样的啊? 能贴一下吗
6 楼
huangzongwu
2016-05-17
稍微改改就可以用在自己的项目,实在是太感谢了,csdn上看到的另一篇用HAL的根本没法编译
5 楼
gqdy365
2016-02-15
zyzyzy123 写道
gqdy365 写道
zyzyzy123 写道
学长你好,能否把这个工程提供给我一份,刚接触串口,急需,万分感谢啊
完成的jni部分已经都贴出来了,你要自己编译一下,生成SO文件才能用,其他代码都是我项目相关的代码,没办法分享;
SerialPortUtil.java,这个文件代码贴进去有错误,我主要是通过串口向gprs发送数据,有没有相关的代码啊
跟GPRS通信的没有现成的代码,不过jni串口通信这一块可以共用
4 楼
zyzyzy123
2015-12-18
gqdy365 写道
zyzyzy123 写道
学长你好,能否把这个工程提供给我一份,刚接触串口,急需,万分感谢啊
完成的jni部分已经都贴出来了,你要自己编译一下,生成SO文件才能用,其他代码都是我项目相关的代码,没办法分享;
SerialPortUtil.java,这个文件代码贴进去有错误,我主要是通过串口向gprs发送数据,有没有相关的代码啊
3 楼
gqdy365
2015-12-18
zyzyzy123 写道
学长你好,能否把这个工程提供给我一份,刚接触串口,急需,万分感谢啊
完成的jni部分已经都贴出来了,你要自己编译一下,生成SO文件才能用,其他代码都是我项目相关的代码,没办法分享;
2 楼
zyzyzy123
2015-12-17
学长你好,能否把这个工程提供给我一份,刚接触串口,急需,万分感谢啊
1 楼
YY793924556
2015-11-23
能否提供一下源码啊 谢谢
发表评论
-
(转)为什么第三方应用能早于System的app启动
2015-06-18 10:52 2130Android应用的启动顺序网上有一大堆资料可以查阅了,这里就 ... -
Android led灯实现大致流程
2015-05-11 18:07 17395led灯的控制在http://gqdy365.iteye.co ... -
Android应用程序获取系统权限
2015-04-29 18:27 1020引用 如何使Android应用程序获取系统权限 ... -
Android jni系统变量、函数、接口定义汇总
2015-03-09 11:29 8351在做Android jni开发时,jni为我们提供了哪些函数、 ... -
Android串口通信:基本知识梳理
2015-03-05 09:23 5417在Android开发中,如果涉及到与外设硬件、新设备的通信,往 ... -
Android media媒体库分析之:分类别统计媒体文件大小
2014-12-18 15:50 5420对系统媒体库不了解的线看这儿: Android media媒体 ... -
Android关于短信加密
2014-08-28 16:07 2453关于Android短信加密功能,我初步了解的如下(只在Andr ... -
Android jni
2014-08-23 15:22 0http://code.google.com/p/androi ... -
Android常用shell指令收集
2016-02-15 17:24 1142一、base cmd 1、挂载文件系统:mount -o r ... -
android系统信息(内存、cpu、sd卡、电量、版本)获取
2011-05-31 11:42 38049要转载请注明出处:http://gqdy365.iteye.c ...
相关推荐
在Android串口通信:基本知识梳理的基础上,我结合我项目中使用串口的实例,进行总结; Android使用jni直接进行串口设备的读写网上已经有开源项目了,本文是基于网上的开源项目在实际项目中的使用做的调整和优化; ...
基于开源的android_serialport_api,实现串口数据的读写 设置设备打开的串口号和波特率 如:/dev/ttyUSB0 115200 public interface Reader { public boolean open() throws SecurityException, IOException; //...
VB串口通信UART程序实例源码200个合集: GE PLC串口通讯,VB编制,读取内存单元.rar PC机与51单片机之间的串口通讯,VB编的,分PC和单片机两部分.rar VB Modbus RTU源码,其中协议部分已生成DLL,可直接调用.rar VB.net...
002、Visual Basic串口通信工程开发实例导航随书源码7个 003、Visual Basic串口通信与测控应用技术实战详解 源代码(15个全) 004、GE PLC串口通讯,VB编制,读取内存单元 005、PC机与51单片机之间的串口通讯,VB编的,...
11.3.2 RS-422与RS-485串行接口标准 11.3.3 RS-422与RS-485的网络安装注意要点 11.3.4 RS-232、RS422、RS485电气参数对比 11.4 串口调试注意事项 11.5 常用数据校验法 11.5.1奇偶校验 11.5.2 循环冗余码...
android 使用服务读取串口数据实例,读取的数据实时写到txt文本。串口读写的库的地址:https://code.google.com/p/android-serialport-api/。我的博客:http://blog.csdn.net/qq_16064871。
VC实现串口通讯,数据接收、数据发送,数据解析,以回调函数的方式给其它调用 的地方或者界面直接使用。
5.1 串行接口简介 131 5.1.1 串口通信的基本概念 131 5.1.2 rs-232c串口通信标准 136 5.1.3 串口通信线路连接 139 5.1.4 计算机中的串行端口 141 5.2 串行通信控件mscomm 143 5.2.1 mscomm控件...
11.3.2 rs-422与rs-485串行接口标准 315 11.3.3 rs-422与rs-485的网络安装注意要点 317 11.3.4 rs-232、rs422、rs485电气参数对比 318 11.4 串口调试注意事项 318 11.5 常用数据校验法 318 11.5.1 奇偶校验 318...
11.3.2 RS-422与RS-485串行接口标准 315 11.3.3 RS-422与RS-485的网络安装注意要点 317 11.3.4 RS-232、RS422、RS485电气参数对比 318 11.4 串口调试注意事项 318 11.5 常用数据校验法 318 11.5.1 奇偶校验 318 ...
主要涵盖串口通信的理论基础、Visual c++集成开发环境简介、MSComm控件串口编程、Windows API串口编程、TAPI通信编程、串口实现双机互连、串口调试精灵、串口控制Modem设备、串口控制单片机、串口控制PLC、串口控制...
mfc串口通信的接收与发送 一、串口通信的概念 二、串口通信的三种协议 2.1 RS-232 2.2 RS-422 2.3 RS-485 三、串口通信方法和用处 3.1 用处 3.2 串口通信方法 四、重要参数 4.1 波特率 4.2 数据位 4.3 停止位 4.4 ...
5.1 串行接口简介 131 5.1.1 串口通信的基本概念 131 5.1.2 rs-232c串口通信标准 136 5.1.3 串口通信线路连接 139 5.1.4 计算机中的串行端口 141 5.2 串行通信控件mscomm 143 5.2.1 mscomm控件...
11.3.2 rs-422与rs-485串行接口标准 315 11.3.3 rs-422与rs-485的网络安装注意要点 317 11.3.4 rs-232、rs422、rs485电气参数对比 318 11.4 串口调试注意事项 318 11.5 常用数据校验法 318 11.5.1 奇偶校验 318...
// filename:stty.h ...//(6) 操作完成后,需要调用函数cleanTTY()来释放申请的串口信息接口; //其中,lockTTY()和unlockTTY()是为了能够在多线程中使用。在读写操作的前后,需要锁定和释放串口资源。
通过C#编写的串口 与三菱PLC 通信 该例程实现了读写三菱PLC的电压、开关量数据
11.3.2 rs-422与rs-485串行接口标准 315 11.3.3 rs-422与rs-485的网络安装注意要点 317 11.3.4 rs-232、rs422、rs485电气参数对比 318 11.4 串口调试注意事项 318 11.5 常用数据校验法 318 11.5.1 奇偶校验 318...
基于C#的RFID串口界面 方便RFID读写器的测试 界面简单 操作方便