Android 开源一个USB读写demo,从多个USB设备中选择一个实现外设控制的通信

news2024/12/28 20:09:05

CSDN 下载链接https://download.csdn.net/download/gao511147456/87226599
如果你不想下载可以阅读下面教程并复制代码

运行视频

device-2022-11-27-231324

AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.rongzl.usbdemo">
    <uses-feature android:name="android.hardware.usb.host" android:required="true"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.USBdemo"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
        </activity>

    </application>

</manifest>

MainActivity

private static final String TAG = "MainActivity";
    private UsbManager mUsbManager;
    private UsbDevice mDevice;
    private UsbInterface inft;
    private AppCompatButton btSend;
    private UsbEndpoint mEndpointIN;
    private UsbEndpoint mEndpointOUT;
    private UsbDeviceConnection mUsbConnection;

    private TextView mTextView;
    private TextView mTextViewDeviceStatus;
    private TextView mTextViewDeviceInfo;

初始USB端口

mDevice.getProductName().startsWith(“USB2.0-Ser”)方法筛选了我的USB端口,如果不做这一步,会误连接到相机等USB设备

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.tv_usb_msg);
        mTextViewDeviceStatus = findViewById(R.id.tv_usb_status);
        mTextViewDeviceInfo = findViewById(R.id.tv_usb_info);
        btSend = findViewById(R.id.bt_send);
        btSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendMsg(view);
            }
        });
        UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        String ACTION_USB_PERMISSION =
                "com.android.example.USB_PERMISSION";
        String ACTION_USB_DEVICE_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";



        PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        PendingIntent permissionIntent1 = PendingIntent.getBroadcast(this, 12, new Intent(ACTION_USB_DEVICE_DETACHED), 0);
        IntentFilter filter1 = new IntentFilter(ACTION_USB_DEVICE_DETACHED);
        registerReceiver(usbPerMissionReceiver, filter);
        registerReceiver(usbDetachedReceiver, filter1);

        mUsbManager = (UsbManager) this.getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

        while (deviceIterator.hasNext()) {
            mDevice = deviceIterator.next();
            //因为只有一个设备插入,所以直接获取该设备的接口及端点
            //请求访问/连接usb设备的权限
            if (mDevice.getProductName().startsWith("USB2.0-Ser")){
                mUsbManager.requestPermission(mDevice, permissionIntent);
                inft = mDevice.getInterface(0);
                Log.d(TAG,"Interface Count:" + mDevice.getInterfaceCount());
                int endpointCount = inft.getEndpointCount();
                for (int i = 0; i < endpointCount; i++) {
                    if (inft.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                        if (inft.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) {
                            mEndpointIN = inft.getEndpoint(i);
                            Log.d(TAG, "获取到mEndpointIN");
                        } else if (inft.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_OUT) {
                            mEndpointOUT = inft.getEndpoint(i);
                            Log.d(TAG, "获取到mEndpointOUT");
                        }
                    }
                }
            }

        }
    }

数据接收广播

    private static final String ACTION_USB_PERMISSION =
            "com.android.example.USB_PERMISSION";
    private final BroadcastReceiver usbPerMissionReceiver = new BroadcastReceiver() {

        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "onReceive");
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        //获取连接权限成功
                        mDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                        if (mDevice != null) {
                            //打开设备
                            mUsbConnection = mUsbManager.openDevice(mDevice);
                            mUsbConnection.claimInterface(inft,true);
                            if (mUsbConnection != null) {
                                Log.d(TAG, "连接设备成功");
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        mTextViewDeviceInfo.setText(mDevice.toString());
                                        mTextViewDeviceStatus.setText("连接设备成功");
                                    }
                                });
                            }

                            //开启接收数据线程
                            if (myThread==null){
                                //设置波特率
                                Log.d(TAG, "Start the thread");
                                configUsb(9600);
                                myThread = new MyThread();
                                myThread.start();
                                sendMsg(null);
                            }

                        }
                    } else {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this,"访问权限被拒绝",Toast.LENGTH_SHORT);
                            }
                        });

                        //Log.d(TAG, "访问权限被拒绝 " + mDevice);
                    }
                }
            }
        }
    };

设置波特率

paramInt 为usb 波特率值

    private boolean configUsb(int paramInt) {
        byte[] arrayOfByte = new byte[8];
        mUsbConnection.controlTransfer(192, 95, 0, 0, arrayOfByte, 8, 1000);
        mUsbConnection.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);
                mUsbConnection.controlTransfer(64, 154, 4882, j, null, 0, 1000);
                mUsbConnection.controlTransfer(64, 154, 3884, k, null, 0, 1000);
                mUsbConnection.controlTransfer(192, 149, 9496, 0, arrayOfByte, 8, 1000);
                mUsbConnection.controlTransfer(64, 154, 1304, 80, null, 0, 1000);
                mUsbConnection.controlTransfer(64, 161, 20511, 55562, null, 0, 1000);
                mUsbConnection.controlTransfer(64, 154, 4882, j, null, 0, 1000);
                mUsbConnection.controlTransfer(64, 154, 3884, k, null, 0, 1000);
                mUsbConnection.controlTransfer(64, 164, 0, 0, null, 0, 1000);
                return true;
            }
            l1 >>= 3;
        }
    }

