I was going through BluetoothGatt.java and found the method boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
Handler handler)
The documentation just above this method specifies that this is used to initiate a connection with BLE devices.
However, the official Android documentation states that to connect with a BLE device boolean connect() should be used.
The documentation for this connect() method states that this is used to reconnect back to a device.
I am confused here because gatt.connect() is sometimes unreliable (the callback for the device connected is not called even though the BLE device is in range but connects when I try to connect in the second or third attempt.)
Would it be better to use the method mentioned earlier to increase connection chances during first connection attempt?
Can anyone share some information regarding this?
However, the official Android documentation states that to connect with a BLE device Boolean connect() should be used.
Above method is the Bluetooth Gatt method that will help you connect with ble device .
after successful connection , BluetoothGatt will call BluetoothGattCallback , that have different override methods .
As per My implementation , I discovered the device using BluetoothAdapter.LeScanCallback that is used for lower version. After that :-
private void addDeviceItem(BluetoothDevice device, int rssi) {
String penAddress = device.getAddress();
mBluetoothLeService.connect(penAddress );
}
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
// refreshDeviceCache(mBluetoothGatt);
Log.d(TAG, "Trying to create a new connection.");
mConnectionState = STATE_CONNECTING;
return true;
}
I will always connect with the device , after finish with Bluetooth , you have to disconnect with device by calling Gatt.disconnect(). then again make connection using above code.
My answer at Which correct flag of autoConnect in connectGatt of BLE? should explain everything.
Basically, a "direct connect" has a higher duty of the scan window / interval than an "auto connect". That's why an auto connect can take very long time if you have a long advertising interval on the peripheral.
Related
I have an industrial computer running Android v7 with multiple serial outputs, I am trying to send packets using RS232 to my COM3 port (/dev/ttyS2) nevertheless I am unable to open a connection since my serial drivers are not detected.
The cable is well connected and I don't have any issues communicating when running a NodeJS script.
Here is the code used in the Android App
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
/*[...]*/
public static UsbSerialPort usb2SerialEnum(Context context)
{
UsbSerialPort device = null;
// Find all available drivers from attached devices.
UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
if (availableDrivers.isEmpty())
{
return null; // -> availableDrivers is always empty
}
/*[...]*/
}
protected void onCreate(Bundle savedInstanceState)
{
UsbSerialPort port = usb2SerialEnum(this);
if (port != null)
{
/*[...]*/
}
}
I always receive an empty list of available drivers, would you have any idea about what am I doing wrong or what I should try ?
I have been stuck on this issue for quite some time, any help is appreciated, thanks a lot !
Is there any way to automatically connect a specific device via Bluetooth LE on app startup?
I've been scrolling through stack overflow for the past few hours and have seen a number of similar questions, although majority are quite outdated and deal with reflections or other complex methods that I can't quite comprehend (these methods I've tried to implement, but not successfully, as I didn't really understand what was going on).
So far, I've managed to find the device by its friendly name, although I have no clue what to execute in that if statement. This is within my MainActivity:
protected void onCreate(Bundle savedInstanceState) {
...
if (bluetoothAdapter == null) {
Toast.makeText(getApplicationContext(),"Bluetooth not supported",Toast.LENGTH_SHORT).show();
} else {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if(pairedDevices.size()>0){
for(BluetoothDevice device: pairedDevices){
if (deviceName.equals(device.getName())) {
//Device found!
//Now how do I pair it?
break;
}
...
Assuming you've successfully identified the BlueToothDevice, you now need to connect to the GATT(Generic Attribute Profile), which allows you to transfer data.
Use the BlueToothDevice.connectGatt method. Using the first overload, the method takes in a Context , a boolean (false = directly connect, true = connect when available), and a BlueToothGhattCallback. The callback receives info from the device.
BlueToothGatt blueToothGatt = device.connectGatt(this, false, blueToothGattCallback);
An example to implement the callback:
BluetoothGattCallback blueToothGattCallback =
new BluetoothGattCallback()
{
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if(newState == BlueToothProfile.STATE_CONNECTED){
/* do stuff */
}
}
}
More details on the callbacks here.
Ended up scrolling through the source code for this app, particularly the SerialSocket, SerialService and SerialListener files which completely solved my problem.
This question might be a duplicate question, but i cant find proper solution.
I have chat app in which i set function for when remote android device on background mode it will get notification by FCM when new message will come(new node added in chatroom).
So
if remote device is in the foreground mode than it will get notification by app and its has definitely internet connectivity for this i can set message delivery successfully.
if remote device is in the background mode than it will get notification by FCM and its has definitely internet connectivity. for this i can also set message delivery successfully.
So how do i check that remote device is totally offline(no internet connection) or how to check FCM is not success to send notification ?
for example:
if(messegeReceiver(remote device) has no internet connectivity )
{
//here i want to change data in firebase//
}
else
{
//here i want to change data in firebase//
}
I have "Users" node in which every users set device_token while login the app.
You can device checking offline/online mode via set one param in your chat table. When user exit or minimize application then set states to 0 and maximum set to 1.Best way if possible you use firebase real-time database for online offline.
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
NetworkChangeReceiver receiver = new NetworkChangeReceiver();
regisenter code hereterReceiver(receiver, filter);
public static class NetworkChangeReceiver extends BroadcastReceiver {
public static boolean isOnline(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
//should check null because in air plan mode it will be null
return (netInfo != null && netInfo.isConnected());
}
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
if (!isConnected) {
relativelayout_connection.setVisibility(View.GONE);
isConnected = true;
return true;
}
} else {
relativelayout_connection.setVisibility(View.VISIBLE);
}
}
}
} else {
relativelayout_connection.setVisibility(View.GONE);
isConnected = false;
return false;
}
return isConnected;
}
#Override
public void onReceive(final Context context, final Intent intent) {
// isNetworkAvailable(context);
if (isOnline(context)) {
} else {
relativelayout_connection.setVisibility(View.VISIBLE);
}
}
}
FCM does not guarantee that the push notification gets delivered. It completely depends upon various factors like internet connection (as you mentioned), OEM behavior, Doze mode etc.
In your case, you are trying to send messages via FCM from one device to another and shown messages in the form notifications just like any other chat application.
The only problem here is that the FCM does not provide you with delivery parameters in response (image attached) that you are looking for. It only gives count for number of notifications that has been accepted by the gateway i.e. FCM (success) and the count for number of notifications that has been rejected by the gateway (failure). It also gives the reason for rejection (error) message like NotRegistered, MissingRegistrationToken, etc and you can refer this for the same.
My suggestion here would be to have a handshake message in place that acknowledges the delivery of the push notification from the other device. As soon as you receive the push notification send a handshake message via FCM and that gets received by the first device which understands that the push notification has been delivered. In case if the device does not receive the handshake you assume that the message is yet to be delivered.
I hope this really helps you and please up vote the answer or accept the answer if you feel like doing so.
I'm trying to use an Android device to connect to Bluetooth devices to retrieve some information. In particular I'm trying to connect to Bluetooth headphones on this UUID:
"0000111E-0000-1000-8000-00805F9B34FB"
To do this I'm creating a socket and connecting it to the remote device this way:
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket
// because mmSocket is final.
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothSocket tmp = null;
mmDevice = device;
try {
// Get a BluetoothSocket to connect with the given BluetoothDevice.
// MY_UUID is the app's UUID string, also used in the server code.
tmp = device.createRfcommSocketToServiceRecord(UUID_HF);
} catch (IOException e) {
Log.e(TAG, "Socket's create() method failed", e);
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it otherwise slows down the connection.
bluetoothAdapter.cancelDiscovery();
try {
// Connect to the remote device through the socket. This call blocks
// until it succeeds or throws an exception.
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and return.
try {
mmSocket.close();
} catch (IOException closeException) {
Log.e(TAG, "Could not close the client socket", closeException);
}
return;
}
// The connection attempt succeeded. Perform work associated with
// the connection in a separate thread.
manageMyConnectedSocket(mmSocket);}
It works fine when the headphones are not yet connected with my Android device. But what happens is that the headphones connect automatically with my Android device thanks to the OS itself. And in this case, when I execute the mmSocket.connect() method, it does not return. I thought that maybe Android has connected automatically another socket with the same UUID and so mine doesn't work. Do you think this is the problem? And if it is, is there a way to close all the sockets between my Android device and a remote Bluetooth device? Or maybe just the one that is bothering my process?
Thanks in advance.
what actually happens is the OS is doing the paired device criteria to save some battery as the searching process consume a lot of energy.
since you've done the search you should go for searching in paired devices not normal search and the result of the search should be taken from
Query paired devices
Before performing device discovery, it's worth querying the set of paired devices to see if the desired device is already known. To do so, call getBondedDevices(). This returns a set of BluetoothDevice objects representing paired devices. For example, you can query all paired devices and get the name and MAC address of each device, as the following code snippet demonstrates:
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// There are paired devices. Get the name and address of each paired device.
for (BluetoothDevice device : pairedDevices) {
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
}
}
To initiate a connection with a Bluetooth device, all that's needed from the associated BluetoothDevice object is the MAC address, which you retrieve by calling getAddress(). You can learn more about creating a connection in the section about Connecting Devices.
this is the official documentation from google covering every detail about Bluetooth:
https://developer.android.com/guide/topics/connectivity/bluetooth
Bluetooth.class
//method inside this class
private void enableBT()
{
getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH))
{
Log.d(TAG, "ble_not_supported");
finish();
}
}
}
You need to check whether the device supports bluetooth or not.
If you are running this on emulator. The emulator does not generally support bluetooth which will return you a null for
BluetoothAdapter.getDefaultAdapter();
You can try using this before the bluetooth operation:
getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
OR
getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
This will tell you whether the bluetooth feature exists or not.