返回顶部
首页 > 资讯 > 移动开发 >Android实现读写USB串口数据
  • 232
分享到

Android实现读写USB串口数据

2024-04-02 19:04:59 232人浏览 八月长安
摘要

本文实例为大家分享了Android实现读写USB串口数据的具体代码,供大家参考,具体内容如下 最近在研究USB方面的内容;先后做了关于Android读写HID、串口设备的DEMO。本

本文实例为大家分享了Android实现读写USB串口数据的具体代码,供大家参考,具体内容如下

最近在研究USB方面的内容;先后做了关于Android读写HID、串口设备的DEMO。本文比较简单,主要介绍的是Android实现读取串口数据的功能

废话不多说,先看一下业务层是如何调用的;如图:

首先,监听USB连接状况,当USB 进行请求USB权限,当USB权限申请成功,进行调用打开Usb设备的方法;当监听到USB断开,进行关闭连接;

这是向串口写入数据的方法;

本DEMO主要使用Handle进行数据各个线程之间的数据传到,以及USB连接读写情况的反馈;

下面直接上代码:
连接USB设备的代码

public void openCDC(UsbDevice usbDevice, UsbDeviceConnection usbDeviceConnection)
    {
        this.usbDeviceConnection = usbDeviceConnection;
        usbInterface = usbDevice.getInterface(findCDC(usbDevice)); //获取USB设备接口
        if (usbDeviceConnection == null) //判断USB设备链路是否为空
        {
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FaiLED);
            return;
        }
        if (!usbDeviceConnection.claimInterface(usbInterface,true)) //USB设备链路绑定获取到的接口
        {
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
            return;
        }
        int numberEndpoints = usbInterface.getEndpointCount(); //获取USB设备接口的数据传输通道数量
        for (int num = 0; num <= numberEndpoints-1; num++)
        {
            UsbEndpoint usbEndpoint = usbInterface.getEndpoint(num);

            switch (usbEndpoint.getType())
            {
                //USB控制传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_CONTROL:
                    controlUsbEndpoint = usbEndpoint;
                    break;
                //USB块传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_BULK:
                    switch (usbEndpoint.getDirection())
                    {
                        case UsbConstants.USB_DIR_OUT:
                            bulkOutUsbEndpoint = usbEndpoint; //USB块传输模式输出通道
                            break;
                        case UsbConstants.USB_DIR_IN:
                            bulkInUsbEndpoint = usbEndpoint; //USB块传输模式输入通道
                            break;
                    }
                    break;
                //USB中断传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_INT:
                    switch (usbEndpoint.getDirection())
                    {
                        case UsbConstants.USB_DIR_OUT:
                            intOutUsbEndpoint = usbEndpoint;
                            break;
                        case UsbConstants.USB_DIR_IN:
                            intInUsbEndpoint = usbEndpoint;
                            break;
                    }
                    break;
            }
        }
        if (bulkOutUsbEndpoint != null && bulkInUsbEndpoint != null) //如果USB块传输模式输入输通道都不为空出
        {
            //USB连接成功
            connect = true;
            //获取到USB设备的ID、VID、PID
            String usbData = "Name:"+usbDevice.getDeviceName()+"\nID:"+usbDevice.getDeviceId()+"    VID:"+usbDevice.getVendorId()+"    PID:"+usbDevice.getProductId();
            mes = new Message();
            mes.obj = usbData;
            mes.what = MyHandler.USB_CONNECT_SUCCESS;
            myHandler.sendMessage(mes);
            threadReadData.start(); //开启接收数据线程
        }
        else
        {
            //USB连接失败
            connect = false;
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
        }
    }

这个代码有点多,可能看的不太清楚,我删减一下,是这样的

public void openCDC(UsbDevice usbDevice, UsbDeviceConnection usbDeviceConnection)
    {
        this.usbDeviceConnection = usbDeviceConnection;
        usbInterface = usbDevice.getInterface(findCDC(usbDevice)); //获取USB设备接口
      
        int numberEndpoints = usbInterface.getEndpointCount(); //获取USB设备接口的数据传输通道数量
        for (int num = 0; num <= numberEndpoints-1; num++)
        {
            UsbEndpoint usbEndpoint = usbInterface.getEndpoint(num);

            switch (usbEndpoint.getType())
            {
                //USB控制传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_CONTROL:
                    controlUsbEndpoint = usbEndpoint;
                    break;
                //USB块传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_BULK:
                    switch (usbEndpoint.getDirection())
                    {
                        case UsbConstants.USB_DIR_OUT:
                            bulkOutUsbEndpoint = usbEndpoint; //USB块传输模式输出通道
                            break;
                        case UsbConstants.USB_DIR_IN:
                            bulkInUsbEndpoint = usbEndpoint; //USB块传输模式输入通道
                            break;
                    }
                    break;
                //USB中断传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_INT:
                    switch (usbEndpoint.getDirection())
                    {
                        case UsbConstants.USB_DIR_OUT:
                            intOutUsbEndpoint = usbEndpoint;
                            break;
                        case UsbConstants.USB_DIR_IN:
                            intInUsbEndpoint = usbEndpoint;
                            break;
                    }
                    break;
            }
        }
       
    }

