finding out Bluetooth State without a Broadcast Receiver? - android

I'd like to know if there is any way I can simply check whether a Bluetooth device is currently connected - I don't want to use a broadcast receiver - just check the state. I can't seem find out how this is done.
I currently have a listener that does listen to state changes with Bluetooth, and changes an internal variable accordingly - but, even though it sounds weird just saying it, it actually seems to miss the Bluetooth device disconnect broadcast sometimes. what I would like to do is run an additional check to see if the device really is still connected, or if the broadcast was missed...
so, how do I do this?
Thanks for reading/helping!

I use this to check the state of Bluetooth. I don't know how to check if is currently connected to another device but I think this can be a start point.
private void CheckBlueToothState() {
if (bluetoothAdapter == null) {
//stateBluetooth.setText("Bluetooth NOT support");
} else {
if (bluetoothAdapter.isEnabled()) {
if (bluetoothAdapter.isDiscovering()) {
//stateBluetooth.setText("Bluetooth is currently in device discovery process.");
} else {
//stateBluetooth.setText("Bluetooth is Enabled.");
}
} else {
//stateBluetooth.setText("Bluetooth is NOT Enabled!");
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
}

Related

Programmatically bonding to BLE device on Android

I'm writing an Android application in which I'd like to programmatically bond to a custom BLE device. I have the manual bonding working in which the user enters the PIN using the standard Android Bluetooth pairing dialog, but I have not been able to find any information on how to automatically bond a BLE device programatically, without user intervention. Is that possible? If so, what's the process?
I was able to make this work MOST OF THE TIME by registering a BroadcastReceiver to receive the BluetoothDevice.ACTION_BOND_STATE_CHANGED intent and then calling BluetoothDevice.setPin after receiving the BluetoothDevice.BOND_BONDING message. As is the case with most BLE things in Android, this seems to act slightly differently depending on the device and Android version. Unfortunately, I can't seem to stop Android from also receiving the bluetooth intent, so the PIN entry screen still pops up for a second before the bonding is completed.
private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
final String action = intent.getAction();
Logger("Broadcast Receiver:" + action);
if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED))
{
final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
if(state == BluetoothDevice.BOND_BONDING)
{
Logger("Bonding...");
if (mDevice != null) {
mDevice.setPin(BONDING_CODE.getBytes());
Logger("Setting bonding code = " + BONDING_CODE);
}
}
else if(state == BluetoothDevice.BOND_BONDED)
{
Logger("Bonded!!!");
mOwner.unregisterReceiver(mReceiver);
}
else if(state == BluetoothDevice.BOND_NONE)
{
Logger("Not Bonded");
}
}
}
};
I managed to do this - see my answer here.
The TL;DR is: forget about ACTION_BOND_STATE_CHANGED; you don't need it. Instead listen to ACTION_PAIRING_REQUEST, and set the priority high. In the broadcast receiver when you get ACTION_PAIRING_REQUEST, call setPin() with your PIN and then abortBroadcast() to prevent the system showing the notification.
All you can do to avoid user interaction is to force Just Works pairing. To do that, program the peripheral to accept pairing with NoInputNoOutput IO Capability.

Android Bluetooth headset connection

I am new to Android Platform. I am working with an application requires integration of Bluetooth. The requirement is instead of manually connecting and disconnecting a Bluetooth headset(HSP profile),Connection and disconnection should be possible within the application.Is it possible to connect and disconnect the device in Android devices running OS 4.2 ,4.3 and 4.4.If any one has a solution for this issue,Please advise me for the same.
It is possible, but sometimes not that simple.
To connect, start by checking whether or not the device you are running on has BT support at all:
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter==null) {
// device not support BT
}
If not - gracefully disable the BT portion of your app and move on.
If supported, check whether or not it is currently enabled (remember, the user can
turn BT on & off as with other communication channels):
boolean isEnabled = bluetoothAdapter.isEnabled(); // Equivalent to: getBluetoothState() == STATE_ON
And, if not enabled, allow the user to turn it on by firing an ACTION_REQUEST_ENABLE intent:
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, ENABLE_BT_CODE);
Once you are clear in terms of availability, perform lookup for the specific device you aim for.
It is always a good idea to start with the bonded device list maintained by Android:
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device: pairedDevices) {
if (device is the one we look for) {
return device;
}
}
If not, you will need to issue a BT discovery command.
Discovery must never be performed on the UI thread, so please spawn a thread (use AsyncTask, Executer, etc. to do the work).
Discovery should not be performed when a BT connection operation is still taking place. The
impact on the device resources will be too high.
Start by setting your discovery receiver:
discoveryReceiver = new BroadcastReceiver() {
private boolean wasFound = false;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
System.out.println(action);
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
discoveryStatus = STARTED;
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
discoveryStatus = FINISHED;
}
else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device is what we look for) {
stopDiscovery(context);
}
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(discoveryReceiver, filter);
And follow with a start off command:
boolean started = bluetoothAdapter.startDiscovery(); //async call!
if (!started) {
// log error
}
Once you find your device, you will then need to create a dedicated BT socket:
BluetoothSocket clientSocket = null;
try {
if (secureMode == SECURE) {
clientSocket = device.createRfcommSocketToServiceRecord(serviceUuid);
}
else { // INSECURE
clientSocket = device.createInsecureRfcommSocketToServiceRecord(serviceUuid);
}
if (clientSocket == null) {
throw new IOException();
}
} catch (IOException e) {
// log error
}
Followed by connect command:
clientSocket.connect(context);
Once connect returns, you can transmit data back & forth the way you do with sockets and when done:
clientSocket.close(context);
The above depicts the general flow. In many cases your work will be harder:
You will use different socket generation methods for secure vs. insecure BT modes. You will use different
methods to interrogate the device for supported UUIDs. You may also sometimes have to resort to reflection to activate hidden services e.g. getUuids() for Android < ver 15. And the list goes on.
It makes sense, especially for a beginner, to use a tool for this job.
My favorite (I am biased, I wrote it..) is BTWiz which will encapsulate the above
flow from you and will also provide you with a simple interface for async IO. Feel free to try it out.

