想實作兩個Android設備的USB通信
實驗環境如下:
1、兩個Android手機,紅米(作為host),小米Note(作為accessory);
2、OTG線連host,accessory連usb線,再連接OTG;

參考文章及參考代碼:
https://developer.android.com/guide/topics/connectivity/usb/host.html
https://developer.android.com/guide/topics/connectivity/usb/accessory.html
https://github.com/quandoo/android2android-accessory
目前情況:
可以連接到設備,但是,
host端:
用connection.bulkTransfer(EndPointIn,...)收不到資料,改為通過UsbRequest收資料可以收到;
用connection.bulkTransfer(EndPointOut,...)發送資料一直回傳-1, 用UsbRequst發送資料不會報錯;
accessory端:
mOutStream.write可以發送;
mInStream.read一直阻塞,收不到資料,不明原因,是否還需要更多的協議通信程序? 如何實作呢?
Host代碼
public class UsbHostActivity extends AppCompatActivity {
private UsbManager mUsbManager;
private UsbDevice mDevice;
private List<String> mSendMsgList;// 發送資料串列
private CommunicationThread mCommThread;
private PendingIntent mPermissionIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
//初始化控制元件,點擊按扭呼叫checkDevice連接設備
}
private void initStringControlTransfer(final UsbDeviceConnection deviceConnection,
final int index,
final String string) {
deviceConnection.controlTransfer(0x40, 52, 0, index, string.getBytes(), string.length(), 100);
}
private volatile boolean mExit = false;
private class CommunicationThread extends Thread {
@Override
public void run() {
mExit = false;
UsbEndpoint endpointIn = null;
UsbEndpoint endpointOut = null;
UsbInterface usbInterface = mDevice.getInterface(0);
if (usbInterface == null) {
return;
}
UsbDeviceConnection connection = mUsbManager.openDevice(mDevice);
if (connection == null) {
return;
}
if (!connection.claimInterface(usbInterface, true)) {
connection.close();
return;
}
// 發送控制訊息
initStringControlTransfer(connection, 0, "UsbTest Example"); // MANUFACTURER
initStringControlTransfer(connection, 1, "UsbTest"); // MODEL
initStringControlTransfer(connection, 2, "Test Usb Host and Accessory"); // DESCRIPTION
initStringControlTransfer(connection, 3, "0.1"); // VERSION
initStringControlTransfer(connection, 4, ""); // URI
initStringControlTransfer(connection, 5, "42"); // SERIAL
connection.controlTransfer(0x40, 53, 0, 0, new byte[]{}, 0, 100);
for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
final UsbEndpoint endpoint = usbInterface.getEndpoint(i);
if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
endpointIn = endpoint;
}
if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
endpointOut = endpoint;
}
}
byte buff[] = new byte[256];
while (!mExit) {
final int bytesTransferred = connection.bulkTransfer(endpointIn, buff, buff.length, 100);
if (bytesTransferred > 0) {
//TODO
} else {
//流程一直走在這里,接收資料失敗
}
// 此方式成功收到訊息
//ByteBuffer buffer = ByteBuffer.allocate(256);
//UsbRequest request = new UsbRequest();
//request.initialize(connection, endpointIn);
//boolean ret = request.queue(buffer, 256);
//if (ret) {
// if (mConnection.requestWait() == request) {
// }
//}
synchronized (mSendMsgList) {
if (!mSendMsgList.isEmpty()){
...
int len = connection.bulkTransfer(endpointOut, sendBuff, sendBuff.length, 100);
if (len >= 0) {
//TODO
} else {
//流程一直走在這里,發送失敗
}
// 此方法可以發送,不會回傳錯誤
//UsbRequest request = new UsbRequest();
//request.initialize(mConnection, mEndOut);
//ByteBuffer buffer = ByteBuffer.wrap(text.getBytes());
//boolean ret = request.queue(buffer, text.getBytes().length);
//if (ret) {
//}
}
}
}
...
}
}
private void checkDevice() {
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
if (deviceList == null || deviceList.isEmpty()) {
return;
}
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
mUsbManager.requestPermission(device, mPermissionIntent);
break;
}
}
private static final String ACTION_USB_PERMISSION = "com.mobilemerit.usbhost.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
mDevice = device;
mCommThread = new CommunicationThread();
mCommThread.start();
}
}
}
}
}
};
}
Accessory代碼
public class UsbDeviceActivity extends AppCompatActivity {
private UsbManager mUsbManager;
private UsbAccessory mAccessory;
private ParcelFileDescriptor mFileDescriptor;
private FileInputStream mInStream;
private FileOutputStream mOutStream;
private CommunicationThread mCommThread;
private PendingIntent mPermissionIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
//初始化控制元件,點擊按扭呼叫checkDevice連接設備
}
private void getAccessory() {
UsbAccessory accessory = (UsbAccessory)getIntent().getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null) {
mUsbManager.requestPermission(accessory, mPermissionIntent);
}
}
private volatile boolean mExit;
private class CommunicationThread extends Thread {
@Override
public void run() {
mExit = false;
byte[] msg = new byte[256];
while (!mExit) {
try {
// 阻塞在此處
int len = mInStream.read(msg);
if (len > 0) {
//TODO
} else {
//TODO
}
} catch (final Exception e) {
break;
}
synchronized (mSendMsgList) {
if (!mSendMsgList.isEmpty()){
...
try {
mOutStream.write(sendBuff);// 可以成功發送
} catch (IOException e) {
continue;
}
}
}
}
}
}
private void openAccessory(UsbAccessory accessory) {
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInStream = new FileInputStream(fd);
mOutStream = new FileOutputStream(fd);
if(mInStream == null || mOutStream == null){
return;
}
mCommThread = new CommunicationThread();
mCommThread.start();
}
}
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(accessory != null){
mAccessory = accessory;
openAccessory(mAccessory);
}
}
}
}
}
};
}
uj5u.com熱心網友回復:
你只用了一段OTG線 + USB線是么?uj5u.com熱心網友回復:
@am256341 是的uj5u.com熱心網友回復:
謝謝,我也是用這種方式給POS機分發密鑰uj5u.com熱心網友回復:
請問用OTG+資料線連接兩個手機的時候會有什么提示嗎?比如識別到USB設備之類的?我的插上沒反應,只有一邊是充電狀態(USB除錯狀態)。這正常嗎uj5u.com熱心網友回復:
這個問題有解決嗎 樓主,我也是要 用OTG鏈接2個手機傳輸資料uj5u.com熱心網友回復:
你這個是host主機端的USB通信吧,在host通信方式中有一個Android 設備當做device,設備端的資料讀寫不應該用host端的方式吧,輸入輸出流的獲取應該是直接操作設備節點才對吧,不應該從USB manager獲得……?uj5u.com熱心網友回復:
不好意思才看到,希望你已經解決了。
我的情況是,會有提示,具體什么提示,有點忘記了,大概是是否同意連接之類的,沒提示那應該是不合理的。
uj5u.com熱心網友回復:
這個問題,還沒解決,之后沒在看,有什么想法,可以討論一下。
uj5u.com熱心網友回復:
https://blog.csdn.net/yaohui_/article/details/62435460uj5u.com熱心網友回復:
謝謝
uj5u.com熱心網友回復:
這樣連接可以互傳json資料嗎?應該怎么實作轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/134246.html
標籤:Android
上一篇:如果獲取Button的ID
下一篇:teacher_tab.setup(this.getLocalActivityManager())報空指標,希望各位幫忙看看
