B4A Library UsbSerial library 2.0 - supports more devices

This is an expanded version of the original UsbSerial library. It has added support for Prolific PL2303 USB to serial converters, Android ADK devices and USB permissions. All devices use the same simple interface intended to be used with AsyncStreams and AsyncStreamsText. Note that AsyncStreams prefix mode is not supported. The library is based on the same open source project Android USB host serial driver library as the existing UsbSerial library but no longer needs a separate jar file as the project source code is incorporated in the library.

The specific enhancements to the library over the original UsbSerial library are :

UsbPresent, HasPermission and RequestPermission are added to identify any attached device or Accessory available to the library and deal with permission to access it.

SetParameters, which must be used after Open(), and the constants for SetParameters provides acess to all the serial line parameters instead of just baud rate.

DeviceInfo provides a string containing information about a device. This works for slave devices only.

Android Accessories, which are host mode devices, are recognised and can be used in the same way as the other slave mode devices.

Prolific PL2303 support is added.

Silicon Labs CP210x support is added - maybe only the CP2102 as I have no hardware to test.

The FTDI "status byte" bug on reading input that existed in version 1.0 of this library is hopefully fixed.


The usb-serial-for-android project and therefore also this library is licensed under the GNU Lesser General Public License v3. http://www.gnu.org/licenses/lgpl.html|http://www.gnu.org/licenses/lgpl.html
Copies of both the General Public License and Lesser General Public License are in the provided archive.

The user has to give your application permission to access the USB device before it can be opened. You can do this in two ways.

As with the original UsbSerial library you can add the following code to the manifest editor