轮训读线程

如果影响性能记得增加延时设置执行频率例如“SystemClock.sleep(1000);

    MyThread myThread;

    public void sendMsg(View view) {
        Log.i(getClass().getSimpleName(),"sendMsgClick");
        sendMessage("updataTem");
    }

    public class MyThread extends Thread {
        private boolean isReceive = true;
        String message = null;
        byte[] bytes = new byte[5];
        @Override
        public void run() {
            super.run();
            while (isReceive) {
                int i = mUsbConnection.bulkTransfer(mEndpointIN, bytes, 0, bytes.length, 3000);
                if(i < 0){
                    // Log.d(TAG,"没有收到数据。。。");
                }else{
                    try {
                        message = new String(bytes,"UTF-8");
                        Log.d(TAG, "接收到数据:" + message);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                mTextView.setText(message);
                            }
                        });
                        isReceive = false;
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
                SystemClock.sleep(1000);
            }
        }
    }
    private void sendMessage(String msg) {
        byte[] bytes = msg.getBytes();
        Log.d(TAG, "mUsbConnection-->msg length: "+bytes.length+";"+mEndpointOUT.getMaxPacketSize());
        if (mUsbConnection != null) {
            int result = mUsbConnection.bulkTransfer(mEndpointOUT, bytes, bytes.length, 3000);
            if (result < 0) {
                Log.d(TAG, "发送失败");
            } else {
                Log.d(TAG, "发送成功"+msg);
            }
        } else {
            Log.d(TAG, "mUsbConnection-->null");
        }

    }

断开USB 监听广播(可选)

    BroadcastReceiver usbDetachedReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (device != null) {
                    mUsbConnection.releaseInterface(inft);
                    mUsbConnection.close();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mTextViewDeviceStatus.setText("设备已断开连接");
                            mTextViewDeviceInfo.setText("请重启连接设备");
                        }
                    });

                }
            }
        }
    };

device_filter

<?xml version="1.0" encoding="utf-8"?>
<resource xmlns:android="http://schemas.android.com/apk/res/android">
    <usb-device vendor-id="6790" product-id="29987" class="255" subclass="0" protocol="0" />
</resource>

上面的值可以通过打印mDevice.toString();方法获取,例如我的运行截图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/50990.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数仓常用排序详解

目录 order by&#xff1a;全局排序 sort by&#xff1a;局部排序 cluster by&#xff1a;簇排序 group by partition by order by&#xff1a;全局排序 order by 会对数据进行一次全局排序&#xff0c;所以说&#xff0c;只要hive的sql中指定了order by&#xff0c;那么…

二、【React拓展】懒加载 lazy

文章目录1、适用点2、汇总1、适用点 懒加载往往配合路由一起使用&#xff0c;此处修改的项目是 二、【React-Router5】路由的基本使用 中的项目 首先从react中引入lazy import { lazy } from react 修改引入路由组件的写法 // import About from ./pages/About // import Home…

