Android 串口通讯-------android -serialport-api
2017-05-21 20:06
615 查看
最近一段时间公司接了个饮水机串口通信的项目,于是去百度、github查找一些资料
http://code.google.com/p/android-serialport-api/这是谷歌提供的demo,但无法运行,这就尴尬了
串口的操作无非就是几步:
1.打开串口(及配置串口)
2.读串口;
3.写串口;
4.关闭串口。
提到串口就不得不说JNI了,它使java可以直接调用C生成的库,为可在android中使用串口,通过配置生成一个c语言的动态链接库serial_port.so(自动命名成libserial_port.so),并把它放在了libs/aemeabi 里,其c源文件在JNI中,大家在下载了android-serialport-api的源代码后,将这两个文件夹copy到自己新建的工程中即可。生成.so文件请看JNI配置
相关代码
1,加载动态库.so文件
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, int flags) throws SecurityException, IOException { /* Check access permission */ if (!device.canRead() || !device.canWrite()) { try { /* Missing read/write permission, trying to chmod the file */ Process su; su = Runtime.getRuntime().exec("/system/bin/su"); String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" + "exit\n"; su.getOutputStream().write(cmd.getBytes()); if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) { throw new SecurityException(); } } catch (Exception e) { e.printStackTrace(); throw new SecurityException(); } } mFd = open(device.getAbsolutePath(), baudrate, flags); if (mFd == null) { Log.e(TAG, "native open returns null"); throw new IOException(); } mFileInputStream = new FileInputStream(mFd); mFileOutputStream = new FileOutputStream(mFd); } // Getters and setters public InputStream getInputStream() { return mFileInputStream; } public OutputStream getOutputStream() { return mFileOutputStream; } // JNI private native static FileDescriptor open(String path, int baudrate, int flags); public native void close(); static { System.loadLibrary("serial_port"); } }
2.C文件
JNI有一定了解的人就会知道,在写c语言链接库时候,函数的命名是和调用它的类所在的包名相关的,一旦包名与链接库中函数的命名不相符,就不能调用链接库的函数。这里可以打开jni中的.c文件
/* * Copyright 2009-2011 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 <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <jni.h> #include "com_cosin_serialport_SerialPort.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 4000 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: android_serialport_SerialPort * Method: open * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; */ JNIEXPORT jobject JNICALL Java_com_cosin_serialport_SerialPort_open (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags) { int fd; speed_t speed; jobject mFileDescriptor; /* Check arguments */ { speed = getBaudrate(baudrate); if (speed == -1) { /* TODO: throw an exception */ return NULL; } } /* Opening device */ { jboolean iscopy; const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy); fd = open(path_utf, O_RDWR | flags); (*env)->ReleaseStringUTFChars(env, path, path_utf); if (fd == -1) { /* Throw an exception */ /* TODO: throw an exception */ return NULL; } } /* Configure device */ { struct termios cfg; if (tcgetattr(fd, &cfg)) { close(fd); /* TODO: throw an exception */ return NULL; } cfmakeraw(&cfg); cfsetispeed(&cfg, speed); cfsetospeed(&cfg, speed); if (tcsetattr(fd, TCSANOW, &cfg)) { close(fd); /* TODO: throw an exception */ return NULL; } } /* Create a corresponding file descriptor */ { jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor"); jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>", "()V"); jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I"); mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor); (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd); } return mFileDescriptor; } /* * Class: cedric_serial_SerialPort * Method: close * Signature: ()V */ JNIEXPORT void JNICALL Java_com_cosin_serialport_SerialPort_close (JNIEnv *env, jobject thiz) { jclass SerialPortClass = (*env)->GetObjectClass(env, thiz); jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor"); jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;"); jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I"); jobject mFd = (*env)->GetObjectField(env, thiz, mFdID); jint descriptor = (*env)->GetIntField(env, mFd, descriptorID); close(descriptor); }
3.操作串口
/** * 进行串口通讯 */ public class SerialPortData { private long nowTimes; public DeviceCodeCallBack mDeviceCodeCallBack = null; public CmdCallBack mCmdCallBack = null; public Timer mTimer = null; private static SerialPortData mSerial = null; private FileOutputStream fileOutputStream; private FileInputStream fileInputStream; private SerialPort serialPort; private int size; private SerialPortFinder finder; private byte[] buffer; private ReadThread readThread; private int i = 1; private Context Cotext; public static SerialPortData getIntence() { if (mSerial == null) { mSerial = new SerialPortData(); } return mSerial; } /** * 打开串口 */ public void openSerialPort(Context mCotext) { Cotext = mCotext; try { serialPort = new SerialPort(new File("/dev/ttyS1"), Constant.BAUD_RATE, 0); fileOutputStream = (FileOutputStream) serialPort.getOutputStream(); fileInputStream = (FileInputStream) serialPort.getInputStream(); Toast.makeText(mCotext, "打开成功", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } } private InputStreamReader inputStream; /** * 启动线程接收数据 */ public void readReceivedData() { Log.i("zy", "线程进行中" + fileInputStream.toString()); if (fileInputStream == null) { return; } if (readThread == null) { readThread = new ReadThread(); readThread.start(); } } /** * 把获取到的数据转成十六进制后设置到TextView显示 * * @param buffer * @param size */ private void onDataReceived(final byte[] buffer, final int size) { byteArrayToHex(buffer, size).toUpperCase(); } /** * byte数组转成十六进制 * * @param buffer * @param size * @return */ public String byteArrayToHex(byte[] buffer, int size) { StringBuilder strBuilder = new StringBuilder(); if (fileInputStream != null) { inputStream = new InputStreamReader(fileInputStream); BufferedReader bufferedReader = new BufferedReader(inputStream); try { String buff = bufferedReader.readLine(); if (buff.contains("+")) { /** * 截取+后面的数据 */ String indexString = buff.substring(buff.indexOf("+") + 1); Log.i("zy", "截取数据-----" + indexString); isData(indexString); } } catch (IOException e) { e.printStackTrace(); } } return strBuilder.toString(); } /** * 获取所有的串口设备 */ public void getAllSerialPortDevices() { finder = new SerialPortFinder(); String[] devices = finder.getAllDevices(); String[] paths = finder.getAllDevicesPath(); } /** * 接收串口数据的线程;因为串口设备每秒发一次数据,这里一直接收。 */ class ReadThread extends Thread { @Override public void run() { while (true) { try { buffer = new byte[512]; size = fileInputStream.read(buffer); if (size > 0) { onDataReceived(buffer, size); } Thread.sleep(1000); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 输出字符串转字节 */ public void OutStreamDevices(final String sendOrder) { try { if (fileOutputStream == null) { return; } byte[] text = (sendOrder).getBytes(); fileOutputStream.write(text); fileOutputStream.flush(); } catch (Exception e) { e.printStackTrace(); } }
以上就是我所有的操作。如果有问题,请联系本人,因没有直接在项目中实现,无法上传Demo,请见谅
相关文章推荐
- Android串口操作,简化android-serialport-api的demo(附源码)
- Android串口操作,简化android-serialport-api的demo
- 关于利用android-serialport-api实现在安卓设备上进行串口通信,附精简版demo,亲测可用。
- Android串口操作,简化android-serialport-api的demo的问题
- Android串口操作,简化android-serialport-api的demo
- android 串口 android-serialport-api
- Android串口操作,简化android-serialport-api的demo
- Android串口操作,简化android-serialport-api的demo(附源码)
- Android串口操作,简化android-serialport-api的demo(附源码)
- [Android串口]android_serialport_api学习
- 关于http://code.google.com/p/android-serialport-api/有个可读写串口的API 遇到的问题以及解决办法
- android开发(37) android使用android_serialport_api 操作串口,解决权限问题
- android开发(37) android使用android_serialport_api 操作串口,解决权限问题
- Android串口操作,简化android-serialport-api的demo(附源码)
- Android串口操作,简化android-serialport-api的demo
- Android串口操作,简化android-serialport-api的demo
- Android串口操作,简化android-serialport-api的demo(转载)
- Android串口操作,简化android-serialport-api的demo(转)
- Android串口的源码(android-serialport-api)
- Android Studio使用Android_Serialport_Api调试串口