设备打开之后,就可以进行读写了;

Android 读取串口数据

public String readData()
    {
        byte[] tempByte = new byte[4096];
       
        int i = usbDeviceConnection.bulkTransfer(bulkInUsbEndpoint,tempByte,tempByte.length,100);//读取数据,100为超时时间,接收的数据为数组类型
   
        //将接收的数组转为字符串并返回
        byte[] messageByte = new byte[i];
        System.arraycopy(tempByte,0, messageByte,0, i);
        return new String(messageByte);
    }

这里主要通过调用谷歌提供的bulkTransfer方法进行的,传递的参数分别有endpoint,要读取的数据长度,和放要读取的数据的数组,超时时间

有了读,当然也需要写,向串口写入数据;代码如下:

public boolean send(String message)
    {
      
        byte[] messageBytes = message.getBytes(); //字符串转为数组
        int result = usbDeviceConnection.bulkTransfer(bulkOutUsbEndpoint,messageBytes,messageBytes.length,100);//发送数据,发送转换为数组后的数据,超时时间为100毫秒
        if ((result >= 0)) //发送数据返回值大于等于0代表发送成功
        {
            //向信息处理中心发送“发送成功”的信息,并将信息内容传递过去
           
            return true;
        }
        else
        {
            //发送失败
            connect = false;
            return false;
        }
    }

传输数据的方式是用Handler;以下是Handler类的写法

public void handleMessage(@NonNull Message msg)
    {
        switch (msg.what)
        {
            case USB_CONNECT_SUCCESS:  //USB设备连接成功
                MyHandler.USB_CONNECT_STATE  = true; //连接状态改变为true
                bt_send.setEnabled(true); //发送控件可以使用
                bt_sendTiming.setEnabled(true);
                bt_send.setTextColor(Color.BLACK); //定时发送控件可以使用
                bt_sendTiming.setTextColor(Color.BLACK); 
                tv_usbDataShow.setText(msg.obj.toString()); //填充意图发送过来的信息
                Toast.makeText(context,"连接成功",Toast.LENGTH_LONG).show();
                break;
            case USB_CONNECT_FAILED: //USB设备连接失败
                MyHandler.USB_CONNECT_STATE  = false;
                bt_send.setEnabled(false);
                bt_sendTiming.setEnabled(false);
                bt_send.setTextColor(Color.GRAY);
                bt_sendTiming.setTextColor(Color.GRAY);
                bt_sendTiming.setText("定时发送");
                tv_usbDataShow.setText("未连接设备");
                mainActivity.closeAll(); //连接断开或连接失败,执行关闭所有连接和对象的方法
                Toast.makeText(context,"断开连接",Toast.LENGTH_LONG).show();
                break;
            case OUTPUT:  //发送消息
                if (messageShowNeedRoll(tv_sendMessageShow) != 0) tv_sendMessageShow.scrollTo(0, messageShowNeedRoll(tv_sendMessageShow));//如果TextView填充满可使用高度就滚动到最新更新处
                tv_sendMessageShow.append("[TX]"+gteNowDate()+": "+msg.obj.toString()+"\n"); //给控件填充意图发送来的信息
                break;
            case INPUT:  //接收消息
                if (messageShowNeedRoll(tv_receiveMessageShow) != 0) tv_receiveMessageShow.scrollTo(0, messageShowNeedRoll(tv_receiveMessageShow));
                tv_receiveMessageShow.append("[RX]"+gteNowDate()+": "+msg.obj.toString()+"\n");
                break;
        }
    }

主要代码已展示完毕,接下来展示具体代码

先看USB类,如下:

public class UsbCDC
{
    private boolean connect; //USB连接状态
    private UsbInterface usbInterface; //USB设备的物理接口

    //控制传输模式通道
    private UsbEndpoint controlUsbEndpoint;
    //块传输模式通道
    private UsbEndpoint bulkInUsbEndpoint;
    private UsbEndpoint bulkOutUsbEndpoint;
    //中断传输模式通道
    private UsbEndpoint intInUsbEndpoint;
    private UsbEndpoint intOutUsbEndpoint;

    private UsbDeviceConnection usbDeviceConnection; //USB设备连接链路,用来进行设备通讯

    private Message mes; //信息包