[附源码]Python计算机毕业设计Django房屋租赁信息系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[附源码]Python计算机毕业设计SSM-乐室预约小程序(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

数字化下烟草行业人力资源管理实践与思考

“十四五”期间&#xff0c;高质量发展要求提质增效、科技创新、转型升级、数字化发展&#xff1b;在政府的工作报告中“创新”、“增长”、“机制”这些词不断提及&#xff0c;企业的发展重点也逐渐由高增长变为高质量发展。烟草行业如何对标世界一流管理&#xff0c;促进人力…

人工智能、机器学习概述

一、人工智能简单了解 1.人工智能发展必备三要素&#xff1a; 数据算法计算力 CPU,GPU,TPU计算力之CPU、GPU对比&#xff1a; CPU主要适合I\O密集型的任务 GPU主要适合计算密集型任务 2.人工智能、机器学习和深度学习 人工智能和机器学习&#xff0c;深度学习的关系 机器学…

野火FPGA进阶(2):基于I2C协议的EEPROM驱动控制

文章目录第49讲&#xff1a;基于I2C协议的EEPROM驱动控制理论部分设计与实现i2c_ctrli2c_rw_dataeeprom_byte_rd_wrtb_eeprom_byte_rd_wr第49讲&#xff1a;基于I2C协议的EEPROM驱动控制 理论部分 I2C通讯协议&#xff08;Inter-Integrated Circuit&#xff09;是由Philips公…

Flume环境搭建

1、新建一个专门放文件的目录&#xff1a;mkdir /export/server 2、将Flume的安装包上传到/export/server目录并解压&#xff0c;重命名&#xff1a; tar -zxvf apache-flume-1.8.0-bin.tar.gz -C /export/server mv apache-flume-1.8.0-bin flume 3、修改flume-env.sh文件…

[附源码]计算机毕业设计JAVA校园飞毛腿系统

[附源码]计算机毕业设计JAVA校园飞毛腿系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis …

第2-4-10章 规则引擎Drools实战(3)-保险产品准入规则

文章目录9.3 保险产品准入规则9.3.1 决策表9.3.2 规则介绍9.3.3 实现步骤9.3 保险产品准入规则 全套代码及资料全部完整提供&#xff0c;点此处下载 9.3.1 决策表 前面我们编写的规则文件都是drl形式的文件&#xff0c;Drools除了支持drl形式的文件外还支持xls格式的文件&am…

天宇优配|钠电池汽车要来了,续航达500公里!持续高成长股揭秘

钠电池行将进入量产元年。 11月29日&#xff0c;在钠离子电池产业链与规范开展论坛上&#xff0c;宁德年代研究院副院长黄起森表明&#xff0c;在乘用车使用方面&#xff0c;钠离子电池遍及可以满意续航400公里以下的车型需求&#xff0c;宁德年代则通过首创的AB电池体系集成技…

内容、文档和流程数字化如何支持精益原则

内容、文档和流程数字化如何支持精益原则 无论您身处哪个行业&#xff0c;想要在业务中取得真正的成功就必须把客户放在所有决策的中心位置&#xff0c;以便您能够给客户提供最佳服务。同时公司以最高效的方式向前发展也很重要。幸运的是&#xff0c;有一种方法可以确保两者兼而…

SpringCloud系列(四)Nacos 的三个有利配置(服务分级存储 / 环境隔离 / 负载均衡策略))

Nacos 的三个有利配置&#x1f697; Nacos 服务分级存储模型&#x1f697; &#x1f697; 环境隔离 - namespace&#x1f697; &#x1f697; &#x1f697; NacosRule 负载均衡策略我们都知道在京东商城购买商品&#xff0c;如果选择的是京东自营&#xff0c;那么几乎都是次日…

Springboot毕业设计毕设作品,农产品销售系统设计与实现

功能清单 【后台管理功能模块】 系统设置&#xff1a;设置关于我们、联系我们、加入我们、法律声明的信息。 广告管理&#xff1a;设置网站首页轮播图和链接地址。 留言管理&#xff1a;显示用户通过前台留言的列表&#xff0c;支持删除。 会员中心&#xff1a;显示所有注册用户…

Python图像处理【1】图像与视频处理

图像与视频处理0. 前言1. 在 3D 空间中显示 RGB 图像颜色通道1.1 图像表示1.2 在 3D 空间中绘制颜色通道2. 使用 scikit-video 读/写视频文件2.1 scikit-video 库2.2 读/写视频文件2.3 提取视频文件属性2.4 读取并保存视频3. 使用 OpenCV 从相机捕获实时视频4. 实现 Gotham 图像…

[附源码]计算机毕业设计springboot葡萄酒销售管理系统论文

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Python jupyter notebook Katex|Latex

目录 1.行内公式编辑 2.矩阵公式编辑 3.添加括号 4.添加图片 1.行内公式编辑 $\alpha\beta \gamma$点击control回车&#xff1b; 运行结果&#xff1a; 2.矩阵公式编辑 \begin{matrix} a & b &c \\ d & e & f \\ j & h & i \end{matrix} 点击…

基于随机森林实现特征选择降维及回归预测(Matlab代码实现)

目录 摘要&#xff1a; 1.随机森林&#xff1a; 2.随机森林的特征选取&#xff1a; 3.基于Matlab自带的随机森林函数进行特征选取具体步骤 &#xff08;1&#xff09;加载数据 &#xff08;2&#xff09;首先建立随机森林并使用全部特征进行车辆经济性预测 &#xff08;3&#…

Shell脚本学习指南(五)——变量、判断、重复动作

文章目录前言变量与算术变量赋值与环境参数展开展开运算符位置参数特殊变量算术展开退出状态退出状态值if-else-else-fi语句逻辑的NOT、AND与ORtest命令case语句循环for循环while与until循环break与continueshift与选项处理函数前言 变量对于正规程序而言很重要。处理维护有用…

Android: SimpleAdapter+GridView 简单图片展示

1&#xff1a;原理解析&#xff1a; 一个xml放总布局&#xff0c;一个xml放适配器要加载的模板&#xff08;我喜欢这样理解&#xff09;&#xff1b; java中写适配事件&#xff1b; 2&#xff1a;目录&#xff1a; 3&#xff1a;主布局&#xff1a;最重要的是要放一个GridView …