I have the following code to handle lost Bluetooth connections.
public class BluetoothReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
//call method to cancel connection thread
}
}
}
However, I have another app that uses Bluetooth connected to a different device running in the background. If I lose connection to that device, I also lose the connection to the device within this app.
I was wondering, is there any way to prevent this?
As described here you are able to get the device instance from the intent with intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) If the device is NOT the one you are interested in, just DO NOT call:
//call method to cancel connection thread
Related
I was trying to pair a BLE device programmatically from my android app.So at first I register a BroadcastReceiver for PAIRING_REQUEST.When device.createBond() is called ,the BroadcastReciever is triggered. When the BroadcastReciever is triggered, I set the passkey by using setpin(). But the problem is pairing request dialog box appeared sometimes and sometimes without appearing pairing box pairing is done automatically . I want that it will never show any dialog box but it should be paired with the passkey programmatically.
Any solution of it ?
Or is there any way to fulfill my expectation?
Thanks in advance.
Registered broadCasterReciever during application launching
IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
appContext.getApplicationContext().registerReceiver(broadCastReceiver,intentFilter);
Implementation of broadcastReciever.
private String BLE_PIN= "000012";
private BroadcastReceiver broadCastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action))
{
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
bluetoothDevice.setPin(BLE_PIN.getBytes());
Log.e("TAG","Auto-entering pin: " + BLE_PIN);
}
}
};
And I called device.createBond() after discovering the device.
calling abortBroadcast(); after setPin() solved the problem for me.
In my application I have to get notified whenever the device connects or disconnects from a WIFI network. For this I have to use a BroadcastReceiver but after reading through different articles and questions here on SO I'm a bit confused which Broadcast action I should use for this. In my opinion I have three choices:
SUPPLICANT_CONNECTION_CHANGE_ACTION
NETWORK_STATE_CHANGED_ACTION
CONNECTIVITY_ACTION
To reduce resources I really only want to get notified whenever the device is CONNECTED to a WIFI network (and it has received an IP address) or when the device has DISCONNECTED from one. I do not care about the other states like CONNECTING etc.
So what do you think is the best Broadcast action I should use for this? And do I have to manully filter the events (because I receieve more then CONNECTED and DISCONNECTED) in onReceive?
EDIT: As I pointed out in a comment below I think SUPPLICANT_CONNECTION_CHANGE_ACTION would be the best choice for me but it is never fired or received by my application. Others have the same problem with this broadcast but a real solution for this is never proposed (in fact other broadcasts are used). Any ideas for this?
You can go for WifiManager.NETWORK_STATE_CHANGED_ACTION works.
Register receiver with WifiManager.NETWORK_STATE_CHANGED_ACTION Action, either in Manifest or Fragment or Activity, which ever suited for you.
Override receiver :
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)){
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
boolean connected = info.isConnected();
if (connected)
//call your method
}
}
Please try
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction("android.net.wifi.STATE_CHANGE");
registerReceiver(networkChangeReceiver, filter);
}
#Override
protected void onDestroy() {
unregisterReceiver(networkChangeReceiver);
super.onDestroy();
}
and
BroadcastReceiver networkChangeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (!AppUtils.hasNetworkConnection(context)) {
showSnackBarToast(getNetworkErrorMessage());
}
}
};
I am using this and it is working for me. Hope it will help you out.
I have registered a BroadcastReceiver to receive ACTION_HEADSET_PLUG which works fine for most devices, ie it is called whenever the headset is plugged or unplugged. But on others eg the ZTE T815, the Intent is never sent/received when the headset is plugged/unplugged.
For reference here is the code for the receiver registration:
private final BroadcastReceiver headsetPlugReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received intent=" + intent);
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_HEADSET_PLUG)) {
// do stuff
}
}
};
public void onCreate(Bundle savedState) {
super.onCeate(savedState);
// ...
registerReceiver(headsetPlugReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
}
Further info:
The Intent is dispatched but only after the HEADSET_HOOK command is fired on the headset.
And when the Intent is dispatched
final int microphone = intent.getIntExtra("microphone", 0);
always returns 0 (ie no microphone).
So
Is there some config/code that can force the delivery of this
Intent?
How do I get the Intent to correctly report whether a
microphone exists or not?
It turns out the ZTE T815 has an OMTP TRRS config for its audio socket instead of CTIA/AHJ like every other modern Android device.
See http://en.wikipedia.org/wiki/Phone_connector_%28audio%29
A sad state of affairs, especially when trying to use audio feed inpout across products.
Normally how Android Broadcast work is: app have to create BroadcastReceiver and have to register action intent for it want to get receive event.
But in case of Bluetooth device discovery/scanning why it required request call through BluetoothAdapter.startDsiccovery().
Basically I want to dicover BLE device through long live Service running in Background.
Any one have idea here?
private void listenPairedDevice() {
Button listenBtn = (Button)findViewById(R.id.button_listen);
listenBtn.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
Intent disc = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(disc, DISCOVERY_REQUEST);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DISCOVERY_REQUEST) {
boolean isDiscoverable = resultCode > 0;
if (isDiscoverable) {
String name = "bluetoothserver";
try {
final BluetoothServerSocket btserver = bluetooth.listenUsingRfcommWithServiceRecord(name, uuid);
AsyncTask<Integer, Void, BluetoothSocket> acceptThread = new AsyncTask<Integer, Void, BluetoothSocket>() {
#Override
protected BluetoothSocket doInBackground(Integer... params) {
try {
socket = btserver.accept();
return socket;
} catch (IOException e) {
Log.d("BLUETOOTH", e.getMessage());
}
finally {
//close statement added later by MR
try{
btserver.close();
} catch (IOException e){
}
}
return null;
}
#Override
protected void onPostExecute(BluetoothSocket result) {
if (result != null)
changeLayout();
}
};
acceptThread.execute(resultCode);
} catch (IOException e) {
Log.d("BLUETOOTH", e.getMessage());
}
}
}
The startDiscovery() does a 2 step process,
Finding the device by inquiring for it.
Followed by a name discovery ie paging and connecting to the device.
If you have gone through the docs it says public boolean startDiscovery ()
Start the remote device discovery process.
The discovery process usually involves an inquiry scan of about 12 seconds, followed by a page scan of each new device to retrieve its Bluetooth name.
This is an asynchronous call, it will return immediately. Register for ACTION_DISCOVERY_STARTED and ACTION_DISCOVERY_FINISHED intents to determine exactly when the discovery starts and completes. Register for ACTION_FOUND to be notified as remote Bluetooth devices are found.
Device discovery is a heavyweight procedure. New connections to remote Bluetooth devices should not be attempted while discovery is in progress, and existing connections will experience limited bandwidth and high latency. Use cancelDiscovery() to cancel an ongoing discovery. Discovery is not managed by the Activity, but is run as a system service, so an application should always call cancelDiscovery() even if it did not directly request a discovery, just to be sure.
Device discovery will only find remote devices that are currently discoverable (inquiry scan enabled). Many Bluetooth devices are not discoverable by default, and need to be entered into a special mode.
If Bluetooth state is not STATE_ON, this API will return false. After turning on Bluetooth, wait for ACTION_STATE_CHANGED with STATE_ON to get the updated value.
Requires BLUETOOTH_ADMIN.
Returns
true on success, false on error
EDIT
Plese follow Bluetooth device discovery in Android — startDiscovery()
I think you have to start on Bluetooth discovery using UUId and socket.
After getting any device you have to set up a connection to this and start a thread that will check regularly while it is connected or not.
Scanning for peripherals is not just a heavy-weight task, it is also not friendly to the battery so it can't be left on all the time.
That said, you can still have something in the background doing the work for you, like something that wakes up every 15 seconds and scans for 5 seconds. On some devices when you try to connect to a device that is no longer available you will get a disconnected callback to onConnectionStateChange in the BluetoothGattCallback, and on other devices the same connection attempt will wait until the device is back and then connect.
So basically, wait, scan, connect if you find your device and if not then wait again.
I'm writing a code that listens for the Bluetooth device to become disconnected, then does something. How would I go about doing this? I'm not exactly sure what I want to put after it yet, figured I'd get this sorted out first. Hopefully I wasn't completely wrong with this code, as I'm new to developing. This is what I have so far:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (BluetoothAdapter.ACTION_ACL_DISCONNECTED.equals(action))
{ // This will be the followup action, once I figure out what I want it to be.
First, use the BluetoothChat example to start with as coding with Bluetooth is pretty complex and it's nice to have working code. What you want to look at is handleMessage() in BluetoothChat.java, and you'll need to save off the state. When the state changes from BluetoothChatService.STATE_CONNECTED to BluetoothChatService.STATE_NONE, the device has become disconnected.