    private MyHandler myHandler;//信息处理中心对象
    UsbCDC(MyHandler myHandler)
    {
        this.myHandler = myHandler;
    }

    
    public boolean send(String message)
    {
        if (this.usbDeviceConnection == null) //判断USB链路是否获取到,不为空才能进行数据发送
        {
            //如果USB链路为空,执行该作用域代码
            connect = false;
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
            return false;
        }
        byte[] messageBytes = message.getBytes(); //字符串转为数组
        int result = usbDeviceConnection.bulkTransfer(bulkOutUsbEndpoint,messageBytes,messageBytes.length,100);//发送数据,发送转换为数组后的数据,超时时间为100毫秒
        if ((result >= 0)) //发送数据返回值大于等于0代表发送成功
        {
            //向信息处理中心发送“发送成功”的信息,并将信息内容传递过去
            mes = new Message();
            mes.obj = new String(messageBytes);
            mes.what = MyHandler.OUTPUT;
            myHandler.sendMessage(mes);
            return true;
        }
        else
        {
            //发送失败
            connect = false;
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
            return false;
        }
    }

    
    public String readData()
    {
        byte[] tempByte = new byte[4096];
        if (usbDeviceConnection == null) //判断USB连接链路是否为空,不为空才能进行数据接收
        {
            connect = false;
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
            return null;
        }
        int i = usbDeviceConnection.bulkTransfer(bulkInUsbEndpoint,tempByte,tempByte.length,100);//读取数据,100为超时时间,接收的数据为数组类型
        if (i < 0) //小于0代表接收失败或未接收到数据,接收结果也受USB设备的影响
        {
            return null;
        }
        //将接收的数组转为字符串并返回
        byte[] messageByte = new byte[i];
        System.arraycopy(tempByte,0, messageByte,0, i);
        return new String(messageByte);
    }

    
    public boolean configUsb(int paramInt)
    {
        if (usbDeviceConnection != null)
        {
            byte[] arrayOfByte = new byte[8];
            usbDeviceConnection.controlTransfer(192, 95, 0, 0, arrayOfByte, 8, 1000);
            usbDeviceConnection.controlTransfer(64, 161, 0, 0, null, 0, 1000);
            long l1 = 1532620800 / paramInt;
            for (int i = 3; ; i--)
            {
                if ((l1 <= 65520L) || (i <= 0))
                {
                    long l2 = 65536L - l1;
                    int j = (short) (int) (0xFF00 & l2 | i);
                    int k = (short) (int) (0xFF & l2);
                    usbDeviceConnection.controlTransfer(64, 154, 4882, j, null, 0, 1000);
                    usbDeviceConnection.controlTransfer(64, 154, 3884, k, null, 0, 1000);
                    usbDeviceConnection.controlTransfer(192, 149, 9496, 0, arrayOfByte, 8, 1000);
                    usbDeviceConnection.controlTransfer(64, 154, 1304, 80, null, 0, 1000);
                    usbDeviceConnection.controlTransfer(64, 161, 20511, 55562, null, 0, 1000);
                    usbDeviceConnection.controlTransfer(64, 154, 4882, j, null, 0, 1000);
                    usbDeviceConnection.controlTransfer(64, 154, 3884, k, null, 0, 1000);
                    usbDeviceConnection.controlTransfer(64, 164, 0, 0, null, 0, 1000);
                    return true;
                }
                l1 >>= 3;
            }
        }
        else  return false;
    }

    
    public void openCDC(UsbDevice usbDevice, UsbDeviceConnection usbDeviceConnection)
    {
        this.usbDeviceConnection = usbDeviceConnection;
        usbInterface = usbDevice.getInterface(findCDC(usbDevice)); //获取USB设备接口
        if (usbDeviceConnection == null) //判断USB设备链路是否为空
        {
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
            return;
        }
        if (!usbDeviceConnection.claimInterface(usbInterface,true)) //USB设备链路绑定获取到的接口
        {
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
            return;
        }
        int numberEndpoints = usbInterface.getEndpointCount(); //获取USB设备接口的数据传输通道数量
        for (int num = 0; num <= numberEndpoints-1; num++)
        {
            UsbEndpoint usbEndpoint = usbInterface.getEndpoint(num);

            switch (usbEndpoint.getType())
            {
                //USB控制传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_CONTROL:
                    controlUsbEndpoint = usbEndpoint;
                    break;
                //USB块传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_BULK:
                    switch (usbEndpoint.getDirection())
                    {
                        case UsbConstants.USB_DIR_OUT:
                            bulkOutUsbEndpoint = usbEndpoint; //USB块传输模式输出通道
                            break;
                        case UsbConstants.USB_DIR_IN:
                            bulkInUsbEndpoint = usbEndpoint; //USB块传输模式输入通道
                            break;
                    }
                    break;
                //USB中断传输模式通道
                case UsbConstants.USB_ENDPOINT_XFER_INT:
                    switch (usbEndpoint.getDirection())
                    {
                        case UsbConstants.USB_DIR_OUT:
                            intOutUsbEndpoint = usbEndpoint;
                            break;
                        case UsbConstants.USB_DIR_IN:
                            intInUsbEndpoint = usbEndpoint;
                            break;
                    }
                    break;
            }
        }
        if (bulkOutUsbEndpoint != null && bulkInUsbEndpoint != null) //如果USB块传输模式输入输通道都不为空出
        {
            //USB连接成功
            connect = true;
            //获取到USB设备的ID、VID、PID
            String usbData = "Name:"+usbDevice.getDeviceName()+"\nID:"+usbDevice.getDeviceId()+"    VID:"+usbDevice.getVendorId()+"    PID:"+usbDevice.getProductId();
            mes = new Message();
            mes.obj = usbData;
            mes.what = MyHandler.USB_CONNECT_SUCCESS;
            myHandler.sendMessage(mes);
            threadReadData.start(); //开启接收数据线程
        }
        else
        {
            //USB连接失败
            connect = false;
            myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
        }
    }

    
    private Thread threadReadData = new Thread(new Runnable()
    {
        String message = "";
        @Override
        public void run()
        {
            while (connect) //USB处于连接状态就循环执行
            {
                String temMes = readData(); //获取到接收到的字符串
                if (temMes != null) 
                {
                    //如果接收到的数据不为空,就一直拼接,因为这些可能属于同一组数据(除非USB设备发送频率小于我们设置的超时时间100毫秒)
                    message = message+temMes;
                    continue;
                }
                else
                {
                    //接收到的数据为空了,表示该组数据接收完整了,就可以发送给消息处理中心进行处理了
                    if (!message.equals("")) //接收到的数据要不为空,不然没意义
                    {
                        mes = new Message();
                        mes.obj = message;
                        mes.what = MyHandler.INPUT;
                        myHandler.sendMessage(mes);
                        message = "";
                    }
                }
            }
        }
    });

    
    private int findCDC(UsbDevice usbDevice)
    {
        int interfaceCount = usbDevice.getInterfaceCount(); //获取USB设备接口数量
        for (int count = 0; count < interfaceCount; ++count)
        {
            //遍历获取到的接口进行判断是否为收发数据的接口,是就返回该接口号
            if (usbDevice.getInterface(count).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)
            {
                return count;
            }
        }
        // 如果获取到的所有接口没有我们需要的就返回-1
        return -1;
    }

     
    public void close()
    {
        connect = false; //连接状态为false
        usbDeviceConnection.releaseInterface(usbInterface); //USB设备链路解绑接口
        usbDeviceConnection.close(); //关闭USB设备链路
        usbDeviceConnection = null; //USB设备链路赋值为空
        bulkOutUsbEndpoint = null; //输出通道赋值为空
        bulkInUsbEndpoint = null; //输入通道赋值为空
    }

}

