In my Android app, I read the values from a 3DConnexion SpaceNavigator via USB-OTG to control an AR.Drone.
Now I want to do the same with a mouse. However, Android is grabbing the mouse and presenting a mouse-cursor. When I write a device-filter with the vendor and product ID of the mouse, I do not get it like with the SpaceNavigator (strangely, both are HID -- I get no cursor with the SpaceNavigator).
Is there a way to get the raw mouse data without the cursor?
Would be perfect with stock Android. but I would also consider altering the ROM for that.
As soon as your Application claims the Mouse (as a USB HID device while being Host), Android should hide the cursor and you can read the raw data. This should work on stock android, but your device has to support USB Host mode and a USB OTG cable will be needed to connect the mouse.
Basic procedure:
enumerate devices
ask for permission to access the USB device
claim the device
read a data package from the HID endpoint
parse the X and Y position, button clicks and scroll wheel rotation from the data package
Example Code that works for me (Android 5.0):
UsbManager usbManager;
UsbDevice usbDevice;
private void connect() {
this.usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
// just get the first enumerated USB device
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
if (deviceIterator.hasNext()) {
this.usbDevice = deviceIterator.next();
}
if (usbDevice == null) {
Log.w(TAG, "no USB device found");
return;
}
// ask for permission
final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
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){
// call method to set up device communication
Log.i(TAG, "permission granted. access mouse.");
// repeat in a different thread
transfer(device);
}
}
else {
Log.d(TAG, "permission denied for device " + device);
}
}
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
// TODO:
// call your method that cleans up and closes communication with the device
// usbInterface.releaseInterface();
// usbDeviceConnection.close();
}
}
}
};
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
context.registerReceiver(mUsbReceiver, filter);
usbManager.requestPermission(usbDevice, mPermissionIntent);
}
private void transfer(UsbDevice device) {
int TIMEOUT = 0;
boolean forceClaim = true;
// just grab the first endpoint
UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
UsbDeviceConnection connection = this.usbManager.openDevice(device);
connection.claimInterface(intf, forceClaim);
byte[] bytes = new byte[endpoint.getMaxPacketSize()];
connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT);
// depending on mouse firmware and vendor the information you're looking for may
// be in a different order or position. For some logitech devices the following
// is true:
int x = (int) bytes[1];
int y = (int) bytes[2];
int scrollwheel = (int) bytes[3]
// call a listener, process your data ...
}
Related
I can detect whether the OTG cable attached or detached. But how to detect if OTG cable already connected when app runs. My app only detects if otg cable attached or detached.
public class BootUpReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e("USB", "Decive Connected -> " + action);
if (action.equalsIgnoreCase(ACTION_USB_ATTACHED)) {
UsbDevice device = (UsbDevice) intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
int vendorID = device.getVendorId();
int productID = device.getProductId();
//If Product and Vendor Id match then set boolean "true" in global variable
tv_otg.setText("External OTG storage device connected !");
Log.e("true", "true");
}
} else if (action.equalsIgnoreCase(ACTION_USB_DETACHED)) {
//When ever device Detach set your global variable to "false"
tv_otg.setText("External OTG storage device disconnected !");
Log.e("ACTION_USB_DETACHED", "ACTION_USB_DETACHED");
}
}
}
bootupreceiver = new BootUpReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_ATTACHED);
filter.addAction(ACTION_USB_DETACHED);
filter.setPriority(100);
registerReceiver(bootupreceiver, filter);
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
UsbDevice device = deviceIterator.next();
//your code for check device check name logic
}
Check DOC
I am struggling on how to capture the audio stream from connected USB microphone. I have tried to use the MediaCapture with MediaRecorder.AudioSource.MIC as source which worked but recording quality isn't quite usable for me and you can't be sure if the audio source is really USB or the built in device microphone. What I need is to use the USB audio feature but so far I am unable to make any progress.
To use third-party libraries is overkill for me since I need to only receive the stream of audio data from the microphone, the rest of the processing is already done and working, only the audio source is the issue.
What I need to do is:
Check if there is USB microphone connected to the device.
Find out what characteristics this device has (supported sampling rates, channels etc.)
Record audio data
What I've done so far:
Generate a list of connected USB device which class is UsbConstants.USB_CLASS_AUDIO
private static final String ACTION_USB_PERMISSION = PACKAGE_NAME + ".USB_PERMISSION";
private UsbManager mUsbManAndroid;
private Map<String, UsbDevice> mAndroidDeviceMap;
private PendingIntent mPermissionIntent;
private ArrayList<UsbDeviceListItem> getUSBDevicesList() {
// Enumerate USB devices
mAndroidDeviceMap = mUsbManAndroid.getDeviceList();
ArrayList<UsbDeviceListItem> usbDevicesList = new ArrayList<>();
for (String key : mAndroidDeviceMap.keySet()) {
UsbDevice device = mAndroidDeviceMap.get(key);
// Check the device class
if (device.getDeviceClass() == UsbConstants.USB_CLASS_AUDIO) {
usbDevicesList.add(usbDeviceToListItem(key, device));
} else if (device.getDeviceClass() == UsbConstants.USB_CLASS_PER_INTERFACE) {
UsbInterface interface;
for (int i = 0; i < device.getInterfaceCount(); i++) {
// Check if at least one interface is audio
interface = device.getInterface(i);
if (interface != null && interface.getInterfaceClass() == UsbConstants.USB_CLASS_AUDIO) {
usbDevicesList.add(usbDeviceToSysBusUsbDevice(key, device));
break;
}
}
}
}
/////////////////////////////////////////////////////////
// Here goes some code to identify the device using
// linux shell commands if device SDK version is older
// than 21 (Lollipop). In older versions of Android
// we can't get device's Vendor and Device names using
// Android API, we need to use some linux shell commands.
/////////////////////////////////////////////////////////
return usbDevicesList;
}
Request permission for selected usb device from the list:
mUsbDeviceList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
UsbDeviceListItem usbDeviceItem = (UsbDeviceListItem) mUsbDeviceList.getItemAtPosition(i);
UsbDevice device = mAndroidDeviceMap.get(usbDeviceItem.getDevicePath());
manager.requestPermission(device, mPermissionIntent);
}
});
Permission broadcast receiver:
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 = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
streamFromUsbDevice(device)
}
}
else {
Toast.makeText(SensorActivity.this, "Permission denied for device " + device,
Toast.LENGTH_SHORT).show();
}
}
}
}
};
Sample method for reading data from the USB device
private void streamFromUSBDevice(UsbDevice device) {
UsbEndpoint endpoint;
UsbInterface usbInterface;
////////////////////////////////////////////////////////////////
// Here was code for finding the first audio interface with its
// endpoint. But because I failed to make it work I was manually
// getting them by index.
////////////////////////////////////////////////////////////////
usbInterface = device.getInterface(2);
endpoint = usbInterface.getEndpoint(0);
if (endpoint == null) {
Log.i(TAG, getString(R.string.endpoint_not_found));
notifyUser(R.string.endpoint_not_found);
return;
}
Log.i(TAG, R.string.connecting_to_usb_device);
notifyUser(R.string.connecting_to_usb_device);
UsbDeviceConnection connection = manager.openDevice(device);
connection.claimInterface(usbInterface, true);
while (true) {
if (!isRecording) {
// Close the connection to the usb device
connection.close();
notifyUser(R.string.status_idle);
break;
}
UsbRequest request = new UsbRequest();
request.initialize(connection, endpoint);
byte[] buffer = new byte[endpoint.getMaxPacketSize()];
final ByteBuffer buf = ByteBuffer.wrap(buffer);
Log.i(TAG, "Requesting queue...");
if (!request.queue(buf, buffer.length)) {
Log.e(TAG, getString(R.string.error_queue_request)));
notifyUser(R.string.error_queue_request);
isRecording = false;
break;
}
Log.i(TAG, "Requesting response...");
final UsbRequest response = connection.requestWait();
if (response == null) {
Log.e(TAG, "Null response!");
notifyUser(R.string.null_response);
isRecording = false;
break;
}
final int nRead = buf.position();
if (nRead > 0) {
Log.i(TAG, "Streaming " + nRead + " bytes to UI");
Bundle args = new Bundle();
args.putShortArray(ARG_RECORDED_DATA, byte2short(buffer));
sendMessageToUI(SHOW_AUDIO_DATA_PACKET, args, null);
} else {
Log.e(TAG, "No data in buffer!");
notifyUser(R.string_empty_buffer);
isRecording = false;
break;
}
}
}
What I am getting from this is that request.queue() is always returning false.
I have also attempted to use the connection.bulkTransfer(endpoint, buffer, buffer.length, 0); method but the result is always -1.
If someone was in similar situation please help.
P.S. The error I am receiving in the log is: UsbRequestJNI: request is closed in native_queue.
I'm trying to read the data already stored by me in the Arduino kit, I'm using the physicaloid library to achieve this. I tested the kit (reading data) by connecting it to my PC using the Type B USB cable provided by Arduino itself and using Tera Term. The data begins to transfer after I press '#' on the keyboard (specific to our implementation).
But when I connect it my Android tablet and use the test project by physicaloid to open a device and start communicating, every time I click 'open' it shows a Toast saying it cannot open. I give permission to access the USB device every time it prompts me. Here is the sample program which I had created to read the data:
if(mPhysicaloid.open()){
Toast.makeText(getBaseContext(), "communicating", Toast.LENGTH_SHORT).show();
String signalToStart = new String("#");
byte[] bufToWrite = signalToStart.getBytes();
mPhysicaloid.write(bufToWrite, bufToWrite.length);
byte[] buf = new byte[255];
mPhysicaloid.read(buf);
String data = new String(buf);
tvResult.setText(data);
mPhysicaloid.close();
}
else
Toast.makeText(getBaseContext(), "no communication with device", Toast.LENGTH_LONG).show();
Now here's what I want to know about the data coming from the Arduino USB cable: is it in the RS232 format where the Android device is not able to understand (I don't know, I may be making a blunder here by asking this data format) or is it in the USB data format that is suitable for the Android device to understand? Please help, I have searched over this the whole day. What can I do to open the device and communicate?
I finally got the idea of reading the data from serial USB device. So I thought I'd share it:
First, get all the USB devices attached (if more than one) and get a suitable interface and search for endpoints to communicate with. While initializing the USB device make sure you consider the USB device which you really want to communicate with. You can do that by considering product id and Vendor id.
The code for doing the above described..
private boolean searchEndPoint() {
usbInterface = null;//class level variables, declare these.
endpointOut = null;
endpointIn = null;
Log.d("USB","Searching device and endpoints...");
if (device == null) {
usbDevices = usbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = usbDevices.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice tempDevice = deviceIterator.next();
/**Search device for targetVendorID(class level variables[vendorId = SOME_NUMBER and productId=SOME_NUMBER] which u can find) and targetProductID.*/
if (tempDevice .getVendorId() == vendorId) {
if (tempDevice .getProductId() == productId) {
device = tempDevice ;
}
}
}
}
if (device == null){
Log.d("USB","The device with specified VendorId and ProductId not found");
return false;
}
else
Log.d("USB","device found");
/**Search for UsbInterface with Endpoint of USB_ENDPOINT_XFER_BULK,
*and direction USB_DIR_OUT and USB_DIR_IN
*/
try{
for (int i = 0; i < device.getInterfaceCount(); i++) {
UsbInterface usbif = device.getInterface(i);
UsbEndpoint tOut = null;
UsbEndpoint tIn = null;
int tEndpointCnt = usbif.getEndpointCount();
if (tEndpointCnt >= 2) {
for (int j = 0; j < tEndpointCnt; j++) {
if (usbif.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (usbif.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_OUT) {
tOut = usbif.getEndpoint(j);
} else if (usbif.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_IN) {
tIn = usbif.getEndpoint(j);
}
}
}
if (tOut != null && tIn != null) {
/** This interface have both USB_DIR_OUT
* And USB_DIR_IN of USB_ENDPOINT_XFER_BULK
*/
usbInterface = usbif;
endpointOut = tOut;
endpointIn = tIn;
}
}
}
if (usbInterface == null) {
Log.d("USB","No suitable interface found!");
return false;
} else {
Log.d("USB","Suitable interface found!");
return true;
}
}catch(Exception ex){
ex.printStackTrace();
return false;
}
}
Now you have a device, USB interface, and endpoints ready for communication. Now it's time to establish a connection between your Android device and USB device.
Below is the code for this (and checking whether the connection is up and communicating):
private boolean checkUsbCOMM() {
/**Value for setting request, on the USB connection.*/
final int RQSID_SET_CONTROL_LINE_STATE = 0x22;
boolean success = false;
Log.d("USB","Checking USB Device for communication: ");
try{
Boolean permitToRead = SUSBS_usbManager.hasPermission(SUSBS_device);
if (permitToRead) {
//class level variable(connection, usbManager : declare it)
connection = usbManager.openDevice(device);
if (connection != null) {
connection.claimInterface(usbInterface, true);
int usbResult;
usbResult = connection.controlTransfer(0x21, //requestType
RQSID_SET_CONTROL_LINE_STATE, //SET_CONTROL_LINE_STATE(request)
0, //value
0, //index
null, //buffer
0, //length
500); //timeout = 500ms
Log.i("USB","controlTransfer(SET_CONTROL_LINE_STATE)[must be 0 or greater than 0]: "+usbResult);
if(usbResult >= 0)
success = true;
else
success = false;
}
}
else {
/**If permission is not there then ask for permission*/
usbManager.requestPermission(device, mPermissionIntent);
Log.d("USB","Requesting Permission to access USB Device: ");
}
return success;
}catch(Exception ex){
ex.printStackTrace();
return false;
}
}
Voila, the USB device is now able to communicate. So let's read using a separate thread:
if(device!=null){
Thread readerThread = new Thread(){
public void run(){
int usbResult = -1000;
int totalBytes = 0;
StringBuffer sb = new StringBuffer();
String usbReadResult=null;
byte[] bytesIn ;
try {
while(true){
/**Reading data until there is no more data to receive from USB device.*/
bytesIn = new byte[endpointIn.getMaxPacketSize()];
usbResult = connection.bulkTransfer(endpointIn,
bytesIn, bytesIn.length, 500);
/**The data read during each bulk transfer is logged*/
Log.i("USB","data-length/read: "+usbResult);
/**The USB result is negative when there is failure in reading or
* when there is no more data to be read[That is :
* The USB device stops transmitting data]*/
if(usbResult < 0){
Log.d("USB","Breaking out from while, usb result is -1");
break;
}
/**Total bytes read from the USB device*/
totalBytes = totalBytes+usbResult;
Log.i("USB","TotalBytes read: "+totalBytes);
for(byte b: bytesIn){
if(b == 0 )
break;
else{
sb.append((char) b);
}
}
}
/**Converting byte data into characters*/
usbReadResult = new String(sb);
Log.d("USB","The result: "+usbReadResult);
//usbResult holds the data read.
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
/**Starting thread to read data from USB.*/
SUSBS_readerThread.start();
SUSBS_readerThread.join();
}
For permission, make sure you add a PendingIntent as well add the permission to your manifest.
AndroidManifest : <uses-feature android:name="android.hardware.usb.host" />
PendingIntent:
private PendingIntent mPermissionIntent;
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
mPermissionIntent = PendingIntent.getBroadcast(MainActivity.this,
0, new Intent(ACTION_USB_PERMISSION), 0);
/**Setting up the Broadcast receiver to request a permission to allow the APP to access the USB device*/
IntentFilter filterPermission = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filterPermission);
I need your help, I'm trying to read some directory and trying to copy it to another place.
Now I can connect to usb host and read the usb specifications but i canĀ“t read the information on the usb to copy it.
this is my code
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) {
//call method to set up device communication
byte[] bytes = new byte[0];
int TIMEOUT = 0;
boolean forceClaim = true;
intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
connection = manager.openDevice(device);
connection.claimInterface(intf, forceClaim);
bytes=connection.getRawDescriptors();
Toast.makeText(context,"PERMISO CONCEDIDO",Toast.LENGTH_SHORT).show();
ArrayList<String>directorios=new ArrayList<>();
directorios=ObtnerDirectorios("/storage/UsbDriveA");
String dir="";
for(int i=0; i<directorios.size();i++){
dir+=directorios.get(i)+"\n";
}
infotext.setText(dir);
}
} else {
Toast.makeText(context,"PERMISO DENEGADO",Toast.LENGTH_SHORT).show();
}
}
}
I read the google documentation and I think t have to use a bulktransfer and control transfer but I'm not sure.
Could you help me?
Thanks
I have two different bluetooth apps. The first provides a service and listens to commands from the other commander app. I have a GT-I9100T phone and a GT-P5210 tablet. The tablet when acting at the listener works fine and the phone can see the UUID for my app. But when I run the phone as the listener, the UUID of the listener is not listed.
I filter the devices by my application UUID so that I know I am talking only to those devices with my application running.
My listening app looks like this (I get the same result if I use an insecure connection as well):
private final UUID GUID = UUID.fromString("3DEF793A-FA94-4478-AE56-108854B1EF4B");
// other stuff....
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(APP_NAME, GUID);
My commander app MainActivity looks likes this:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.i(TAG,"Action received: "+action);
if(action.equals(BluetoothDevice.ACTION_UUID)) {
BluetoothDevice btd = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.i(TAG,"Received uuids for "+btd.getName());
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
StringBuilder sb = new StringBuilder();
List<String> uuids = new ArrayList<String>(uuidExtra.length);
if(uuidExtra != null) {
for (int i = 0; i < uuidExtra.length; i++) {
sb.append(uuidExtra[i].toString()).append(',');
uuids.add(uuidExtra[i].toString());
}
}
Log.i(TAG,"ACTION_UUID received for "+btd.getName()+" uuids: "+sb.toString());
ListContent.addItemWithUUIDs(btd, uuids);
}
}
}
My list content (I am using the master/detail template):
public static synchronized void addItem(BluetoothItem item) {
BluetoothDevice btd = item.mBluetoothDevice;
Log.i(TAG,"Attempting to add "+item.mBluetoothDevice.getName());
if(ITEMS.contains(item)) {
Log.i(TAG,item.mBluetoothDevice.getName()+" already in list");
return;
}
// Do we know this device?
Parcelable[] uuids = btd.getUuids();
Set<String> setUUIDs = new HashSet<String>();
StringBuilder sb = new StringBuilder();
if(uuids != null) {
for (Parcelable parcelable : uuids) {
sb.append(parcelable.toString()).append(',');
setUUIDs.add(parcelable.toString());
}
}
Log.v(TAG,"Device has uuids: "+sb.toString());
if ((btd.getUuids() != null && setUUIDs.contains(BluetoothItem.GUID.toLowerCase()))){
Log.i(TAG, "Found app device: " + btd.getName());
addItem(btd);
} else {
// If we don't know this device, perform sdp fetch of uuids
Log.i(TAG,"Requesting fresh UUIDs for: "+btd.getName());
// this is flushed when discovering finishes
CANDIDATES.add(btd);
}
}
public static synchronized void addItemWithUUIDs(BluetoothDevice btd, List<String> uuids) {
Log.i(TAG,"Attempting to add with uuids"+btd.getName()+" uuids: "+btd.getUuids());
if (uuids.contains(BluetoothItem.GUID)) {
Log.i(TAG, "Found app device: " + btd.getName());
addItem(btd);
} else {
Log.i(TAG, "Ignoring device " + btd.getName() + " without app guid");
}
}
When discovery is finished, this happens:
for (BluetoothDevice i : ListContent.CANDIDATES) {
Log.i(TAG,"Fetching UUIDs for "+i.getName());
i.fetchUuidsWithSdp();
}
ListContent.CANDIDATES.clear();
The logcat output when using the tablet as the commander and phone as listener:
DeviceListActivity(29524): Received uuids for GT-I9100T
DeviceListActivity(29524): ACTION_UUID received for GT-I9100T uuids:
0000110a-0000-1000-8000-00805f9b34fb,
00001105-0000-1000-8000-00805f9b34fb,
00001116-0000-1000-8000-00805f9b34fb,
0000112d-0000-1000-8000-00805f9b34fb,
0000112f-0000-1000-8000-00805f9b34fb,
00001112-0000-1000-8000-00805f9b34fb,
0000111f-0000-1000-8000-00805f9b34fb,
00001132-0000-1000-8000-00805f9b34fb,
I get the correct output with phone as commander and tablet as listener:
DeviceListActivity(23121): Received uuids for GT-P5210
DeviceListActivity(23121): ACTION_UUID received for GT-P5210 uuids:
00001105-0000-1000-8000-00805f9b34fb,
0000110a-0000-1000-8000-00805f9b34fb,
0000110c-0000-1000-8000-00805f9b34fb,
00001112-0000-1000-8000-00805f9b34fb,
00001115-0000-1000-8000-00805f9b34fb,
0000111f-0000-1000-8000-00805f9b34fb,
00001200-0000-1000-8000-00805f9b34fb,
3def793a-fa94-4478-ae56-108854b1ef4b,
As you can see, the GUID for my app is listed as the last item. I've tried making the devices discoverable and bonding and unbonding, but the GUID for my app is never returned for the phone. I have other non-Android devices that also use this GUID and they are discovered normally as well.
The phone is running 4.1.2 and the tablet is 4.2.2