B4X:
AddActivityText(main, <intent-filter>
        <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" />)
Then copy device_filter.xml from the demo in the attached archive to: <your project>\objects\res\xml and mark it as read-only. Note that this is an expanded version of the original device_filter.xml file.

Finally install the program and attach the USB device. A dialog will appear asking whether you want to start your program. If you check the “Use by default…” checkbox from now on when the USB device is plugged in your program will be started. If you don’t check the checkbox then you will be asked each time the device is plugged in.

A similar procedure can be used for Accessories as detailed in the “Using an intent filter” section here USB Accessory | Android Developers


Alternatively you can use the new HasPermission and RequestPermission methods without requiring any of the above steps. The demo in the archive incorporates both ways of obtaining permission.

EDIT:- Version 2.1 now posted. See post #4 for details

EDIT:- Version 2.2 now posted. See post #14 for details

EDIT:- Version 2.3 now posted. See post #26 for details

V2.4 is available here: http://www.b4x.com/android/forum/th...pports-more-devices.28176/page-11#post-259167
This update adds support for devices connected to multiple USB adapters.


V2.5 is available as an attachment to this post. It is identical to version 2.4 referenced above but adds the required flag for Pending Intents when targeting SDK 31+.

V2.6 is available as an attachment to this post. It is identical to version 2.5 referenced above but adds the required flag for Pending Intents when targeting SDK 34+.
 

Attachments

  • UsbSerial2.3.zip
    99.2 KB · Views: 6,273
  • UsbSerial2.5.zip
    36.3 KB · Views: 953
  • UsbSerial2.6.zip
    36.3 KB · Views: 101
Last edited:

ralphie911

Member
Licensed User
Longtime User
Hey agraham, what is the best way to connect the android to use this library?

I buy this cable http://www.pcjove.es/eminent-ew1116-cable-usb-a-serie-ew1116.html

and in Windows works perfectly, what I need to connect the Android through this cable, just one OTG Cable is enought?

This this both cables I can use this library?

Thanks

Alberto Iglesias

Hi Alberto,

There is no way of knowing what kind of serial converter chip your adapter uses and therefore, I cannot really answer your question about if your adapter is supported or not. However, I can make a recommendation about a adapter that works 100% for sure as I have been using this for a few years now on many devices.

Here is a link:
http://www.amazon.com/TRENDnet-TU-S...UTF8&qid=1446825631&sr=8-81&keywords=prolific

Yes, you will also need an OTG adapter connected into the HOST port.

I hope this helps.

Ralph
 

ralphie911

Member
Licensed User
Longtime User
Erel asked the question what the RS 232 adapter is connected to.

Answer: Mostly cheap no-brand 7" and 10.1" tablets running android 4.1 - 4.4 but this even works on my Samsung Galaxy phone. In fact I have yet to find an instance where this doesn't work.
 

Creideiki

Active Member
Licensed User
Longtime User
I have an usb opto head which I try to connect to my tablet. DeviceInfo gets
B4X:
Manufacturer : FTD
Product : USB
Serial : not available
DeviceName : /dev/bus/usb/002/007
DeviceClass : USB_CLASS_PER_INTERFACE (per-interface basis)
DeviceSubClass : 0
Device ID : 0x7D7
ProductId : 0x6001
VendorId : 0x403
  B4aInterfaceNumber : 0
  InterfaceClass : USB_CLASS_VENDOR_SPEC (vendor specific)
  InterfaceSubClass : 255
  InterfaceProtocol : 255
  EndpointNumber : 1
  EndpointDirection : In
  EndpointType : USB_ENDPOINT_XFER_BULK (bulk)
  EndpointAttribute : 2
  EndpointInterval : 0
  EndpointMaxPacketSize : 64
  EndpointNumber : 2
  EndpointDirection : out
  EndpointType : USB_ENDPOINT_XFER_BULK (bulk)
  EndpointAttribute : 2
  EndpointInterval : 0
  EndpointMaxPacketSize : 64
It seems to be an FTDI FT232; Linux assumes it's an FT232BM.

I can access it, open it, send data. But when I receive data, I get errors like
java.lang.NullPointerException and java.io.IOException: Expected at least 2 bytes.

Am I right that that's a driver problem? Is there anything I can do to make it work with the usbserial library (apart from getting the exact docu and implementing it myself)?
 

koffie

Member
Licensed User
Longtime User
Does the 2.4 library already support the CH341 ?
There seems to be an USBserial library JAVA lib with the CH341 supported.
I do see a lot of questions about the CH341, but no updates on the availability in B4a so I expect the worst :(

I bought cheapo arduino nanos and ...you guessed it.

Is there a simple solution to just send and receive a few bytes of text between an arduino and B4A, without buying other stuff like FTDI ?

Thanks,
 

Abílio Magalhães

Member
Licensed User
Longtime User
Hi Agraham,

I tried to use your library but I always get error when open(9600,1) serial comm.

I jump to Java (Android Studio) and I'm already printing to my ticket printer using 3rd part usbserial library (http://felhr85.net/2014/11/11/usbserial-a-serial-port-driver-library-for-android-v2-0/)

It is possible to use your library? Do you have any update to your library? Where are any way to understand why open() is failing? Some logs?

Regards,
Abilio
 

Abílio Magalhães

Member
Licensed User
Longtime User
Hi,

I'm, trying to use usbserial with two USB ticket printers. Our app works perfectly with ethernet and bluetooth ticket printers but it is completely blocked to print to usb printers.

We have always the same error from 2.4 usbserial library: "Error opening USB port 1".

Outside B4A, we have successfully printing with Android Studio but we need to use B4A. Now we don't have time to recode the entire app in java. We really need to do it in B4A.

It is possible to request to B4A team an implementation of this library (http://felhr85.net/2014/11/11/usbserial-a-serial-port-driver-library-for-android-v2-0/)?

Or it is possible to insert inside usbserial some debug logs so we can understand what can be happen?

How can B4A team help us?

Regards,
Abilio
 

Abílio Magalhães

Member
Licensed User
Longtime User
Hi Erel,

Here is the complete and working example

I'm using this library:
https://github.com/felHR85/UsbSerial

This is the manifest:
<code>
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.a486software.abilio.printusb">
<applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-dataandroid:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"android:resource="@xml/device_filter" />
</activity>
</application>
</manifest>
</code>


And this is the entire MainActivity.java, printing from tablets and smartphones:

<code>
package com.a486software.abilio.printusb;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import com.felhr.usbserial.UsbSerialDevice;
import com.felhr.usbserial.UsbSerialInterface;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity implements View.OnClickListener {

public final String ACTION_USB_PERMISSION = "com.a486software.abilio.printusb.USB_PERMISSION";
private Button btnStart;
private Button btnPrint;

UsbManager usbManager;
UsbDevice device;
UsbSerialDevice serialPort;
UsbDeviceConnection connection;
int comm_open;

@Overrideprotected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout ll = new LinearLayout(this);
// // Interface // // Start buttonbtnStart = new Button(this);
btnStart.setText("Start Comm");
btnStart.setX(100);
btnStart.setY(100);
btnStart.setId(1);
btnStart.setOnClickListener(this);

// Print buttonbtnPrint = new Button(this);
btnPrint.setText("Print");
btnPrint.setX(100);
btnPrint.setY(250);
btnPrint.setId(2);
btnPrint.setOnClickListener(this);

ll.addView(btnStart);
setContentView(ll);
ll.addView(btnPrint);
setContentView(ll);

// // Comm //comm_open = 0;
usbManager = (UsbManager) getSystemService(this.USB_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(broadcastReceiver, filter);


}

@Overridepublic void onClick(View v) {
System.out.println("ON LICK");
switch(v.getId()) {
case 1: // Start commStartComm();
break;
case 2: // Print!String string = "Hello USB ticket printer\n";
serialPort.write(string.getBytes());
System.out.println("Data Sent : " + string + "\n");
break;
default: // No buttonSystem.out.println("Button ??");
}
}
// // Handle device answer //UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
//Defining a Callback which triggers whenever data is read.@Overridepublic void onReceivedData(byte[] arg0) {
System.out.println("UsbReadCallback");
String data = null;
try {
data = new String(arg0, "UTF-8");
data.concat("/n");
System.out.println("Answer from device:" + data);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}


}
};
// // Handle broadcast //private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
//Broadcast Receiver to automatically start and stop the Serial connection.@Overridepublic void onReceive(Context context, Intent intent) {
Log.d("SERIAL", "onReceive");
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted = intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
if (granted) {
Log.d("SERIAL", "granted");
connection = usbManager.openDevice(device);
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort.open()) { //Set Serial Connection Parameters. //setUiEnabled(true);serialPort.setBaudRate(9600);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
comm_open = 1;
Log.d("SERIAL", "Serial Connection Opened!");

} else {
Log.d("SERIAL", "PORT NOT OPEN");
}
} else {
Log.d("SERIAL", "PORT IS NULL");
}
} else {
Log.d("SERIAL", "PERM NOT GRANTED");
}
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
StartComm();
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
StopComm();

}
}