接下来是连接USB类与业务层的中枢,HANDLER类:

package com.jlkj.lsk.usb_host;

import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import java.text.SimpleDateFORMat;
import java.util.Date;

public class MyHandler extends Handler
{

    public static final int OUTPUT = 0; //发送消息
    public static final int INPUT = 1; //接收消息

    public static final int USB_CONNECT_SUCCESS = 2; //USB设备连接成功
    public static final int USB_CONNECT_FAILED = 3; //USB设备连接失败或断开连接

    public static boolean USB_CONNECT_STATE = false; //当前USB设备连接状态

    private Button bt_send,bt_sendTiming; 
    private TextView tv_sendMessageShow,tv_receiveMessageShow,tv_usbDataShow;
    private Context context; //上下文
    private MainActivity mainActivity;
    MyHandler(TextView tv_sendMessageShow, TextView tv_receiveMessageShow, TextView tv_usbDataShow, Button bt_send, Button bt_sendTiming, Context context,MainActivity mainActivity)
    {
        this.bt_send = bt_send;
        this.tv_sendMessageShow = tv_sendMessageShow;
        this.tv_receiveMessageShow = tv_receiveMessageShow;
        this.tv_usbDataShow = tv_usbDataShow;
        this.bt_sendTiming = bt_sendTiming;
        this.context = context;
        this.mainActivity = mainActivity;
    }

