Can`t run BlueTooth discovery from Service - android

I can`t run startDiscovery (for BlueTooth) from Service.
Service run from sleep by WakefulBroadcastReceiver (by timer).
Source code of Service:
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = "LocationService";
private BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Service onCreate");
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBTReceiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service onStartCommand");
BTscanner();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (btAdapter != null) {
btAdapter.cancelDiscovery();
}
unregisterReceiver(mBTReceiver);
}
private void BTscanner() {
Log.e(TAG, "==BT: Run BTscanner");
btAdapter.cancelDiscovery();
btAdapter.startDiscovery();
Log.e(TAG, "==BT: End BTscanner");
}
private final BroadcastReceiver mBTReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.e(TAG, "==BT: Started");
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.e(TAG, "==BT: Finished");
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.e(TAG, "==BT: " + device.getAddress());
}
}
};
}
In log i see:
Service onStartCommand
==BT: Run BTscanner
==BT: End BTscanner
but don`t see:
==BT: Started
==BT: Finished
and list of discovered devices.
In Manifest all permissions installed:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
and service enabled in application field of Manifest:
<service
android:name=".LocationService"
android:enabled="true"
android:exported="true" />
What did I do wrong?
Tnx.

Are you sure that your receiver has not been unregistered in the onDestroy method before having the time to handle any action? I would put a break point in it to see what's happenning in there?

I think, I found a solution.
There were problems when I install and run the application with active Bluetooth on smartphone.
After installing application and manual deactivate/activate Bluetooth device all works fine.
Maybe it was some sort of a hardware failure.
Then reinstall the application twice, and the problem is not repeated.

Related

android: Bluetooth won't discover devices

I'm writing an Android-App, which is supposed to discover devices via Bluetooth.
I don't get any exceptions, but the devices are just not found, even though my windows pc finds them (and can be found itself).
I'm certain they are BLE, but I tried both ways. And of course I tried them separately.
Here is my ListActivity, which searches for the devices:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
setContentView(R.layout.bluetooth_list_view);
listView = getListView();
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "BLE is not supported", Toast.LENGTH_SHORT).show();
finish();
}
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
Log.d(TAG, "on Create start5");
if (mBluetoothAdapter == null) {
Toast.makeText(this, "BLE is not supported", Toast.LENGTH_SHORT).show();
finish();
return;
}
mLeDeviceListAdapter = new LeDeviceListAdapter(this);
setListAdapter(mLeDeviceListAdapter);
listView.setAdapter(mLeDeviceListAdapter);
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery();
}
private void scanLeDevice(final boolean enable) {
Log.e(TAG, "scanLeDevice: " + enable);
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
Log.e(TAG, "after Scan mLeDeviceListAdapter: " + mLeDeviceListAdapter.getCount());
Log.e(TAG, "after Scan isEmpty(): " + mLeDeviceListAdapter.isEmpty());
mScanning = false;
mBluetoothLeScanner.stopScan(mScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothLeScanner.startScan(mScanCallback);
} else {
mScanning = false;
mBluetoothLeScanner.stopScan(mScanCallback);
}
invalidateOptionsMenu();
}
The logs say after Scan mLeDeviceListAdapter: 0 and after Scan isEmpty(): true.
ScanCallback mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.e(TAG, "onScanResult: " + result);
super.onScanResult(callbackType, result);
mLeDeviceListAdapter.addDevice(result.getDevice());
mLeDeviceListAdapter.notifyDataSetChanged();
}
};
That log (onScanResult) is never called.
And for not BLE:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { //TODO not ble example
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.e(TAG, "Not BLE discovry starts");
//discovery starts, we can show progress dialog or perform other tasks
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.e(TAG, "Not BLE discovry finishes");
//discovery finishes, dismis progress dialog
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
//bluetooth device found
BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.e(TAG, "Found device " + device.getName());
}
}
};
Not BLE discovry finishes is printed and so is Not BLE discovry starts. Found device is never printed. But I'm positiv that the devices are BLE.
I have the necessary permissions in my manifest:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
What am I doing wrong?
Edit:
i really need help. Thinks I tried/checked so far:
Enabled Bluetooth adapter.
Bluetooth usage permissions granted.
Location permission (ACCESS_COARSE and ACCESS_FINE) granted.
Made sure gps provider is enabled (Smartphone GPS settings).
Maybe because you didn't request ACCESS_COARSE_LOCATION in onCreate
This project is a good resource for you to start your Bluetooth scanner:
https://github.com/joelwass/Android-BLE-Scan-Example

Bluetooth:onReceive() and registerReceiver() these method never been called

I am developing an application for a Bluetooth client side, and inside this application has a listview that will list out all the connected devices. First, the application will check for the availability of the Bluetooth and then try to connect to another device(Server) , beside that, I initialised the intent filter in the manifest file.
Below is my code :
public class MainActivity extends AppCompatActivity {
ArrayAdapter<String> listAdapter;
ListView listView;
BluetoothAdapter mBluetoothAdapter;
Set<BluetoothDevice> bondedDevices;
private BluetoothSocket socket;
Intent discoverableIntent;
private BluetoothDevice remoteDevice;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equalsIgnoreCase("android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED"))
{
Log.i("Connect", "Connecting.>>>>");
unregisterReceiver(this);
remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String Temp1 = remoteDevice.getName();
String Temp2 = remoteDevice.getAddress();
listAdapter.add(Temp1 + Temp2);
listView.setAdapter(listAdapter);
new Thread(reader).start();
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
IntentFilter intentFilter = new IntentFilter("com.example.jackpowell.bluetoothclient.ACTION_ACL_CONNECTED");
registerReceiver(mReceiver,intentFilter);
startDiscovery();
}
private void startDiscovery() {
mBluetoothAdapter.cancelDiscovery();
mBluetoothAdapter.startDiscovery();
}
public void init() {
listView = (ListView)findViewById(R.id.listView);
listAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,0);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(MainActivity.this, "Bluetooth is not supported in this device", Toast.LENGTH_SHORT).show();
finish();
} else {
if (!mBluetoothAdapter.isEnabled()) {
turnOnBluetooth();
}
}
bondedDevices = mBluetoothAdapter.getBondedDevices();
discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivity(discoverableIntent);
}
private Runnable reader = new Runnable() {
#Override
public void run() {
try {
Log.i("Connect","Connecting...........");
android.util.Log.e("TrackingFlow", "Found: " + remoteDevice.getName());
UUID uuid = UUID.fromString("a60f35f0-b93a-11de-8a19-03002011c456");
socket = remoteDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
} catch (Exception e) {
e.printStackTrace();
}
}
};
private void turnOnBluetooth() {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Bluetooth must be enabled to continue", Toast.LENGTH_SHORT).show();
finish();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
my manifest:
<application
android: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>
</activity>
</application>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<receiver android:name="bluetoothclient">
<intent-filter>
<action android:name="android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED" />
</intent-filter>
</receiver>
The problem now is onReceive() and registerReceiver() these method never been called, or maybe it already called, I just dont get it. If these method were called, the log cat should be displaying the log command. Why are these method never been called? thank you in advance!
The action name is "android.bluetooth.device.action.ACL_CONNECTED" (to use in manifest) or BluetoothDevice.ACTION_ACL_CONNECTED (to use in code, for intent filter). Action names in your code seem wrong.
Note, to register receiver in manifest the receiver name should be public class based on BroadcastReceiver, not sure what is the "bluetoothclient" meaning in the code above (you didn't show the receiver code).
Usually you don't need both manifest receiver and intent filter receiver in activity, one may be sufficient. The main difference is that manifest receiver can be independent from activity life cycle and receive even when activity is not running.
Try to listen also for ACTION_FOUND (per documentation after startDiscovery you'll receive BluetoothDevice.ACTION_FOUND) and others and try to reduce into minimal example. You need also check result of startDiscovery() which can return false on failure.
Here is slightly modified sample from Discovering devices section:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
// Register for broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
registerReceiver(mReceiver, filter);
...
if(!mBluetoothAdapter.startDiscovery()){
Log.e("Bluetooth", "discovery error");
}
}
// Create a BroadcastReceiver for bluetooth actions
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("Bluetooth", "got action " + action);
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.i("Bluetooth", "got device " + deviceName );
}
}
};
#Override
protected void onDestroy() {
super.onDestroy();
...
// Don't forget to unregister the ACTION_FOUND receiver.
unregisterReceiver(mReceiver);
}
Also note, per this question/answer, on some devices discovery does not always work as expected and there is a need for workarounds.
By the way, did you check the logcat for other errors, for example denied permissions etc.? You may try to enable location and add location permission.
Here is a working sample to display all devices:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testbluetooth"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
package com.example.testbluetooth;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView textView;
StringBuilder text = new StringBuilder();
private void addLine(String line)
{
Log.i(getClass().getSimpleName(), line);
text.append("[bluetooth] ").append(line).append('\n');
if(textView!=null)
textView.setText(text);
}
BluetoothAdapter mBluetoothAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
FrameLayout content = new FrameLayout(this);
textView = new TextView(this);
content.addView(textView, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addLine("onCreate");
setContentView(content);
// Register for broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
registerReceiver(mReceiver, filter);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
for(BluetoothDevice pairedDevice : mBluetoothAdapter.getBondedDevices())
{
addLine("got paired device " + pairedDevice.getName());
}
if(!mBluetoothAdapter.startDiscovery()){
addLine("ERROR: discovery error");
}
else
{
addLine("starting discovery");
}
}
// Create a BroadcastReceiver for bluetooth actions
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
addLine("got action " + action);
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
addLine("got device " + deviceName );
}
}
};
}

How to dismiss bluetooth pairing request dialog completely?

My app should pair with a BLE without showing any pairing request dialog. I am setting pin in the code. But actually dialog is showing for a sec and then disappearing. Pairing is happening, but i don't want this dialog to be shown. Is there a method to do that?
Since the SDK version 19 this is more difficult. I found a way to bypass it using a subclass of BroadcastReceiver.
public class BluetoothPairingRequest extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
// convert broadcast intent into activity intent (same action string)
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
Intent pairingIntent = new Intent();
pairingIntent.setClass(context, MainActivity.class);
pairingIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, type);
pairingIntent.setAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
pairingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (device != null) {
try {
device.setPin("1111".getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
context.startActivity(pairingIntent);
}
}
}
Then you need register a bond receiver like this.
/**
* Lock used in synchronization purposes
*/
private final Object lock = new Object();
private String deviceAddress;
...
#Override
public void onCreate() {
super.onCreate();
...
final IntentFilter bondFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(bondStateBroadcastReceiver, bondFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
...
unregisterReceiver(bondStateBroadcastReceiver);
}
After this you can add this code when you want to initialize the bonding process.
...
BluetoothDevice newDevice = bluetoothAdapter.getRemoteDevice(device.getAddress());
deviceAddress = newDevice.getAddress();
createBond(newDevice);
...
The implementation of the createBond is here:
private final BroadcastReceiver bondStateBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
// Obtain the device and check it this is the one that we are connected to
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (!device.getAddress().equals(mDeviceAddress))
return;
// Read bond state
final int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
if (bondState == BluetoothDevice.BOND_BONDING)
return;
requestCompleted = true;
// Notify waiting thread
synchronized (lock) {
lock.notifyAll();
}
}
};
private boolean createBond(final BluetoothDevice device) {
if (device.getBondState() == BluetoothDevice.BOND_BONDED)
return true;
boolean result;
requestCompleted = false;
sendLogBroadcast(LOG_LEVEL_VERBOSE, "Starting pairing...");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
result = device.createBond();
} else {
result = createBondApi18(device);
}
// We have to wait until device is bounded
try {
synchronized (lock) {
while (!requestCompleted) lock.wait();
}
} catch (final InterruptedException e) {
Log.e(TAG, "Sleeping interrupted", e);
}
return result;
}
private boolean createBondApi18(final BluetoothDevice device) {
/*
* There is a createBond() method in BluetoothDevice class but for now it's hidden. We will call it using reflections. It has been revealed in KitKat (Api19)
*/
try {
final Method createBond = device.getClass().getMethod("createBond");
if (createBond != null) {
return (Boolean) createBond.invoke(device);
}
} catch (final Exception e) {
Log.w(TAG, "An exception occurred while creating bond", e);
Log.e(TAG, e.toString());
}
return false;
}
Finally don't forget to add to your manifest these lines:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
And register the receiver:
<receiver android:name=".bluetooth.BluetoothPairingRequest">
<intent-filter>
<action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
<action android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
</intent-filter>
</receiver>

Detect when USB device detached from Android device

I am using a usb POS printer with my application. I have successfully written the code to connect, request permission and print data. However, I'm unsure how do notify the user when the printer is disconnected, if it is then the device falls back to the network printer.
So this is my BroadcastReceiver for requesting permission:
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 = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
mDevice = device;
if(mConnection == null){
Log.i(m_Tag, "Connection is null");
}
Log.i(m_Tag, "Connected successfully");
}else{
Log.i(m_Tag, "Device is null");
}
}
else {
}
}
}
}
};
I have trawled through the forums here and suggested answers and I've checked out this http://developer.android.com/guide/topics/connectivity/usb/host.html I can't find a solid way to do it without including a device filter xml file. I can't do this because I'm unsure as to what model of printer will be used by the end user.
My brain is fried from this, if someone could please point out how to do this, I'd greatly appreciate it.
Quite late, but for future readers here is how I do it.
In onStart() I register a broadcast receiver for the ACTION_USB_DEVICE_DETACHED action.
#Override
protected void onStart() {
Log.d(TAG, "onStart()");
super.onStart();
// Catch a USB detach broadcast intent.
detachReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
jobsDone();
}
}
};
// Set the intent filter for the broadcast receiver, and register.
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(detachReceiver, filter);
}
In my jobsDone() I just finish the Activity which is basically the same as pressing "back".
private void jobsDone() {
Log.d(TAG, "jobsDone()");
this.finish();
}
Since in my case only one USB device can be attached at one single time I do not have to bother with device_filter.xml for the detach.
Also remember to unregister the receiver.
#Override
protected void onStop() {
Log.d(TAG, "onStop()");
super.onStop();
// Unregister the BroadcastReceiver
unregisterReceiver(detachReceiver);
}

How to scan for available bluetooth devices in range in android?

I need to get a list of available bluetooth devices in the area using google android 2.1.
Thing is, i don't just need a list of those devices, i need some unique id for each device found and i need an indicator, how "good" the signal is received (like the "level" in android.wifi.ScanResult)... How do i do that?
Check out code below :
Starting search
mBluetoothAdapter.startDiscovery();
mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//Finding devices
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
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
Call method bluetoothScanning, context is required
void bluetoothScanning(){
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(mReceiver, filter);
final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.startDiscovery();
}
// Create a BroadcastReceiver for ACTION_FOUND.
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 = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
Log.i("Device Name: " , "device " + deviceName);
Log.i("deviceHardwareAddress " , "hard" + deviceHardwareAddress);
}
}
};
Result
Name: LE-Bose Revolve+ SoundLink
deviceHardwareAddress: MAC .....
This code uses BeaconManager, it continuously scans for new Bluetooth devices and returns a Beacons List object which you can use to get what ever information you need.
Make sure you import BeaconManager
private BeaconManager beaconManager;
//In onCreate method
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
//use these out of the onCreate method
public void onScanStart(View view) {
stopScanButton.setEnabled(true);
scanningButton.setEnabled(false);
beaconManager.bind(this);
}
#Override
public void onBeaconServiceConnect() {
beaconManager.removeAllRangeNotifiers();
beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
for (Beacon b : beacons) {
System.out.println(String.format("%s: %f: %d", b.getBluetoothName(), b.getDistance(), b.getRssi()));
});
try {
//Tells the BeaconService to start looking for beacons that match the passed.
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
} catch (RemoteException e) {
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
}
}
Let me know if that works for you!
To able to discovery devices by bluetooth. Make sure you
Enable bluetooth
Allow required permissions for your application (some permission is runtime permission). You can check here https://developer.android.com/about/versions/12/features/bluetooth-permissions
AndroidManifest.xml
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
MainActivity
class MainActivity : AppCompatActivity() {
private var bluetoothAdapter: BluetoothAdapter? = null
private val bluetoothReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val action = intent.action
Log.i("TAG", "onReceive $action")
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) {
Log.i("TAG", "Discovery finished, hide loading")
} else if (BluetoothDevice.ACTION_FOUND == action) {
val device =
intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
Log.i("TAG", "Device Name: " + (device?.name ?: ""))
Log.i("TAG", "Device Address:" + (device?.address ?: ""))
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
...
findViewById<Button>(R.id.button_start_discovery).setOnClickListener {
if (bluetoothAdapter == null) {
initBluetoothDiscovery()
}
startDiscovery()
}
}
private fun initBluetoothDiscovery() {
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothAdapter = bluetoothManager.adapter
val intentFilter = IntentFilter().apply {
addAction(BluetoothDevice.ACTION_FOUND)
addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
}
registerReceiver(bluetoothReceiver, intentFilter)
}
private fun startDiscovery() {
if (bluetoothAdapter?.isDiscovering == true) {
Log.i("TAG", "cancel start discovery")
bluetoothAdapter?.cancelDiscovery()
}
Log.i("TAG", "start discovery, show loading")
bluetoothAdapter?.startDiscovery()
}
override fun onDestroy() {
super.onDestroy()
bluetoothAdapter?.cancelDiscovery();
unregisterReceiver(bluetoothReceiver);
}
}

Categories

Resources