It's my first time working with Bluetooth module in Android, I'm trying to scan devices not paired yet and show them in a message but it doesn't work. I have tried a lot of things but nothing. I have all the permissions needed. This is part of my code
mScanBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
//registerReceiver(mBroadcastReceiver, filter);
if(mBlueAdapter!=null && mBlueAdapter.isEnabled()) {
listAdapter.clear();
mBlueAdapter.startDiscovery();
showToast("Discovery");
IntentFilter filtera = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBroadcastReceiver, filter);
}
And this is my BroadcastReceiver
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
listAdapter.add(device.getName() + device.getAddress());
listAdapter.notifyDataSetChanged();
showToast("Action Scan Mode " );
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
mpossibleBtn.setText("Scanning Bluetooth Devices");
showToast("Scannning Bluetooth Devices... " );
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
mpossibleBtn.setText("Scanning in progress...");
showToast("Scanning in progress... " );
}
if (action.equals(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)) {
showToast("Action Scan Mode " );
int modeValue=intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.ERROR);
if(modeValue==BluetoothAdapter.SCAN_MODE_CONNECTABLE){
mPairedTv.setText("The device is not in discoverable mode but still can receive connections");
} else if(modeValue==BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
mPairedTv.setText("The device is in discoverable mode");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
showToast("onReceive: " + device.getName() + ": " + device.getAddress());
} else if (modeValue==BluetoothAdapter.SCAN_MODE_NONE){
mPairedTv.setText("The device is not in discoverable mode and can't receive connection");
} else{
mPairedTv.setText("Error");
}
}
}
};
I'm testing the app on my Xiaomi cellphone.
you need to ADD after registering receiver
mBtAdapter.startDiscovery();
Start discovery after registering your receiver.
IntentFilter intent = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(mBroadcastReceiver, intent);
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mBroadcastReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBroadcastReceiver, filter);
mBtAdapter.startDiscovery();
Or in your case
IntentFilter filtera = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBroadcastReceiver, filter);
mBtAdapter.startDiscovery();
Also ensure you have bt permissions on your manifest
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
On some phones you will need to restart the adapter first.
mBluetoothAdapter.disable();
mBluetoothAdapter.enable();
for some time on the broadcast receiver if you don't receive BluetoothAdapter.ACTION_DISCOVERY_STARTED after starting discovery, you have to prompt device restart as the bt may not be working properly.you can use a timer to check this.
Ok so I just found my error. In this case BLUETOOTH and BLUETOOTH_ADMIN permissions have a protection Level of normal, and so all you need to do is request them in the manifest. The location permissions are dangerous, though, and so on Android 6.0+ devices, with a targetSdkVersion of 23 or higher, you need to request those at runtime.
I alredy have the permissions however, we do need to request ACCESS_COARSE_LOCATION at runtime.
This time the code works
mScanBtn.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onClick(View v) {
if(mBlueAdapter!=null && mBlueAdapter.isEnabled()) {
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBroadcastReceiver, filter);
if (context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mMap != null) {
mMap.setMyLocationEnabled(true);
mBlueAdapter.startDiscovery();
}
}
else {
// Permission to access the location is missing. Show rationale and request permission
PermissionUtils.requestPermission(MainActivity.this, MY_PERMISSIONS_REQUEST_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION, true);
mBlueAdapter.startDiscovery();
}
}
});
Related
I am able to list unpaired devices on scan discovery only if other devices are on their 'bluetooth setting screen'.If other devices are on their homepage then my application cannot find those devices.
I have android 7 on my mobile phone and other devices have android 9 on them.
Any help is appreciated.Thanks:)
public void startDiscovery()
{
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
BA.startDiscovery();
registerReceiver(mReceiver, filter);
Toast.makeText(getApplicationContext(), "Discovery started", Toast.LENGTH_SHORT).show();
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("main","action found"+action);
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Toast.makeText(getApplicationContext(), "Discovery started", Toast.LENGTH_SHORT).show();
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Toast.makeText(getApplicationContext(), "Discovery finished", Toast.LENGTH_SHORT).show();
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
//Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
Log.d("main","devicename"+deviceName);
Log.d("main","deviceHardwareAddress"+deviceHardwareAddress);
}
};
#Override
protected void onDestroy() {
Log.d("main","destroyed");
super.onDestroy();
BA.cancelDiscovery();
// Don't forget to unregister the ACTION_FOUND receiver.
unregisterReceiver(mReceiver);
}
Its not being discovered because its hidden according to the bt protocol however see https://stackoverflow.com/a/36984988/8461344
I am trying to discover bluetooth devices nearby. I followed tutorials but I can't figure out why onReceive() method is never called. Even though startDiscovery() is successful,the method onReceive() never gets called. I have added the proper permissions to the manifest
if(adapter.isDiscovering()) {
adapter.cancelDiscovery();
if (adapter.startDiscovery())
test.setText("Searching >>>");
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
Receiver receiver = new Receiver();
registerReceiver(receiver, filter);
}
}
if(!adapter.isDiscovering()) {
if (adapter.startDiscovery())
test.setText("Searching >>>");
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
Receiver receiver = new Receiver();
registerReceiver(receiver, filter);
}
private class Receiver extends BroadcastReceiver {
public Receiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
devices = new ArrayList<BluetoothDevice> ();
devices.add(device);
listAdapter = new DeviceListAdapter(context,R.layout.activity_bluetooth_connection,devices);
pairedDivices = (ListView) findViewById(R.id.pairedDevices);
pairedDivices.setAdapter(listAdapter);
if(devices.isEmpty())
test.setText("no devices");
}
}
}
Hello i have followed the example in https://developer.android.com/guide/topics/connectivity/bluetooth and my broadcast receiver maybe is not working. I am running android 8.1 in my Android Xiaomi mi A1 device.
#Override
protected void onCreate(Bundle savedInstanceState) {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
bluetoothAdapter.startDiscovery();
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
Toast.makeText(MainActivity.this, deviceName, Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, deviceHardwareAddress, Toast.LENGTH_SHORT).show();
mDeviceList.add(deviceHardwareAddress);
ArrayAdapter arrayAdapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1,mDeviceList);
listV.setAdapter(arrayAdapter);
}
}
};
Thank you!
NOTE
For android Api 21 Broadcast receiver works fine is there a change i have to make to make it work for Android 8.1?
In manifest I have put the permissions and other services like start stop bluetooth and find paired devices are working fine...
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
You Need to Add Permission in code above Version M
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 1000);
I am trying to discover all available bluetooth devices and pass to another activity.
However even when looking at the Android Docs, I am unable to figure out why I cannot discover any devices and my ArrayList remains empty.
OnClick execute this:
mBluetoothAdapter.startDiscovery();
My broadcast listener also works but nothing is every returned and ArrayList remains empty.
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDeviceList.add(device);
showToast("Found device " + device.getName());
}
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_ON) {
showToast("Enabled");
showEnabled();
}
}
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
mDeviceList = new ArrayList<>();
mProgressDlg.show();
}
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
mProgressDlg.dismiss();
Intent newIntent = new Intent(MainScreen.this, DeviceListActivity.class);
if (mDeviceList.isEmpty()){
Log.d("onReceive: ", "EMPTY");
}
newIntent.putParcelableArrayListExtra("device.list", mDeviceList);
startActivity(newIntent);
}
}
};
GIST
Answered my own question.
The fix was to turn location on with app permissions.
Apparently this is required for Android Marshmallow
I am developing an Android application using Android Studio 0.5.2.
My application is operating a USB host which appears to operate correctly - unless the device is connected (and permissions have not yet been granted) when the app starts.
Generally, what happens when the USB is connected (while app is running):
"onResume" is called - this detects the device and asks for permission. An intent filter is created to catch when the USB is attached, detached or permission granted
Permission request is shown, select Ok
"onResume" is called again. The first line of this funciton is "super.onResume()"
As soon as I step over super.onResume, "Unfortunately, System UI has stopped" message is displayed and the Android UI crashes
My application continues to work correctly
If I connect the device while the application is already running there is no issue - this only occurs when the USB is connected on launch.
Any insight into what could be causing this or how to further narrow down on the problem would be greatly appreciated. I have attached the notable code below. I am not normally a Java developer, so I suspect the issue is something to do with the pause/resume behaviour, receivers, intent filters or permissions.
// *************************************************************
// ************************* USB Stuff *************************
// *************************************************************
boolean resumePermissionBlocked = false;
PendingIntent pendingIntent = null;
BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
// Get the information about what action caused this event
try {
String action = intent.getAction();
Log.i(TAG, "$EC: action:" + action);
if ("com.android.example.USB_PERMISSION".equals(action)) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
if (device.getProductId() == 0xAAAA) {
if (device.getVendorId() == 0xBBBB) {
// see if we have permission
UsbManager openManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
// send a message to the worker thread to begin opening a connection to this device
ThreadMsg msg = new ThreadMsg();
msg.request = MsgRequest.openConnection;
msg.objectA = device;
msg.objectB = openManager;
sendMessageToWorker(msg);
}
}
}
} else {
if (device != null)
Log("USB Permission denied", TextFormat.StrongWarning_withTime);
}
}
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device == null) return;
if (device.getProductId() == 0x003C) {
if (device.getVendorId() == 0x04D8) {
// see if we have permission
UsbManager openManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
if (!openManager.hasPermission(device)) {
resumePermissionBlocked = true; // block the resume function from trying to re-ask for permission
openManager.requestPermission(device, mPermissionIntent);
return;
}
ThreadMsg msg = new ThreadMsg();
msg.request = MsgRequest.openConnection;
msg.objectA = device;
msg.objectB = openManager;
sendMessageToBootloader(msg);
}
}
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
// If it was a USB device detach event, then get the USB device
// that caused the event from the intent.
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
ThreadMsg msg = new ThreadMsg();
msg.request = MsgRequest.closeConnection;
msg.objectA = device;
sendMessageToBootloader(msg);
}
} catch (Exception e) {
Log.i(TAG, "onResume catch: " + e.toString());
}
}
};
boolean receiverHasBeenRegistered = false;
PendingIntent mPermissionIntent;
#Override
public void onResume(){
try {
super.onResume();
if (resumePermissionBlocked) {
// this was resumed from a permission request - don't try to connect to the device now, leave it for the USB_PERMISSION_GRANTED intent
resumePermissionBlocked = false; // clear the flag
} else {
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
if (deviceList != null) {
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
Log.i(TAG, "$EC: Begin iteration");
while (deviceIterator.hasNext()) {
// Is this the device we are after?
UsbDevice device = deviceIterator.next();
if (device == null) return;
if (device.getProductId() == 0xAAAA) {
if (device.getVendorId() == 0xBBBB) {
// see if we have permission
UsbManager openManager = (UsbManager) this.getSystemService(Context.USB_SERVICE);
if (!openManager.hasPermission(device)) {
resumePermissionBlocked = true; // block the subsequent call to this (between the application resuming and permission being granted)
openManager.requestPermission(device, mPermissionIntent);
return;
}
ThreadMsg msg = new ThreadMsg();
msg.request = MsgRequest.openConnection;
msg.objectA = device;
msg.objectB = openManager;
sendMessageToWorker(msg);
}
}
}
}
}
} catch (Exception e)
{
Log.i(TAG, "onResume catch: " + e.toString());
}
if (!receiverHasBeenRegistered) {
// this line is for permissions
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent("com.android.example.USB_PERMISSION"), 0);
//Create a new filter to detect USB device events
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
filter.addAction("com.android.example.USB_PERMISSION");
registerReceiver(receiver, filter);
pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(getPackageName() + ".USB_PERMISSION"), 0);
receiverHasBeenRegistered = true;
}
}
#Override
public void onPause() {
/* unregister any receivers that we have */
try {
if (receiver != null && receiverHasBeenRegistered) {
unregisterReceiver(receiver);
receiverHasBeenRegistered = false;
}
} catch (Exception e) {
// if this happens, then the receiver was probably never registered in the first place
Log.i(TAG, "onPause catch: " + e.toString());
}
super.onPause();
}
Try super.onResume at the end of onResume method
Alert user to connect the usb device on application start (main activity's
onCreate) if device is not connected, toast an alert msg and finish/close
the main activity
Add intend filter in manifest file allowing the app to start automatically on connecting the device
Try to capture exception printstacktrack when the UI stopped message is
shown and debug further from the exception.
Make sure to follow the steps from android doc
https://developer.android.com/guide/topics/connectivity/usb/host.html