    @Override
    public void handleMessage(@NonNull Message msg)
    {
        switch (msg.what)
        {
            case USB_CONNECT_SUCCESS:  //USB设备连接成功
                MyHandler.USB_CONNECT_STATE  = true; //连接状态改变为true
                bt_send.setEnabled(true); //发送控件可以使用
                bt_sendTiming.setEnabled(true);
                bt_send.setTextColor(Color.BLACK); //定时发送控件可以使用
                bt_sendTiming.setTextColor(Color.BLACK); 
                tv_usbDataShow.setText(msg.obj.toString()); //填充意图发送过来的信息
                Toast.makeText(context,"连接成功",Toast.LENGTH_LONG).show();
                break;
            case USB_CONNECT_FAILED: //USB设备连接失败
                MyHandler.USB_CONNECT_STATE  = false;
                bt_send.setEnabled(false);
                bt_sendTiming.setEnabled(false);
                bt_send.setTextColor(Color.GRAY);
                bt_sendTiming.setTextColor(Color.GRAY);
                bt_sendTiming.setText("定时发送");
                tv_usbDataShow.setText("未连接设备");
                mainActivity.closeAll(); //连接断开或连接失败,执行关闭所有连接和对象的方法
                Toast.makeText(context,"断开连接",Toast.LENGTH_LONG).show();
                break;
            case OUTPUT:  //发送消息
                if (messageShowNeedRoll(tv_sendMessageShow) != 0) tv_sendMessageShow.scrollTo(0, messageShowNeedRoll(tv_sendMessageShow));//如果TextView填充满可使用高度就滚动到最新更新处
                tv_sendMessageShow.append("[TX]"+gteNowDate()+": "+msg.obj.toString()+"\n"); //给控件填充意图发送来的信息
                break;
            case INPUT:  //接收消息
                if (messageShowNeedRoll(tv_receiveMessageShow) != 0) tv_receiveMessageShow.scrollTo(0, messageShowNeedRoll(tv_receiveMessageShow));
                tv_receiveMessageShow.append("[RX]"+gteNowDate()+": "+msg.obj.toString()+"\n");
                break;
        }
    }

    
    private String gteNowDate()
    {
        SimpleDateFormat sdf = new SimpleDateFormat();// 格式化时间
        sdf.applyPattern("HH:mm:ss");// 时:分:秒
        Date date = new Date();// 获取当前时间戳
        return sdf.format(date); //返回格式化后的时间戳
    }

    
    private int messageShowNeedRoll(TextView textView)
    {
        int offset = textView.getLineCount() * textView.getLineHeight(); //添加的textview数量 x 字体高度
        if (offset > textView.getHeight()) return offset - tv_receiveMessageShow.getHeight(); //如果乘积大于控件高度就返回需要滚动的距离
        else return 0; //小于就返回0
    }

}

监听USB连接状况的广播类,如下:

package com.jlkj.lsk.usb_host;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.widget.TextView;
import android.widget.Toast;
import java.util.HashMap;

public class UsbMonitor extends BroadcastReceiver //继承USB广播对象
{

    private static final String ACTION_USB_PERMISSION = "com.spark.teaching.answertool.USB_PERMISSION"; //USB设备的操作权限,可自定义
    //private static final String ACTION_USB_PERMISSION = "android.USB"; //USB设备的操作权限,可自定义
    private int VID = 1155; //USB设备生产厂商ID,用来区分选择目标USB设备,如果不是该ID的USB设备,不对其进行操作
    private int PID = 1155; //USB设备生产厂商ID,用来区分选择目标USB设备,如果不是该ID的USB设备,不对其进行操作
    private UsbController usbController; //USB动作管理接口
    private UsbManager usbManager; //USB状态、管理对象
    private UsbDevice usbDevice; //USB设备
    private Context context; //上下文
    private TextView tv_usbDeviceDataShow; //USB信息数据展示控件

    
    UsbMonitor(UsbController usbController,Context context,TextView tv_usbDeviceDataShow)
    {
        this.usbController = usbController;
        this.context = context;
        this.tv_usbDeviceDataShow = tv_usbDeviceDataShow;
    }

    
    public void reGISter()
    {
        if (this.context != null)
        {
            IntentFilter intentFilter = new IntentFilter(); //意图过滤器
            intentFilter.addAction(ACTION_USB_PERMISSION); //添加USB设备的操作权限意图
            intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); //添加设备接入意图
            intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); //添加设备拔出意图
            this.context.registerReceiver(this, intentFilter); //注册添加的意图
            usbManager = (UsbManager)this.context.getSystemService(Context.USB_SERVICE); //获取USB设备管理

