Android 开源USB读写demo,实现串口通信

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


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

这是我插拔USB的运行视频

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">
    <!--  添加1  -->
    <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" />
                <!-- 添加2 -->
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <!-- 添加3 -->
            <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();方法获取,例如我的运行截图
在这里插入图片描述

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

		if (mDevice.getProductName().startsWith("USB2.0-Ser")) {
    
    
				if (!mUsbManager.hasPermission(mDevice)){
    
    
					// 没有权限的情况下再申请
                    mUsbManager.requestPermission(mDevice, permissionIntent);
                }
                if (mUsbManager.hasPermission(mDevice)){
    
    
                    configDevice();// 方法具体是设置波特率指令,以及你自己的业务
                }

猜你喜欢

转载自blog.csdn.net/gao511147456/article/details/128128565