Dynamically update a TextField without using AsyncTask

I've got a short question. How can I update a TextField without using an AsyncTask? In my Activity class I've got a function like this:
private void CheckBlueToothState(){
if (bluetoothAdapter == null){
status.setText("Bluetooth NOT support.");
}else{
if (bluetoothAdapter.isEnabled()){
if(bluetoothAdapter.isDiscovering()){
status.setText("Bluetooth is currently in device discovery process.");
}else{
status.setText("Bluetooth is Enabled");
search.setEnabled(true);
}
}else{
status.setText("Bluetooth is NOT Enabled");
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
}
Which checks if device got Bluetooth, is it enabled or disabled, you hopefully got the picture. So over to my question once again. How can I dynamically change the textfield status if I turn of the bluetooth, and vice versa?
Register BroadcastReceiver with intent action BluetoothAdapter.ACTION_STATE_CHANGED and move your text updating code into onReceive method.
Example code could be found here.

Bluetooth ToggleButton not checking state

I am developing an app that is going to use a ToggleButton to enable and disable BlueTooth. I manage to make the ToggelButton turn on and off BlueTooth, but I can not make it check if BlueTooth is turned on and off. The problem is that if you turn BlueTooth on or off from another location, you may turn off BlueTooth when you actually want to turn it on. Here is my code so far:
public void onClick(View v) {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if(adapter != null) {
if(adapter.getState() == BluetoothAdapter.STATE_ON) {
adapter.disable();
} else if (adapter.getState() == BluetoothAdapter.STATE_OFF){
adapter.enable();
} else {
//State.INTERMEDIATE_STATE;
}
}
}
How can I make it be checked when BlueTooth is on and unchecked when BlueTooth is off?
You will have to register a broadcast receiver with the following intent filter:
"android.bluetooth.intent.action.BLUETOOTH_STATE_CHANGED".
Whenever you receive this broadcast you should recheck for actual bluetooth state.
Check out Google's PowerWidget implementation.
The receiver with appropriate intent-filters is registered in the manifest.

Android: Creating a persistent event listener

I am trying to figure out how to implement an event listener (unsure if this is the proper term.) I want the service, once my app is launched, to listen for the phones power status. I am uncertain to as how android handles this situation so don't really know what to search for. I've been working with this code that uses a broadcast receiver:
BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
unregisterReceiver(this);
int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
if (plugged == BatteryManager.BATTERY_PLUGGED_AC) {
// on AC power
Toast.makeText(getApplicationContext(), "AC POWER", Toast.LENGTH_LONG).show();
} else if (plugged == BatteryManager.BATTERY_PLUGGED_USB) {
// on USB power
Toast.makeText(getApplicationContext(), "USB POWER", Toast.LENGTH_LONG).show();
startActivity(alarmClockIntent);
} else if (plugged == 0) {
Toast.makeText(getApplicationContext(), "On Battery", Toast.LENGTH_LONG).show();
} else {
// intent didnt include extra info
}
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, filter);
The code works fine. When I open my app it will toast what the current status of the phone power is.
Here is what I am trying to do:
When the user launches the app, it is effectively turning on the service
The user can go about using the phone, but once it is plugged in, my service will catch that and use the code above
How do I adapt this code to achieve the objectives above?
You could keep the listener on for the battery status by removing the line
unregisterReceiver(this);
This way, the app will continue to listen to power status change in the background even though that the app is not running in the foreground. Note that at some point, you might still want to unregister your receiver. You probably want to allow the user to control that via settings.
One other note, your code contains starting activity in the receiver in below code:
else if (plugged == BatteryManager.BATTERY_PLUGGED_USB) {
// on USB power
Toast.makeText(getApplicationContext(), "USB POWER", Toast.LENGTH_LONG).show();
startActivity(alarmClockIntent);
}
If your activity is in the background then it can't start another activity. See this SO Question - how to start activity when the main activity is running in background?, the accepted answer has suggestion on how to handle situation that requires starting activity from the background

Categories

Resources