            if (usbManager != null)
            {
                HashMap<String,UsbDevice> list = usbManager.getDeviceList(); //获取USB设备,返回的是 UsbDevice 的Hash列表,里面是所有当前连接主机的USB设备
                for (UsbDevice usbDevice : list.values()) //遍历获取到的UsbDevice
                {
                    if ((usbDevice.getVendorId() == VID)&&(usbDevice.getProductId() == PID)) //找到目标USB设备
                    {
                        this.usbDevice = usbDevice;
                        usbController.onDeviceInsert(this, usbManager,usbDevice); //执行USB接入时接口
                        break;
                    }
                }
                tv_usbDeviceDataShow.setText("不支持该设备"); //如果列表里面没有目标USB设备,执行该操作
            }
            tv_usbDeviceDataShow.setText("未连接设备"); //如果没有USB设备接入,执行该操作
        }
    }

    
    public void requestOpenDevice(UsbDevice usbDevice)
    {
        if (usbManager != null)
        {
            if (usbManager.hasPermission(usbDevice))//如果有该USB设备的操作权限
            {
                usbController.onDeviceOpen(this,usbManager,usbDevice);//连接USB设备(打开USB设备)
            }
            else
            {
                usbManager.requestPermission(usbDevice,PendingIntent.getBroadcast(context, 666, new Intent(ACTION_USB_PERMISSION), 0));//如果没有USB操作权限则请求权限
            }
        }
    }

    
    public void unregister()
    {
        if (context != null)
        {
            context.unregisterReceiver(this); //注销USB设备广播监听
            context = null;
            usbManager = null;
            usbController = null;
        }
    }

    
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if (intent.getExtras() != null && !intent.getExtras().isEmpty())
        {
            usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); //获取意图中的USB设备
            switch(intent.getAction())
            {
                case UsbManager.ACTION_USB_DEVICE_ATTACHED: //USB设备接入
                    Toast.makeText(context, "设备接入", Toast.LENGTH_LONG).show();
                    if ((usbDevice.getVendorId() == VID)&&(usbDevice.getProductId() == PID)) usbController.onDeviceInsert(this, usbManager,usbDevice); //找到目标USB设备,执行USB设备接入时接口
                    else tv_usbDeviceDataShow.setText("不支持该设备"); //未找到目标USB设备
                    break;
                case UsbManager.ACTION_USB_DEVICE_DETACHED: //USB设备拔出
                    Toast.makeText(context, "设备断开", Toast.LENGTH_LONG).show();
                    usbController.onDevicePullOut(this,usbManager,usbDevice); //执行USB设备拔出时接口
                    break;
                case UsbMonitor.ACTION_USB_PERMISSION: //请求USB设备操作权限
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
                    {
                        //同意USB权限
                        usbController.onDeviceOpen(this,usbManager,usbDevice); //执行连接USB设备接口
                    }
                    else
                    {
                        //拒绝USB权限
                        Toast.makeText(context, "拒绝USB权限!", Toast.LENGTH_LONG).show();
                    }
                    break;
            }
        }
        else
        {
            Toast.makeText(this.context,"请检查USB设备!",Toast.LENGTH_LONG).show();
        }
    }

}

接口类 UsbController

public interface UsbController
{

     
    void onDeviceInsert(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice);

    //USB设备拔出时的接口
    void onDevicePullOut(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice);

    //连接USB设备(打开USB设备)的接口
    void onDeviceOpen(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice);
    
}

activity类

