Android 开源USB读写demo,实现串口通信
CSDN 下载链接如果你不想下载可以阅读下面教程并复制代码。
·
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();// 方法具体是设置波特率指令,以及你自己的业务
}
更多推荐
已为社区贡献1条内容
所有评论(0)