I have been trying to follow this tutorial to read data output from my arduino using my android phone, they are connected via OTG.
https://code.google.com/p/usb-serial-for-android/
I am able to print the result in a text view, however the output is 0. This is the code snippet I am using:
// Get UsbManager from Android.
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
// Find the first available driver.
UsbSerialDriver driver = UsbSerialProber.acquire(manager);
if (driver != null) {
driver.open();
try {
driver.setBaudRate(115200);
byte buffer[] = new byte[16];
int numBytesRead = driver.read(buffer, 1000);
Log.d(TAG, "Read " + numBytesRead + " bytes.");
} catch (IOException e) {
// Deal with error.
} finally {
driver.close();
}
}
My error might be relating to driver.read, can't find much documentation on it. Any thoughts on how the data get's pulled from the Arduino through serial in this method? If not, better ways to do it?
Thanks!
Arun
Related
We are experimenting with a bunch of new tablets, and every one we tried is having issues with slow transfer rates with the RN4678 board. We currently use the Lenovo M10 FHD Plus. We tried a few such as the Teclast M40S, Nokia T20, and Samsung Galaxy Tab A8. The first two had horrible transfer rates, while the latter was okay but not ideal. We cannot use the Lenovo M10 Plus 3rd Gen because the buttons are too close to the corner to use with our tablet holders.
Here is my code:
public void SendMessage(BluetoothSocket socket, String msg) {
OutputStream outStream;
try {
outStream = BluetoothConnectionService.outputStream;
outStream.write("S".getBytes());
Thread.sleep(4000);
processThread = true;
mApp.running = true;
BluetoothSocketListener bsl = new BluetoothSocketListener(socket,
CollectingDetail.this);
Thread messageListener = new Thread(bsl);
messageListener.start();
timer = new CounterClass(remaingTime, 1000);
timer.start();
bt_stop.setText("Stop");
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(bluetoothReceiver, filter);
bluetoothReceiver.setRegistered(true);
} catch (IOException | InterruptedException e) {
Log.e("BLUETOOTH_COMMS", e.getMessage());
connectSocket();
}
}
public static class BluetoothSocketListener implements Runnable {
private final WeakReference<CollectingDetail> wrActivity;
private BluetoothSocket socket;
public BluetoothSocketListener(BluetoothSocket socket, CollectingDetail collectingDetail) {
this.socket = socket;
wrActivity = new WeakReference<CollectingDetail>(collectingDetail);
}
#Override
public void run() {
final CollectingDetail activity = wrActivity.get();
if (activity != null) {
activity.inStream = null;
if (!Thread.currentThread().isInterrupted()) {
int bufferSize = 512;
byte[] buffer = new byte[bufferSize];
Log.i("Bluetooth bytes", new String(buffer));
activity.inStream = BluetoothConnectionService.inputStream;
int availableBytes;
int bytesRead = -1;
String message = "";
while (activity.processThread) {
message = "";
try {
availableBytes = activity.inStream.available();
if (availableBytes > 0) {
bytesRead = activity.inStream.read(buffer);
if (bytesRead != -1 && bytesRead < bufferSize) {
message = new String(buffer, 0, bytesRead);
if (activity.mainHandler != null) {
activity.mainHandler.post(new MessagePoster(message, activity));
}
}
}
} catch (IOException e) {
Log.e("BLUETOOTH_COMMS", "Error reading bytes");
try {
socket.close();
} catch (IOException e1) {
Log.e("BLUETOOTH_COMMS", "Could not close socket");
}
activity.processThread = false;
}
}
}
}
}
}
public void seprateData(String message) {
try {
message = message.replaceAll("(\\r\\n|\\n|\\r)", ",");
String[] a = message.split(",");
boolean goodData = false;
for (int i = 0; i < a.length; i++) {
final String data = a[i];
if (data.length() > 0 && !data.equals(" ")) {
if (data.length() >= 10 && data.startsWith("5A")) {
al_sepratedMessageList.add(data);
goodData = true;
}
}
}
if (goodData) {
calculation();
if (ConnectThrough.equalsIgnoreCase("usb")) {
UsbConnectionSerivce.sendMessage("K");
} else {
BluetoothConnectionService.sendMessage(socket, "K");
}
}
} catch (Exception e) {
Log.e("BiSym", "Error Parsing BiSym Data");
}
}
Is there any way we can increase the transfer rate without changing the firmware? It appears others have faced similar problems, but none of the answers have a real solution. Could you please help me out. Thanks.
I fear this may not be software-solvable and may be an issue with BT hardware or firmware. How would I communicate with my boss about this?
I fear this may not be software-solvable and may be an issue with BT hardware or firmware. How would I communicate with my boss about this?
The difference is in the quality of the filtering of the signal, a better filter, narrower bandwidth, means lower Signal to Noise Ratio. Lower SNR means faster transfer.
Better analog filters, mean more components and slightly more cost and loss, however, due to the wide-band nature of Bluetooth, most analog filters can only filter out of band signals (nearby AM/FM/TV broadcasters).
In addition to the analog filters, digital filters are applied to the signal to narrow the bandwidth within the band, this technique incurs little loss, but requires more processing power to be included in the chip, more transistors, more costs.
The order of the filter and the type FIR or IIR determine the characteristics of the filer.
Most designers will minimize the cost to meet the minimum specifications, some will balance the cost versus performance and go further, you never know.
You tell your boss, the the better platforms perform digital filtering well beyond what the Bluetooth specification requires.
I just tested the Teclast M40 Plus which doesn't have this problem.
Something wants to make me believe it is an issue with the UNISOC Bluetooth stack. The Teclast M40 Plus has MediaTek which doesn't have this issue.
EDIT: Also tested on Lenovo M10 Plus 3rd Gen with MediaTek Helio G80, no issue. If we have to use it, we may need a new tablet holder.
Have you repeated the tests? Bluetooth uses the same frequencies as 2.4 GHz Wifi and microwave ovens. In a congested Wifi environment, and/or too many Bluetooth connections(mice, keyboards, headphones, speakers, watches ...), slowdowns are normal for high-speed transfers.
Wifi 6 MIMO utilizes all three distinct channels in the 2.4G band, (1,6,11) of the 12 overlapping. Higher bandwidth/speeds are available in 5.4G (and above), but wall penetration and signal propagation factors keep 2.4G as the primary band in the absence of other possibilities.
There is only so much space in the 2.4G band that Bluetooth operates.
Repeat your tests in an area without interference and see if you get the same results.
A cheap isolation method is to build a Faraday Cage out of .25 inch chicken wire fencing. Isolate the sender and receiver inside of the cage and measure the throughput.
In an uncontrolled environment, hundreds to thousands of tests for each device are required across different time spans to establish a true baseline measurement. You never know when you neighbor is going to start or stop a variable bit-rate video, or move a mouse.Every action contributes to the background noise in the band.
I am trying to establish Bluetooth connection between an Android device with other mobile phone over Handsfree profile. I am using following code -
private static final UUID MY_UUID = UUID.fromString("0000111F-0000-1000-8000-00805F9B34FB"); // UUID for Hands free profile
// Some code...
// Get Bluetooth Adapter.
m_oBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// Some code...
// For paired BT device, getting a connection established.
if(null != m_oBluetoothDevice)
{
if(BluetoothDevice.BOND_BONDED == m_oBluetoothDevice.getBondState())
{
try
{
m_oBluetoothSocket = m_oBluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
m_oBluetoothSocket.connect();
Log.i(TAG, "Socket Connected");
}
catch(Exception e)
{
if(null != m_oBluetoothSocket)
{
Log.i(TAG, "Closing socket");
try
{
m_oBluetoothSocket.close();
}
catch (Exception e1)
{
Log.i(TAG, "Error while closing socket : " + e1.getMessage());
}
}
}
}
}
I can create RFCOMMSocket using this code.
Now I want to send AT commands based on Bluetooth Hands-Free profile. e.g. If other mobile phone receives a phone call, my Android device can reject this call by sending AT command- "+CHUP". I am not sure whether this is possible or not.
At this point, I am stuck. I have read Bluetooth APIs where I found -
BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT
Can we use this Intent for sending AT commands? Is this a proper way to send AT command based on Bluetooth Hands-Free profile? Please someone help me out and give me proper direction.
Any input from you all will be great help for me.
Thanks in advance.
You need to create InputStream and OutputStream so you can talk to the phone:
mmInStream = m_oBluetoothSocket.getInputStream();
mmOutStream = m_oBluetoothSocket.getOutputStream();
To setup the HFP connection you start to send:
mmOutStream.write("AT+BRSF=20\r".getBytes());
Where 20 is code for what you support of HFP.
And to read from the phone:
buffer = new byte[200];
mmInStream.read(buffer);
command = new String(buffer).trim();
So now you can talk beetwen the devices and you can read more about the Handsfree profile on https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=238193
Adding reference to AT commnads
http://forum.xda-developers.com/showthread.php?t=1471241
http://www.zeeman.de/wp-content/uploads/2007/09/ubinetics-at-command-set.pdf
I am trying to make application for reading external storage file system connected using OTG cable to XOOM with ICS.
i am using this code to determine IN and OUT endpoint for communication with flash device
final UsbDeviceConnection connection = manager.openDevice(device);
UsbInterface inf = device.getInterface(0);
if (!connection.claimInterface(inf, true)) {
Log.v("USB", "failed to claim interface");
}
UsbEndpoint epOut = null;
UsbEndpoint epIn = null;
// look for our bulk endpoints
for (int i = 0; i < inf.getEndpointCount(); i++) {
UsbEndpoint ep = inf.getEndpoint(i);
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
epOut = ep;
} else {
epIn = ep;
}
}
}
if (epOut == null || epIn == null) {
throw new IllegalArgumentException("not all endpoints found");
}
final UsbEndpoint inEndPoint = epIn;
it works normal.
then i am trying to read first 512 bytes to get FAT32 boot sector
ByteBuffer arg1 = ByteBuffer.allocate(512);
UsbRequest request = new UsbRequest();
request.initialize(connection, inEndPoint);
request.queue(arg1, inEndPoint.getMaxPacketSize());
UsbRequest result = connection.requestWait(); // halt here
connection.releaseInterface(inf);
connection.close();
but it does not read any data from connected device.
all this code run on separate thread after granding permission on device
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(USBHostSampleActivity.this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
manager.requestPermission(lDevices.get(position),mPermissionIntent);
in Broadcast receiver i just start new thread with previous code;
i also tried to make call to
USBDeviceConnection.controlTransfer
byte[] b = new byte[0x10];
int cTransfer = connection.controlTransfer(128, 6, 16, 0,b, 12, 0);
like in libusb sample to get f0 data and/or hwstats but it always return -1
also i tried replace async request using USBRequst to sync bulkTransfers but result is the same.
Have anyone worked with this part of Android SDK?
Thanks!
It appears you are missing a whole protocol layer; you can't just read 512 bytes from the device. What should it send back? How could it know you want to start to read at the beginning of the disk?
How you actually read a memory location from USB-MSC device depends on the device sub class type and the supported transport protocol.
It is likely that an ordinary flash disk uses the SCSI transparent command set in conjunction with the USB Mass Storage Class Bulk-Only (BBB) Transport.
You have to examine the device descriptor to find out what your device supports. See also the MSC device class overview for all possible values and references to their documentation.
I wrote a library for that called libaums: https://github.com/mjdev/libaums
The library takes care of low level USB communication and implements the FAT32 file system. It also includes an example app. Listing a directory would work as follows:
UsbMassStorageDevice[] devices = UsbMassStorageDevice.getMassStorageDevices(this);
device.init();
// we only use the first device
device = devices[0];
// we always use the first partition of the device
FileSystem fs = device.getPartitions().get(0).getFileSystem();
Log.d(TAG, "Capacity: " + fs.getCapacity());
Log.d(TAG, "Occupied Space: " + fs.getOccupiedSpace());
Log.d(TAG, "Free Space: " + fs.getFreeSpace());
UsbFile root = fs.getRootDirectory();
for(UsbFile f : root.listFiles())
Log.d(TAG, f.getName())
i want to make a modification to my project and right now the project status is.....
it is searches the available WiFi networks and shows the list with info of the network this works properly.Now i want to search and see the details of the devices connected to the network.
Is there any way to find these devices ?
Your comment will be useful for me, Thanks.
You can loop over the IP ranges, and "ping" them.
It is not the best / fastest method (UDP is better) but, it works in many cases.
The sample code below returns the list of the IP addresses connected to the current network.
private int LoopCurrentIP = 0;
public ArrayList<InetAddress> getConnectedDevices(String YourPhoneIPAddress) {
ArrayList<InetAddress> ret = new ArrayList<InetAddress>();
LoopCurrentIP = 0;
String IPAddress = "";
String[] myIPArray = YourPhoneIPAddress.split("\\.");
InetAddress currentPingAddr;
for (int i = 0; i <= 255; i++) {
try {
// build the next IP address
currentPingAddr = InetAddress.getByName(myIPArray[0] + "." +
myIPArray[1] + "." +
myIPArray[2] + "." +
Integer.toString(LoopCurrentIP));
// 50ms Timeout for the "ping"
if (currentPingAddr.isReachable(50)) {
ret.add(currentPingAddr);
}
} catch (UnknownHostException ex) {
} catch (IOException ex) {
}
LoopCurrentIP++;
}
return ret;
}
Would you like to discover a specific device ? Or you need the list of all connected devices? The second I don't think is possible.
EDIT
Discovering specific devices:
Using UDP Broadcast. Some reference can be found here!
There are some protocols that are supported by some devices( routers, HDD, etc...), like UPNP!
If you develop a software on the device which you would like to discover you could create a UDP server listening on a specific port.
Your client will just send a broadcast message on that port and your Server will send a response with the information you need.
Here it is a simple example.
I want to simulate the action of going throgh Settings->Wireless->Bluetooth and connect a paired bluetooth headset programmatically. I've done some search in Stackoverflow and Google, both indicating that there is no solution available before API level 11. However, I'm interested in working it out by peeking in the source code of bluetooth implementation of Android. The problem is that I'm not aware of which specific source code I should review. Any suggestions? Many thanks.
After days of struggling, I've now managed to do it, cheers :)
Add android.bluetooth.IBluetoothA2dp.aidl in your /src dir of your app;
Add this private method in your code:
private IBluetoothA2dp getIBluetoothA2dp() {
IBluetoothA2dp ibta = null;
try {
Class c2 = Class.forName("android.os.ServiceManager");
Method m2 = c2.getDeclaredMethod("getService", String.class);
IBinder b = (IBinder) m2.invoke(null, "bluetooth_a2dp");
Log.d("Felix", "Test2: " + b.getInterfaceDescriptor());
Class c3 = Class.forName("android.bluetooth.IBluetoothA2dp");
Class[] s2 = c3.getDeclaredClasses();
Class c = s2[0];
// printMethods(c);
Method m = c.getDeclaredMethod("asInterface", IBinder.class);
m.setAccessible(true);
ibta = (IBluetoothA2dp) m.invoke(null, b);
} catch (Exception e) {
Log.e("flowlab", "Erroraco!!! " + e.getMessage());
}
Test it with this:
private void testBluetoothA2dp(BluetoothDevice device) {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
IBluetoothA2dp ibta = getIBluetoothA2dp();
try {
Log.d("Felix", "Here: " + ibta.getSinkPriority(device));
ibta.connectSink(device);
} catch (RemoteException e) {
// * TODO Auto-generated catch block
e.printStackTrace();
}
}
I'm not able to provide references of these code since I've spent lots of time googling, checking out stackoverflow, and reviewing Android source code, but failed to keep track of sources. Many thanks to you guys in Stackoverflow :)
OK, I got this updated to support Honeycomb and up. You need to add new functions to the interface. I did that here:
interface IBluetoothA2dp {
boolean connectSink(in BluetoothDevice device); // Pre API 11 only
boolean disconnectSink(in BluetoothDevice device); // Pre API 11 only
boolean connect(in BluetoothDevice device); // API 11 and up only
boolean disconnect(in BluetoothDevice device); // API 11 and up only
boolean suspendSink(in BluetoothDevice device); // all
boolean resumeSink(in BluetoothDevice device); // all
BluetoothDevice[] getConnectedSinks(); // change to Set<> once AIDL supports, pre API 11 only
BluetoothDevice[] getNonDisconnectedSinks(); // change to Set<> once AIDL supports,
int getSinkState(in BluetoothDevice device);
boolean setSinkPriority(in BluetoothDevice device, int priority); // Pre API 11 only
boolean setPriority(in BluetoothDevice device, int priority); // API 11 and up only
int getPriority(in BluetoothDevice device); // API 11 and up only
int getSinkPriority(in BluetoothDevice device); // Pre API 11 only
boolean isA2dpPlaying(in BluetoothDevice device); // API 11 and up only
}
Then you need to check the API version before calling functions in this interface. Here is my example:
if (android.os.Build.VERSION.SDK_INT < 11) {
IBluetoothA2dp ibta = getIBluetoothA2dp();
try {
Log.d(LOG_TAG, "Here: " + ibta.getSinkPriority(device));
if (ibta != null)
ibta.connectSink(device);
} catch (Exception e) {
Log.e(LOG_TAG, "Error " + e.getMessage());
}
} else {
IBluetoothA2dp ibta = getIBluetoothA2dp();
try {
Log.d(LOG_TAG, "Here: " + ibta.getPriority(device));
if (ibta != null)
ibta.connect(device);
} catch (Exception e) {
Log.e(LOG_TAG, "Error " + e.getMessage());
}
}
Hope this helps. I was able to get the same app to work with both interfaces.
I tried this on Android 4.2
and following line returns null.
It was working on 4.1, any ideas ?
IBinder b = (IBinder) m2.invoke(null, "bluetooth_a2dp");
this is KIND of related to the connect/reconnect issue (the ANSWER being an apple script) ..
i just bought an android htc one V and am using it as a hotspot via the app PdaNet (installed both on my phone and my mac os 10.5.8 ppc laptop).
I can't seem to get the hotspot tethering working via wifi or usb but it DOES work well with BLUETOOTH! only problem is the connection only lasts up to 2 minutes to 40 minutes (looking at it now ha, a record) and i have to reconnect manually, which only takes 2 seconds but it'd be nice if the Network aspect of my mac could AUTO reconnect.
my cell is not the problem as it's sending out a constant signal (although i could be losing signal temporarily from my cell, which is normal connection stuff) .. the problem is having my laptop auto RE-connect. my laptop and htc one v DO remain paired, there's just no AUTO-RECONNECT on the laptop end.
i wish i knew apple scripts bcs then i could maybe write an apple script that AUTO-RECONNECTS a lost bluetooth connection .. or maybe a widget could do this? if so i'd have it made in the shade as bluetooth tethering is working NICELY.
i was hoping this would help both myself and others searching for the same answers .. if you keep this thread open i could return later with some possible apple script solutions (which i will have to quickly learn) .. thanks -marcus