package com.jlkj.lsk.usb_host;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity implements UsbController
{
    private Timer timer; //计时器对象
    private TimerTask timerTask; //计时器任务对象

    private UsbCDC usbCDC; //当前连接的USB设备对象
    private MyHandler myHandler; //消息处理中心对象
    private UsbMonitor usbMonitor; //USB监听广播对象
    private TextView m_tv_sendMessageShow,m_tv_receiveMessageShow,m_tv_usbDataShow,m_tv_porterShow;
    private EditText m_et_messageText,m_et_time;
    private Button m_bt_send,m_bt_sendTiming,m_bt_clean,m_tv_porterSet;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView(); //实例化当前页面控件
        initData(); //加载初始数据

        m_bt_send.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                //开启新线程进行数据发送
                new Thread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        usbCDC.send(m_et_messageText.getText().toString()); //向当前连接的USB设备发送消息
                    }
                }).start();
            }
        });

        m_bt_clean.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                m_tv_sendMessageShow.setText(""); //清除发送的消息文本
                m_tv_receiveMessageShow.setText(""); //清除接收的消息文本
                m_tv_sendMessageShow.scrollTo(0, 0); //发送的消息文本回滚到最顶部
                m_tv_receiveMessageShow.scrollTo(0, 0); //接收的消息文本回滚到最顶部
            }
        });

        m_bt_sendTiming.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                //判断计时器是否为空,不为就代表正在执行计时任务,就停止当前任务
                if (timer != null)
                {
                    timer.cancel(); //停止计时器
                    timer = null; //计时器设为空
                    m_bt_sendTiming.setTextColor(Color.BLACK); //改变定时发送控件的颜色
                    m_bt_sendTiming.setText("定时发送"); //控件 恢复为“定时发送”
                }
                else
                {
                    //如果为空,就开始定时发送任务
                    if (!m_et_time.getText().toString().equals("")) //获取定时任务的时间间隔
                    {
                        timer = new Timer(); //创建定时器
                        timerTask = new TimerTask() //创建定时任务
                        {
                            @Override
                            public void run()
                            {   
                                //定时任务要执行的内容
                                usbCDC.send(m_et_messageText.getText().toString());
                            }
                        };
                        new Thread(new Runnable() //开启新线程执行 开启计时器
                        {
                            @Override
                            public void run()
                            {
                                //开启计时器
                                timer.schedule(timerTask,0,Integer.parseInt(m_et_time.getText().toString()));
                            }
                        }).start();
                        m_bt_sendTiming.setTextColor(Color.RED);
                        m_bt_sendTiming.setText("停止"); //计时器开始后“定时发送”控件就改变颜色和字体
                    }
                    else
                    {
                        //判断计时器是否为空,如果为空,就执行该作用域内容
                        Toast.makeText(MainActivity.this,"定时不能为空",Toast.LENGTH_LONG).show();
                    }
                }
            }
        });

        m_tv_porterSet.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                //展示设置波特率的diaog对象
                setPorter();
            }
        });
    }

    @Override
    public void onDeviceInsert(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice)
    {
        usbMonitor.requestOpenDevice(usbDevice); //请求USB连接权限
    }

    @Override
    public void onDevicePullOut(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice)
    {
       closeAll(); //执行关闭所有连接的方法
       myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED); //向消息中心发送 断开连接 信息
    }

    @Override
    public void onDeviceOpen(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice)
    {
        usbCDC = new UsbCDC(myHandler); //创建USB连接的对象
        UsbDeviceConnection connection = usbManager.openDevice(usbDevice); //获取此USB链路
        usbCDC.openCDC(usbDevice, connection); //连接USB设备(打开USB设备)
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        closeAll();//执行关闭所有连接的方法
        myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);//向消息中心发送 断开连接 信息
    }

    //关闭所有连接
    public void closeAll()
    {
        if (usbCDC != null)
        {
            usbCDC.close();
            usbCDC = null;
        }
        if (timer != null)
        {
            timer.cancel();
            timer = null;
        }
    }

    //展示设置波特率dialog的对象,用一个AlertDialog让用户进行选择比特率
    private void setPorter()
    {
        final String[] items = {"2400","4800","9600","19200","38400","57600","115200","230400","460800","1700000","2300000","3400000"};
        AlertDialog.Builder listDialog = new AlertDialog.Builder(MainActivity.this);
        listDialog.setTitle("设置波特率");
        listDialog.setItems(items, new DialogInterface.OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                //判断当前USB设备是否连接,连接之后才可以设置波特率
               if (usbCDC != null)
               {
                   boolean porter = usbCDC.configUsb(Integer.parseInt(items[which])); //执行设置波特率的对象,返回true代表设置成功
                   m_tv_porterShow.setText(porter ? "波特率:"+items[which]:"波特率:9600"); //设置波特率对象返回true才改变控件字体,否则设置失败,不改变控件字体
               }
               else
               {
                    //判断当前USB设备是否连接,未连接则提示 设备未连接
                   Toast.makeText(MainActivity.this,"设备未连接",Toast.LENGTH_LONG).show();
               }
            }
        });
        listDialog.show(); //展示dialog
    }

    //加载数据
    private void initData()
    {
        myHandler = new MyHandler(m_tv_sendMessageShow,m_tv_receiveMessageShow,m_tv_usbDataShow,m_bt_send,m_bt_sendTiming,this,MainActivity.this); //实例化消息处理中心
        usbMonitor = new UsbMonitor(this,this,m_tv_usbDataShow); //实例化USB广播监听
        usbMonitor.register(); //注册USB广播监听,注册之后,才可以正常监听USB设备
    }

    //实例化控件
    private void initView()
    {
        m_tv_receiveMessageShow = (TextView)findViewById(R.id.m_tv_receiveMessageShow);
        m_tv_receiveMessageShow.setMovementMethod(ScrollingMovementMethod.getInstance());
        m_tv_sendMessageShow = (TextView)findViewById(R.id.m_tv_sendMessageShow);
        m_tv_sendMessageShow.setMovementMethod(ScrollingMovementMethod.getInstance());
        m_tv_usbDataShow = (TextView)findViewById(R.id.m_tv_usbDataShow);
        m_et_messageText = (EditText)findViewById(R.id.m_et_messageText);
        m_et_time = (EditText)findViewById(R.id.m_et_time);
        m_bt_sendTiming = (Button)findViewById(R.id.m_bt_sendTiming);
        m_bt_clean = (Button)findViewById(R.id.m_bt_clean);
        m_bt_send = (Button)findViewById(R.id.m_bt_send);
        m_tv_porterShow = (TextView)findViewById(R.id.m_tv_porterShow);
        m_tv_porterSet = (Button)findViewById(R.id.m_bt_porterSet);
    }

}

这个比较初级,接下来,我会再出一个精简版本;详细探讨Android读取USB串口、HID设备的实现;我把这两个集成在了一起,并打包成了arr文件,这个库可以自动识别USB 串口或USB hid ,当连接成功,就可以自动读写;代码比这个更为精简;接下来我会慢慢的记录下来。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Android实现读写USB串口数据