;
};
// // Start comm //private void StartComm() {
Log.d("SERIAL", "START COMM");
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
if (!usbDevices.isEmpty()) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
Log.d("SERIAL", "deviceVID:" + deviceVID);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, pi);
// Uses first USB device - for me is fine ;)
}
}
}
// // CLoses serial comm //private void StopComm() {
Log.d("SERIAL", "STOP COMM");
if(comm_open ==1) {
serialPort.close();
}
comm_open = 0;
}
}
</code>



I would like to have a library without an Activity, so i can use it in background and inside any B4A activity.

Can you send me some tips how to do it?

Kind regards,
Abilio
 

Abílio Magalhães

Member
Licensed User
Longtime User
Hi Erel,

This is the complete Android Studio 2.0 project.

I'm getting an error (picture) when trying to create the Activity.

I think my manifest is correct.

If possible can you help me?

Kind regards,
Abilio
 

Attachments

  • library_PrintuSB_with_source.zip
    118.6 KB · Views: 306
  • B4A_example.zip
    404.9 KB · Views: 340
  • error_when_create_activity.jpg
    error_when_create_activity.jpg
    102.6 KB · Views: 305
Last edited:

Devv

Active Member
Licensed User
Longtime User
Thanks for this nice library



I'm trying to receive data from Arduino to Android device
void setup()
{
Serial.begin(115200);
}

void loop()
{
byte msg[64];
int len;
len = Serial.available();
if (len > 0)
{
len = Serial.readBytes((char*)msg, sizeof(msg)); // readBytes seems to need a char* not a byte*
Serial.write(msg, len);
}
}

i tried that example and it is working perfectly!

but when i put Serial.write("3"); in the setup loop after Serial.begin(115200); it appears as question mark on my android device, i guess that I'm not sending it as a byte , i searched online but with not luck


any ideas ?
 

secilcemal

Member
Licensed User
Longtime User
Hi,
I am working with B4a and with this library for some times, they are perfect tools for me to create a cnc marking machine.
What i can not figure out is;
For my application i send more than 1500 bytes to a micro controller.
What i want to impliment is the reading process into a for loop that sends the data to micro controller.
So after sending 500 byte it will wait the signal from microcontroller to go on.
When i add the line "ReceivedByte = BytesToString(Buffer, 0, Buffer.Length, "UTF8")" into the for loop
it gives me the error that "undeclared variable buffer is used before assigned any value".
Would you please tell me the proper way to use it.
Thanks.
 

Toley

Active Member
Licensed User
Longtime User
Does the library already support the microchip MCP2221 ?
Personally I would say that it can be done. I have successfully connect some microchip MCU that enumerate a CDC device. You just need to edit the .xml file and add your PID/VID. But don't forget the xml file is and must be read only.
 

JeanLC

Member
Licensed User
Longtime User
From Microchip site: MCP2221 -> Communication Device Class (CDC) for communications and configuration
So...if the device is Compatible, you could use this from the library:
SetCustomDevice(int driverID, int vendorID, int productID)
/**
*If a device might be supported by an existing driver in this library but is not recognised
*then it can be added by this method.
*
*The driverID parameter can be one of
*
*DRIVER_PROLIFIC for a device that is compatible with the Prolific PL2303.
*DRIVER_SILABS for a device that is compatible with the Silicon Labs CP2102
*DRIVER_CDCACM for a device that is compatible with the CDC ACM model.
*DRIVER_FTDI for a device that is compatible with the FTDI FT232.
*
*DRIVER_NONE can be used in the unlikely event of needing to unrecongise a device
*
*The vendorID and productID parameters are those of the device in question.
*/
 
Top