USB opendevice fails even if it has permission - HostAPI is restricted - android

I'm trying to connect Android and Arduino UNO using the Android USB Host API.
I discover the device using an intent-filter.
I obtain the appropriate UsbInterface and UsbEndpoint. Everything seems fine until I try opening the UsbDeviceConnection, which always fails despite permissions are granted.
What's the reason?
Snippet below:
#Override
protected void onResume() {
super.onResume();
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
Intent intent = getIntent();
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
}
}
public boolean connect(UsbDevice device){
[...] // search for appropriate interfaces/endpoints
Log.i(TAG, "usbInEndpoint = " + usbInEndpoint.toString());
Log.i(TAG, "usbOutEndpoint = " + usbOutEndpoint.toString());
Log.i(TAG, "usbInterface = " + usbInterface.toString());
Log.i(TAG, "permission = " + usbManager.hasPermission(device));
usbDeviceConnection = usbManager.openDevice(device);
Log.i(TAG, "usbDeviceConnection = " + usbDeviceConnection));
[...]
}
Logcat extract below:
usbInEndpoint = UsbEndpoint[mAddress=131,mAttributes=2,mMaxPacketSize=64,mInterval=1]
usbOutEndpoint = UsbEndpoint[mAddress=4,mAttributes=2,mMaxPacketSize=64,mInterval=1]
usbInterface = UsbInterface[mId=1,mAlternateSetting=0,mName=null,mClass=10,mSubclass=0,mProtocol=0,mEndpoints=[
UsbEndpoint[mAddress=4,mAttributes=2,mMaxPacketSize=64,mInterval=1]
UsbEndpoint[mAddress=131,mAttributes=2,mMaxPacketSize=64,mInterval=1]]
permission = true
D/UsbService: openDevice(/dev/bus/usb/001/002) : HostAPI is restricted
usbDeviceConnection = null
EDIT
I edited the question and the Logcat extract because I noticed UsbService logs that "Host API is restricted" after I call opendevice, so I guess is kind of device security setting. How to check that? I'm using Samsung A8

I answer my own question hoping this would be helpful for others with same issue. This was due to my mobile being managed by a MDM.

Related

How to get name of the connected Bluetooth device on android

I'm trying to get the name of the device that is connected to the Android phone running android Oreo.
I was searching for an answer for the past two days, and none of them worked. suggestions mostly returning ioexception-read-failed-socket-might-closed-bluetooth error
The question is, is there any way to make Query that returns the connected Bluetooth device?
These are the links and suggestion which not working:
IOException: read failed, socket might closed - Bluetooth on Android 4.3
In Android, how to get the profile of a connected bluetooth device?
list connected bluetooth devices?
I can get information about the device that is previously paired and trying to make a connection or a device trying to pair to the device. what I want is the name or the connection state of the currently paired and connected device.
here is the answer :
String name;
String address;
String threadName;
public void checkConnected()
{
BluetoothAdapter.getDefaultAdapter().getProfileProxy(this, serviceListener, BluetoothProfile.HEADSET);
}
private BluetoothProfile.ServiceListener serviceListener = new BluetoothProfile.ServiceListener()
{
#Override
public void onServiceDisconnected(int profile)
{
}
#Override
public void onServiceConnected(int profile, BluetoothProfile proxy)
{
for (BluetoothDevice device : proxy.getConnectedDevices())
{
name = device.getName();
address = device.getAddress();
threadName = Thread.currentThread().getName();
Toast.makeText(MainActivity.this, name+" " + address+ threadName, Toast.LENGTH_SHORT).show();
txtName.setText(name + " " + address);
Log.i("onServiceConnected", "|" + device.getName() + " | " + device.getAddress() + " | " + proxy.getConnectionState(device) + "(connected = "
+ BluetoothProfile.STATE_CONNECTED + ")");
}
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy);
}
};
Have you tried this?
BluetoothServerSocket bluetoothServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord("abc", uuid);
BluetoothSocket bluetoothSocket = bluetoothServerSocket.accept();
BluetoothDevice device = bluetoothSocket.getRemoteDevice();
String deviceName = device.getName();

