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


    CSDN 下载链接https://download.csdn.net/download/gao511147456/87226599(可0积分免费下载)


    如果你不想下载可以阅读下面教程并复制代码到自己的项目中

    这是我插拔USB的运行视频

    device-2022-11-27-231324

    AndroidManifest

    
    <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>
    
    • 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

    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;
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    初始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");
                            }
                        }
                    }
                }
    
            }
        }
    
    • 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

    数据接收广播

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

    设置波特率

    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;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    轮询读线程

    如果影响性能记得增加延时设置执行频率例如“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);
                }
            }
        }
    
    • 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

    发送数据方法封装

        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");
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    断开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("请重启连接设备");
                            }
                        });
    
                    }
                }
            }
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    device_filter

    
    <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>
    
    • 1
    • 2
    • 3
    • 4

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

    如果每次申请USB弹窗麻烦,可以加这个判断

    		if (mDevice.getProductName().startsWith("USB2.0-Ser")) {
    				if (!mUsbManager.hasPermission(mDevice)){
    					// 没有权限的情况下再申请
                        mUsbManager.requestPermission(mDevice, permissionIntent);
                    }
                    if (mUsbManager.hasPermission(mDevice)){
                        configDevice();// 方法具体是设置波特率指令,以及你自己的业务
                    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    Trino 387 Docker 部署配置数据源后不显示对应数据Catalog
    ESP8266-Arduino编程实例-WS2812驱动
    REF543KB127AAAA 支持整个企业的有效扩展规划和分析
    Windows 启动过程
    Java游戏核心架构之通信架构
    传输层协议:TCP/IP协议,UDP的协议
    React - 路由 NavLink 使用 与 NavLink 组件封装使用(路由高亮)
    [附源码]计算机毕业设计springboot校园服装租赁系统
    A - Penalty Kick
    腾讯 T10级 Jetpack 学习思维导图意外流出,还不赶紧过来围观?
  • 原文地址:https://blog.csdn.net/gao511147456/article/details/128128565