广告位联系
返回顶部
分享到

Android实现读写USB串口数据的代码

Android 来源:互联网 作者:佚名 发布时间:2022-09-19 16:22:45 人浏览
摘要

最近在研究USB方面的内容;先后做了关于Android读写HID、串口设备的DEMO。本文比较简单,主要介绍的是Android实现读取串口数据的功能 废话不多说,先看一下业务层是如何调用的;如图:

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

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

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

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

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);

        }

    }

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

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 读取串口数据

1

2

3

4

5

6

7

8

9

10

11

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,要读取的数据长度,和放要读取的数据的数组,超时时间

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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类的写法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

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类,如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

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;

    }

 

    /**

     * 向USB设备发送数据

     * @param message 要发送的数据,字符串类型

     * @return 数据发送结果,true代表发送成功

     */

    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;

        }

    }

 

    /**

     * 接收数据

     * @return 接收的数据内容

     */

    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);

    }

 

    /**

     * 设置USB设备的波特率,方法内涉及算法等;

     * @param paramInt 要设置波特率的数值

     * @return 设置结果,true代表设置成功

     */

    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;

    }

 

    /**

     * 获取收发数据的通道

     * @param usbDevice USB设备

     * @param usbDeviceConnection 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);

        }

    }

 

    /**

     * USB接收数据线程

     */

    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 = "";

                    }

                }

            }

        }

    });

 

    /**

     * 获取USB可以收发数据的接口号

     * @param usbDevice USB设备

     * @return USB可以收发数据的接口号

     */

    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;

    }

 

     /**

     * 关闭USB连接、链路、数据通道等

     */

    public void close()

    {

        connect = false; //连接状态为false

        usbDeviceConnection.releaseInterface(usbInterface); //USB设备链路解绑接口

        usbDeviceConnection.close(); //关闭USB设备链路

        usbDeviceConnection = null; //USB设备链路赋值为空

        bulkOutUsbEndpoint = null; //输出通道赋值为空

        bulkInUsbEndpoint = null; //输入通道赋值为空

    }

 

}

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

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;

        }

    }

 

    /**

     * 返回格式化后的当前时间

     * @return 当前时间字符串形式

     */

    private String gteNowDate()

    {

        SimpleDateFormat sdf = new SimpleDateFormat();// 格式化时间

        sdf.applyPattern("HH:mm:ss");// 时:分:秒

        Date date = new Date();// 获取当前时间戳

        return sdf.format(date); //返回格式化后的时间戳

    }

 

    /**

     * 判断当前TextView是否已经填充满控件可使用高度,如果高度已满就滚动需要的距离高度

     * @param textView 需要判断的TextView控件

     * @return 已满就返回对应高度,否则就返回0

     */

    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连接状况的广播类,如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

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信息数据展示控件

 

    /**

     * 数据初始化

     * @param usbController usb控制器接口

     * @param context 上下文

     * @param tv_usbDeviceDataShow USB信息数据展示控件

     */

    UsbMonitor(UsbController usbController,Context context,TextView tv_usbDeviceDataShow)

    {

        this.usbController = usbController;

        this.context = context;

        this.tv_usbDeviceDataShow = tv_usbDeviceDataShow;

    }

 

    /**

     * 注册USB广播监听、USB权限

     */

    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设备接入,执行该操作

        }

    }

 

    /**

     * 请求打开此USB设备的权限

     * @param usbDevice 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操作权限则请求权限

            }

        }

    }

 

    /**

     * 注销USB广播监听

     */

    public void unregister()

    {

        if (context != null)

        {

            context.unregisterReceiver(this); //注销USB设备广播监听

            context = null;

            usbManager = null;

            usbController = null;

        }

    }

 

    /**

     * 广播事务处理中心

     * @param context 上下文

     * @param intent 意图

     */

    @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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public interface UsbController

{

 

     /**

     * USB设备接入时的接口

     * @param usbMonitor USB监听广播对象

     * @param usbManager USB状态、管理对象

     * @param usbDevice USB设备对象

     */

    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类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

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 ,当连接成功,就可以自动读写;代码比这个更为精简;接下来我会慢慢的记录下来。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/zhoupuxian/article/details/124309055
相关文章
  • Kotlin的Collection与Sequence操作异同点介绍

    Kotlin的Collection与Sequence操作异同点介绍
    在Android开发中,集合是我们必备的容器,Kotlin的标准库中提供了很多处理集合的方法,而且还提供了两种基于容器的工作方式:Collection 和
  • 实现一个Kotlin函数类型方法

    实现一个Kotlin函数类型方法
    接口与函数类型 业务开发中,经常会有实现一个函数式接口(即接口只有一个方法需要实现)的场景,大家应该都会不假思索的写出如下代
  • Android10 App启动Activity源码分析
    ActivityThread的main方法 让我们把目光聚焦到ActivityThread的main方法上。 ActivityThread的源码路径为/frameworks/base/core/java/android/app/ActivityThread。 1 2
  • Android10客户端事务管理ClientLifecycleManager源码解析

    Android10客户端事务管理ClientLifecycleManager源码解析
    在Android 10 App启动分析之Activity启动篇(二)一文中,简单地介绍了Activity的生命周期管理器是如何调度Activity进入onCreate生命周期的流程。这
  • Kotlin对象的懒加载方式by lazy与lateinit异同介绍

    Kotlin对象的懒加载方式by lazy与lateinit异同介绍
    属性或对象的延时加载是我们相当常用的,一般我们都是使用 lateinit 和 by lazy 来实现。 他们两者都是延时初始化,那么在使用时那么他们两
  • Android类加载流程分析

    Android类加载流程分析
    本文分析的代码基于Android8.1.0源码。 流程分析 从loadClass开始,我们来看下Android中类加载的流程 /libcore/ojluni/src/main/java/java/lang/ClassLoader.ja
  • Android实现读写USB串口数据的代码

    Android实现读写USB串口数据的代码
    最近在研究USB方面的内容;先后做了关于Android读写HID、串口设备的DEMO。本文比较简单,主要介绍的是Android实现读取串口数据的功能 废话不
  • Epoxy - 在RecyclerView中构建复杂界面
    Diffing 对于复杂数据结构支持的多个视图类型展示在屏幕上, Epoxy此时是尤其有用的. 在这些场景中, 数据可能会被网络请求, 异步 Observable, 用
  • Android性能优化的详细介绍

    Android性能优化的详细介绍
    性能优化是一个app很重要的一部分,一个性能优良的app从被下载到启动到使用都能给用户到来很好的体验。自然我们做性能优化也是从被下
  • Android进阶宝典-插件化2(Hook启动插件中四大组件

    Android进阶宝典-插件化2(Hook启动插件中四大组件
    在上一节,我们主要介绍了如果通过反射来加载插件中的类,调用类中的方法;既然插件是一个apk,其实最重要的是启动插件中的Activity、
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计