Android Bluetooth: fetchUuidsWithSdp() does not return all UUIDs on some devices

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

Android Serial Read from Arduino Output through USB

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

How to change the name of bluetooth low energy device in Android 4.3?

I am developing an application where I have to connect to Bluetooth device on Android 4.3.
And I want to change the name of CC2541 Keyfob via the Android application.
I have trying to use 0x2A00 to get the Device Name service , but it seen not working when I call the Device_Name function.
The Name_Service is null.
private static final UUID Device_Name_UUID = UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb");
private static final UUID Write_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb");
public void Device_Name(){
BluetoothGattService Name_Service = mBluetoothGatt.getService(Write_UUID );
if(Name_Service == null) {
Log.d(TAG, "Name_Service service not found!");
return;
}
BluetoothGattCharacteristic DeviceName = Name_Service.getCharacteristic(Device_Name_UUID);
if(DeviceName == null) {
Log.d(TAG, "DeviceName charateristic not found!");
return;
}
}
Log.v(TAG, "readCharacteristic(DeviceName) = " + mBluetoothGatt.readCharacteristic(DeviceName));
String i = "123";
DeviceName.setValue(i);
Log.v(TAG, "writeCharacteristic(DeviceName) = " + mBluetoothGatt.writeCharacteristic(DeviceName));
I can read the name from BLE device , but it show writeCharacteristic(DeviceName) is false when I use mBluetoothGatt.readCharacteristic(DeviceName).
Does somebody has trying to use the UUID(0x2A00) of Device Name to write the name to BLE device ??
You need to modify the firmware of CC2541 keyfob to add the write permission of device name by adding the code below into KeyFobApp_Init() inside keyfobdemo.c:
uint8 devNamePermission = GATT_PERMIT_READ|GATT_PERMIT_WRITE;
GGS_SetParameter( GGS_W_PERMIT_DEVICE_NAME_ATT, sizeof ( uint8 ), &devNamePermission );
Reference: http://processors.wiki.ti.com/index.php/CC2540_DeviceNameWrite

list connected bluetooth devices?

