mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-30 09:57:19 +00:00 
			
		
		
		
	README with SerialInputOutputManager for read() and port for write()
test the usually not used read/write variants
This commit is contained in:
		
							parent
							
								
									800381e370
								
							
						
					
					
						commit
						b3631dff58
					
				
							
								
								
									
										67
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								README.md
									
									
									
									
									
								
							| @ -33,9 +33,9 @@ dependencies { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| **2.** Copy [device_filter.xml](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples/src/main/res/xml/device_filter.xml) to your project's `res/xml/` directory. | **2.** If the app should be notified when a device is attached, add  | ||||||
| 
 | [device_filter.xml](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples/src/main/res/xml/device_filter.xml)  | ||||||
| **3.** Configure your `AndroidManifest.xml` to notify your app when a device is attached (see [Android USB Host documentation](http://developer.android.com/guide/topics/connectivity/usb/host.html#discovering-d) for help). | to your project's `res/xml/` directory and configure in your `AndroidManifest.xml`. | ||||||
| 
 | 
 | ||||||
| ```xml | ```xml | ||||||
| <activity | <activity | ||||||
| @ -50,49 +50,50 @@ dependencies { | |||||||
| </activity> | </activity> | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| **4.** Use it! Example code snippet: | **3.** Use it! Example code snippet: | ||||||
| 
 | 
 | ||||||
| ```java | ```java | ||||||
| // Find all available drivers from attached devices. |     // Find all available drivers from attached devices. | ||||||
| UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); |     UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); | ||||||
| List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager); |     List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager); | ||||||
| if (availableDrivers.isEmpty()) { |     if (availableDrivers.isEmpty()) { | ||||||
|         return; |         return; | ||||||
| } |     } | ||||||
| 
 | 
 | ||||||
| // Open a connection to the first available driver. |     // Open a connection to the first available driver. | ||||||
| UsbSerialDriver driver = availableDrivers.get(0); |     UsbSerialDriver driver = availableDrivers.get(0); | ||||||
| UsbDeviceConnection connection = manager.openDevice(driver.getDevice()); |     UsbDeviceConnection connection = manager.openDevice(driver.getDevice()); | ||||||
| if (connection == null) { |     if (connection == null) { | ||||||
|   // You probably need to call UsbManager.requestPermission(driver.getDevice(), ..) |         // add UsbManager.requestPermission(driver.getDevice(), ..) handling here | ||||||
|         return; |         return; | ||||||
| } |     } | ||||||
| 
 | 
 | ||||||
| // Read some data! Most have just one port (port 0). |     UsbSerialPort port = driver.getPorts().get(0); // Most devices have just one port (port 0) | ||||||
| UsbSerialPort port = driver.getPorts().get(0); |  | ||||||
| try { |  | ||||||
|     port.open(connection); |     port.open(connection); | ||||||
|     port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); |     port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); | ||||||
| 
 |     usbIoManager = new SerialInputOutputManager(usbSerialPort, this); | ||||||
