Android 串口通讯-------android -serialport-api

来源:互联网 发布:淘宝店铺装修首页全屏 编辑:程序博客网 时间:2024/05/17 03:53

最近一段时间公司接了个饮水机串口通信的项目,于是去百度、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 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,请见谅

原创粉丝点击