How can I list all connected bluetooth devices on android ?
thanks!
public void checkConnected()
{
// true == headset connected && connected headset is support hands free
int state = BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(BluetoothProfile.HEADSET);
if (state != BluetoothProfile.STATE_CONNECTED)
return;
try
{
BluetoothAdapter.getDefaultAdapter().getProfileProxy(_context, serviceListener, BluetoothProfile.HEADSET);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private ServiceListener serviceListener = new ServiceListener()
{
#Override
public void onServiceDisconnected(int profile)
{
}
#Override
public void onServiceConnected(int profile, BluetoothProfile proxy)
{
for (BluetoothDevice device : proxy.getConnectedDevices())
{
Log.i("onServiceConnected", "|" + device.getName() + " | " + device.getAddress() + " | " + proxy.getConnectionState(device) + "(connected = "
+ BluetoothProfile.STATE_CONNECTED + ")");
}
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy);
}
};
As of API 14 (Ice Cream), Android has a some new BluetoothAdapter methods including:
public int getProfileConnectionState (int profile)
where profile is one of HEALTH, HEADSET, A2DP
Check response, if it's not STATE_DISCONNECTED you know you have a live connection.
Here is code example that will work on any API device:
BluetoothAdapter mAdapter;
/**
* Check if a headset type device is currently connected.
*
* Always returns false prior to API 14
*
* #return true if connected
*/
public boolean isVoiceConnected() {
boolean retval = false;
try {
Method method = mAdapter.getClass().getMethod("getProfileConnectionState", int.class);
// retval = mAdapter.getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET) != android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
retval = (Integer)method.invoke(mAdapter, 1) != 0;
} catch (Exception exc) {
// nothing to do
}
return retval;
}
First you need to retrieve the BluetoothAdapter:
final BluetoothAdapter btAdapter =
BluetoothAdapter.getDefaultAdapter();
Second you need to make sure Bluetooth is available and turned on :
if (btAdapter != null && btAdapter.isEnabled()) // null means no
Bluetooth!
If the Bluetooth is not turned out you can either use btAdapter.enable() which is not recommended in the documentation or ask the user to do it : Programmatically enabling bluetooth on Android
Third you need to define an array of states (to filter out
unconnected devices):
final int[] states = new int[] {BluetoothProfile.STATE_CONNECTED,
BluetoothProfile.STATE_CONNECTING};
Fourth, you create a BluetoothProfile.ServiceListener which
contains two callbacks triggered when a service is connected and
disconnected :
final BluetoothProfile.ServiceListener listener = new BluetoothProfile.ServiceListener() {
#Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
}
#Override
public void onServiceDisconnected(int profile) {
}
};
Now since you have to repeat the querying process for all available Bluetooth Profiles in the Android SDK (A2Dp, GATT, GATT_SERVER, Handset, Health, SAP) you should proceed as follow :
In onServiceConnected, place a condition that check what is the current profile so that we add the found devices into the correct collection and we use : proxy.getDevicesMatchingConnectionStates(states) to filter out unconnected devices:
switch (profile) {
case BluetoothProfile.A2DP:
ad2dpDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.GATT: // NOTE ! Requires SDK 18 !
gattDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.GATT_SERVER: // NOTE ! Requires SDK 18 !
gattServerDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.HEADSET:
headsetDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.HEALTH: // NOTE ! Requires SDK 14 !
healthDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.SAP: // NOTE ! Requires SDK 23 !
sapDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
}
And finally, the last thing to do is start the querying process :
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.A2DP);
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.GATT); // NOTE ! Requires SDK 18 !
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.GATT_SERVER); // NOTE ! Requires SDK 18 !
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.HEADSET);
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.HEALTH); // NOTE ! Requires SDK 14 !
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.SAP); // NOTE ! Requires SDK 23 !
source: https://stackoverflow.com/a/34790442/2715054
So you get the list of paired devices.
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevicesList = btAdapter.getBondedDevices();
for (BluetoothDevice pairedDevice : pairedDevicesList) {
Log.d("BT", "pairedDevice.getName(): " + pairedDevice.getName());
Log.d("BT", "pairedDevice.getAddress(): " + pairedDevice.getAddress());
saveValuePreference(getApplicationContext(), pairedDevice.getName(), pairedDevice.getAddress());
}
Android system doesn't let you query for all "currently" connected devices. It however, you can query for paired devices. You will need to use a broadcast receiver to listen to ACTION_ACL_{CONNECTED|DISCONNECTED} events along with STATE_BONDED event to update your application states to track what's currently connected.
I found a solution and it works on android 10
Kotlin
private val serviceListener: ServiceListener = object : ServiceListener {
var name: String? = null
var address: String? = null
var threadName: String? = null
override fun onServiceDisconnected(profile: Int) {}
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
for (device in proxy.connectedDevices) {
name = device.name
address = device.address
threadName = Thread.currentThread().name
Toast.makeText(
this#MainActivity,
"$name $address$threadName",
Toast.LENGTH_SHORT
).show()
Log.i(
"onServiceConnected",
"|" + device.name + " | " + device.address + " | " + proxy.getConnectionState(
device
) + "(connected = "
+ BluetoothProfile.STATE_CONNECTED + ")"
)
}
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy)
}
}
Call this method in main thread
BluetoothAdapter.getDefaultAdapter()
.getProfileProxy(this, serviceListener, BluetoothProfile.HEADSET)
Java
original code
Please analyze this class online.
Here you will find how to discover all connected (paired) Bluetooth devices.
Well here are the steps:
First, you start intent to discover devices
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
Register a broadcast reciver for it:
registerReceiver(mReceiver, filter);
On the definition of mReceiver:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
arrayadapter.add(device.getName())//arrayadapter is of type ArrayAdapter<String>
lv.setAdapter(arrayadapter); //lv is the list view
arrayadapter.notifyDataSetChanged();
}
}
and the list will be automatically populated on new device discovery.

Categories

Resources