|   byte buffer[] = new byte[16]; |     Executors.newSingleThreadExecutor().submit(usbIoManager); | ||||||
|   int numBytesRead = port.read(buffer, 1000); | ``` | ||||||
|   Log.d(TAG, "Read " + numBytesRead + " bytes."); | ```java | ||||||
| } catch (IOException e) { |     port.write("hello".getBytes(), WRITE_WAIT_MILLIS); | ||||||
|   // Deal with error. | ``` | ||||||
| } finally { | ```java | ||||||
|   port.close(); | @Override | ||||||
|  | public void onNewData(byte[] data) { | ||||||
|  |     runOnUiThread(() -> { textView.append(new String(data)); }); | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  | ```java | ||||||
|  |     port.close(); | ||||||
|  | ``` | ||||||
| 
 | 
 | ||||||
| For a simple example, see the | 
 | ||||||
| [UsbSerialExamples project](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples) | For a simple example, see | ||||||
| in git, which is a simple application for reading and showing serial data. | [UsbSerialExamples](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples) | ||||||
|  | folder in this project. | ||||||
| 
 | 
 | ||||||
| For a more complete example, see separate github project  | For a more complete example, see separate github project  | ||||||
| [SimpleUsbTerminal](https://github.com/kai-morich/SimpleUsbTerminal) | [SimpleUsbTerminal](https://github.com/kai-morich/SimpleUsbTerminal). | ||||||
| 
 |  | ||||||
| A [simple Arduino application](https://github.com/mik3y/usb-serial-for-android/blob/master/arduino) |  | ||||||
| is also available which can be used for testing. |  | ||||||
| 
 | 
 | ||||||
| ## Probing for Unrecognized Devices | ## Probing for Unrecognized Devices | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,43 +0,0 @@ | |||||||
| /* Copyright 2012 Google Inc.
 |  | ||||||
|  * |  | ||||||
|  * This library is free software; you can redistribute it and/or |  | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  | ||||||
|  * License as published by the Free Software Foundation; either |  | ||||||
|  * version 2.1 of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This library is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU |  | ||||||
|  * Lesser General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU Lesser General Public |  | ||||||
|  * License along with this library; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, |  | ||||||
|  * USA. |  | ||||||
|  * |  | ||||||
|  * Project home page: http://code.google.com/p/usb-serial-for-android/
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| // Sample Arduino sketch for use with usb-serial-for-android.
 |  | ||||||
| // Prints an ever-increasing counter, and writes back anything
 |  | ||||||
| // it receives.
 |  | ||||||
| 
 |  | ||||||
| static int counter = 0; |  | ||||||
| void setup() { |  | ||||||
|   Serial.begin(115200); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void loop() { |  | ||||||
|   Serial.print("Tick #"); |  | ||||||
|   Serial.print(counter++, DEC); |  | ||||||
|   Serial.print("\n"); |  | ||||||
| 
 |  | ||||||
|   if (Serial.peek() != -1) { |  | ||||||
|     Serial.print("Read: "); |  | ||||||
|     do { |  | ||||||
|       Serial.print((char) Serial.read()); |  | ||||||
|     } while (Serial.peek() != -1); |  | ||||||
|     Serial.print("\n"); |  | ||||||
|   } |  | ||||||
|   delay(1000); |  | ||||||
| } |  | ||||||
| @ -194,22 +194,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | |||||||
|         try { |         try { | ||||||
|             telnetRead(0); |             telnetRead(0); | ||||||
|         } catch (Exception ignored) {} |         } catch (Exception ignored) {} | ||||||
| 
 |         usbClose(); | ||||||
|         try { |  | ||||||
|             usbIoManager.setListener(null); |  | ||||||
|             usbIoManager.stop(); |  | ||||||
|         } catch (Exception ignored) {} |  | ||||||
|         try { |  | ||||||
|             usbSerialPort.setDTR(false); |  | ||||||
|             usbSerialPort.setRTS(false); |  | ||||||
|             usbSerialPort.close(); |  | ||||||
|         } catch (Exception ignored) {} |  | ||||||
|         try { |  | ||||||
|             usbDeviceConnection.close(); |  | ||||||
|         } catch (Exception ignored) {} |  | ||||||
|         usbIoManager = null; |  | ||||||
|         usbSerialPort = null; |  | ||||||
|         usbDeviceConnection = null; |  | ||||||
|         usbSerialDriver = null; |         usbSerialDriver = null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -261,10 +246,15 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | |||||||
| 
 | 
 | ||||||
|     private void usbClose() { |     private void usbClose() { | ||||||
|         if (usbIoManager != null) { |         if (usbIoManager != null) { | ||||||
|  |             usbIoManager.setListener(null); | ||||||
|             usbIoManager.stop(); |             usbIoManager.stop(); | ||||||
|             usbIoManager = null; |  | ||||||
|         } |         } | ||||||
|         if (usbSerialPort != null) { |         if (usbSerialPort != null) { | ||||||
|  |             try { | ||||||
|  |                 usbSerialPort.setDTR(false); | ||||||
|  |                 usbSerialPort.setRTS(false); | ||||||
|  |             } catch (Exception ignored) { | ||||||
|  |             } | ||||||
|             try { |             try { | ||||||
|                 usbSerialPort.close(); |                 usbSerialPort.close(); | ||||||
|             } catch (IOException ignored) { |             } catch (IOException ignored) { | ||||||
| @ -274,6 +264,18 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | |||||||
|         if(usbDeviceConnection != null) |         if(usbDeviceConnection != null) | ||||||
|             usbDeviceConnection.close(); |             usbDeviceConnection.close(); | ||||||
|         usbDeviceConnection = null; |         usbDeviceConnection = null; | ||||||
|  |         if(usbIoManager != null) { | ||||||
|  |             for(int i=0; i<2000; i++) { | ||||||
|  |                 if(SerialInputOutputManager.State.STOPPED == usbIoManager.getState()) break; | ||||||
|  |                 try { | ||||||
|  |                     Thread.sleep(1); | ||||||
|  |                 } catch (InterruptedException e) { | ||||||
|  |                     e.printStackTrace(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             assertEquals(SerialInputOutputManager.State.STOPPED, usbIoManager.getState()); | ||||||
|  |             usbIoManager = null; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void usbOpen(boolean withIoManager) throws Exception { |     private void usbOpen(boolean withIoManager) throws Exception { | ||||||
| @ -520,6 +522,11 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | |||||||
|             usbSerialPort.close(); |             usbSerialPort.close(); | ||||||
|         } catch (IOException ignored) { |         } catch (IOException ignored) { | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         if (usbSerialDriver instanceof Cp21xxSerialDriver) { // why needed? | ||||||
|  |             usbIoManager.stop(); | ||||||
|  |             usbIoManager = null; | ||||||
|  |         } | ||||||
|         // full re-open supported |         // full re-open supported | ||||||
|         usbClose(); |         usbClose(); | ||||||
|         usbOpen(true); |         usbOpen(true); | ||||||
| @ -640,8 +647,8 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | |||||||
|                     assertNotEquals(data1, buf1); |                     assertNotEquals(data1, buf1); | ||||||
|                     assertNotEquals(data2, buf2); |                     assertNotEquals(data2, buf2); | ||||||
|                 } |                 } | ||||||
|                 assertThat("42000/8N1", data1, equalTo(buf1)); |  | ||||||
|             } else { |             } else { | ||||||
|  |                 assertThat("42000/8N1", data1, equalTo(buf1)); | ||||||
|                 assertThat("42000/8N1", data2, equalTo(buf2)); |                 assertThat("42000/8N1", data2, equalTo(buf2)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -1109,4 +1116,85 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | |||||||
| 
 | 
 | ||||||
|         // todo: purge receive buffer |         // todo: purge receive buffer | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     // WriteAsync rarely makes sense, as data is not written until something is read | ||||||
|  |     public void writeAsync() throws Exception { | ||||||
|  |         if (usbSerialDriver instanceof FtdiSerialDriver) | ||||||
|  |             return; // periodically sends status messages, so does not block here | ||||||
|  |         usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|  |         telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|  | 
 | ||||||
|  |         SerialInputOutputManager ioManager; | ||||||
|  |         ioManager = new SerialInputOutputManager(null); | ||||||
|  |         assertEquals(null, ioManager.getListener()); | ||||||
|  |         ioManager.setListener(this); | ||||||
|  |         assertEquals(this, ioManager.getListener()); | ||||||
|  |         ioManager = new SerialInputOutputManager(null, this); | ||||||
|  |         assertEquals(this, ioManager.getListener()); | ||||||
|  | 
 | ||||||
|  |         byte[] data, buf = new byte[]{1}; | ||||||
|  |         int len; | ||||||
|  |         usbIoManager.writeAsync(buf); | ||||||
|  |         usbIoManager.writeAsync(buf); | ||||||
|  |         data = telnetRead(1); | ||||||
|  |         assertEquals(0, data.length); | ||||||
|  |         telnetWrite(buf); | ||||||
|  |         data = usbRead(1); | ||||||
|  |         assertEquals(1, data.length); | ||||||
|  |         data = telnetRead(2); | ||||||
|  |         assertEquals(2, data.length); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     // Blocking read should be avoided in the UI thread, as it makes the app unresponsive. | ||||||
|  |     // You better use the SerialInputOutputManager. | ||||||
|  |     // | ||||||
|  |     // With the change from bulkTransfer to queued requests, the read timeout has no effect | ||||||
|  |     // and the call blocks until close() if no data is available! | ||||||
|  |     // The change from bulkTransfer to queued requests was necessary to prevent data loss. | ||||||
|  |     public void readSync() throws Exception { | ||||||
|  |         if (usbSerialDriver instanceof FtdiSerialDriver) | ||||||
|  |             return; // periodically sends status messages, so does not block here | ||||||
|  | 
 | ||||||
|  |         Runnable closeThread = new Runnable() { | ||||||
|  |             @Override | ||||||
|  |             public void run() { | ||||||
|  |                 try { | ||||||
|  |                     Thread.sleep(100); | ||||||
|  |                 } catch (InterruptedException e) { | ||||||
|  |                     e.printStackTrace(); | ||||||
|  |                 } | ||||||
|  |                 usbClose(); | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         usbClose(); | ||||||
|  |         usbOpen(false); | ||||||
|  |         usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|  |         telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|  | 
 | ||||||
|  |         byte[] buf = new byte[]{1}; | ||||||
|  |         int len; | ||||||
|  |         long time; | ||||||
|  |         telnetWrite(buf); | ||||||
|  |         len = usbSerialPort.read(buf, 0); // not blocking because data is available | ||||||
|  |         assertEquals(1, len); | ||||||
|  | 
 | ||||||
|  |         time = System.currentTimeMillis(); | ||||||
|  |         Executors.newSingleThreadExecutor().submit(closeThread); | ||||||
|  |         len = usbSerialPort.read(buf, 0); // blocking until close() | ||||||
|  |         assertEquals(0, len); | ||||||
|  |         assertTrue(System.currentTimeMillis()-time >= 100); | ||||||
|  | 
 | ||||||
|  |         usbOpen(false); | ||||||
|  |         usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|  |         telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|  | 
 | ||||||
|  |         time = System.currentTimeMillis(); | ||||||
|  |         Executors.newSingleThreadExecutor().submit(closeThread); | ||||||
|  |         len = usbSerialPort.read(buf, 10); // timeout not used any more -> blocking until close() | ||||||
|  |         assertEquals(0, len); | ||||||
|  |         assertTrue(System.currentTimeMillis()-time >= 100); | ||||||
|  |    } | ||||||
| } | } | ||||||
|  | |||||||
| @ -50,7 +50,7 @@ public class SerialInputOutputManager implements Runnable { | |||||||
|     // Synchronized by 'mWriteBuffer' |     // Synchronized by 'mWriteBuffer' | ||||||
|     private final ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ); |     private final ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ); | ||||||
| 
 | 
 | ||||||
|     private enum State { |     public enum State { | ||||||
|         STOPPED, |         STOPPED, | ||||||
|         RUNNING, |         RUNNING, | ||||||
|         STOPPING |         STOPPING | ||||||
| @ -111,7 +111,7 @@ public class SerialInputOutputManager implements Runnable { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private synchronized State getState() { |     public synchronized State getState() { | ||||||
|         return mState; |         return mState; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user