本文链接: https://lsjlt.com/news/167847.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android实现读写USB串口数据
    本文实例为大家分享了Android实现读写USB串口数据的具体代码,供大家参考,具体内容如下 最近在研究USB方面的内容;先后做了关于Android读写HID、串口设备的DEMO。本...
    99+
    2024-04-02
  • Python 串口读写实现
    #Python 串口读写实现 如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:12951803 1.安装pyserial https://pypi.python.org/pypi/p...
    99+
    2023-01-31
    串口 Python
  • 【python】之serial模块,读写串口数据!
    串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。串口是计算机上一种非常通用的设备通信协议。pyserial模...
    99+
    2023-09-13
    python pip
  • linux串口读写异步怎么实现
    在Linux系统中,可以使用文件IO的方式来实现串口的读写操作。具体的步骤如下:1. 打开串口设备文件: 使用`open()`函数来...
    99+
    2023-09-16
    linux
  • java读写串口数据你了解多少
    目录1.导入支持java串口通信的jar包:2.编写代码操作串口:总结最近接触到了串口及其读写,在此记录java进行串口读写的过程。 1.导入支持java串口通信的jar包: 在ma...
    99+
    2024-04-02
  • Android实现读写JSON数据的方法
    本文实例讲述了Android实现读写JSON数据的方法。分享给大家供大家参考。具体如下: 1. 解析JSON: package de.vogella.android.twit...
    99+
    2022-06-06
    json数据 JSON 方法 Android
  • php_dio读取串口数据
    php_dio读取串口数据 一、运行环境 php_dio.dll需要找到与PHP版本相匹配的版本,下载后打开扩展完成安装。 下载地址phpStudy2018 切换到PHP 7.0.12-NTS。(更...
    99+
    2023-09-24
    php 开发语言
  • Android Usb(OTG)串口通信,Service 后台服务实现方式
    以下是几个开源的 Android 串口通信库: 1. SerialPort:https://github.com/felHR85/SerialPort 这是一个非常流行的 Android 串口通信库,支持多种设备和多种波特率,并且提供了非常...
    99+
    2023-09-01
    android android studio ide
  • Android USB转串口通信开发实例详解
     Android USB转串口通信开发实例详解 好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行...
    99+
    2022-06-06
    usb转串口 串口 串口通信 通信 Android
  • python如何读取串口数据
    在Python中,可以使用第三方库pyserial来读取串口数据。首先需要安装pyserial库,可以使用pip安装: pip in...
    99+
    2024-04-02
  • Android实现读写SD卡
    SD卡的读写是我们在开发Android 应用程序过程中最常见的操作。下面介绍SD卡的读写操作方式:    1. 获取SD卡的根目录 代码如下: Strin...
    99+
    2022-06-06
    sd卡 sd Android
  • android读写sd卡操作写入数据读取数据示例
    代码如下:package com.example.sdcardtest;import java.io.BufferedReader;import java.io.File;i...
    99+
    2022-06-06
    示例 数据 sd sd卡 Android
  • RS232 Android获取串口数据
    串口 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单...
    99+
    2023-09-20
    android
  • android实现NFC读写功能
    一、NFC是什么? 近距离无线通讯技术,这个技术由非接触式射频识别(RFID)演变而来,由飞利浦半导体(现恩智浦半导体公司)、诺基亚和索尼共同研制开发,其基础是RFID及互连技术。近...
    99+
    2024-04-02
  • Amoeba实现数据库读写分离
    一 环境以及软件版本:系统:CentOS Linux release 7.2.1511 (Core)mysql:Server version: 5.6.33Amoeba:amoeba-mysql-3.0.5...
    99+
    2024-04-02
  • Android串口开发之使用JNI实现ANDROID和串口通信
    导语:Android串口通信在物联网、智能家居等领域具有广泛的应用。本文将详细介绍如何使用JNI技术实现Android设备与串口的通信,包括串口的打开、设置参数和读写数据等过程。 目录 一...
    99+
    2023-10-20
    android java android studio 串口通信 JNI
  • python怎么读取保存串口数据
    在Python中,可以使用pySerial库来读取和保存串口数据。以下是一个简单的示例代码: import serial # 打开...
    99+
    2024-04-02
  • vb实时读取串口数据的方法是什么
    在VB中实时读取串口数据的方法有多种,以下是其中一种常用的方法:首先,在VB中引用`System.IO.Ports`命名空间,以便使...
    99+
    2023-09-29
    vb
  • Android操作串口时,可读不可写,视美泰A20~A40问题
    背景: 最近由于项目需要将先前视美泰A20的程序升级到A40上使用,原则上不应该有问题的,但发现切换过来的程序操作串口数据时只能读不能写。 原因分析: 对于可读不可写,说明波特...
    99+
    2022-06-06
    串口 Android
  • Android存储卡读写文件与Application数据保存的实现介绍
    目录一、在存储卡上读写图片文件二、Application1、Application生命周期2、利用Application操作全局变量一、在存储卡上读写图片文件 Android的位图工...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作