Problems with Bluetooth discovery - java

So I need device A (client) to connect to device B (server) and I've gotten it to work, but not in all cases. Upon opening the app, I want to allow the device to be discovered
private void enableDiscoverability() {
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
3600);
startActivity(discoverableIntent);
}
, and i set up a receiver to look for one specific device (just for now, I'm still learning how to use Bluetooth)
private final BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
TextView output = findViewById(R.id.output);
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 temp = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = temp.getName();
Log.i("Device ", deviceName + " was found");
String deviceHardwareAddress = temp.getAddress();
if (deviceHardwareAddress.equalsIgnoreCase("DC:F7:56:DD:73:8F")) {
device = temp;
startClient();
}
}
}
};
So here is my problem. When device A is left on, it'll discover new devices for a little while, but it won't discover the new device B after a few minutes. Both devices should have a receiver and should be discoverable.
Is there a timeout when you're discovering devices? Would something happen to the receiver if it tried to connect but failed? I've tried to look it up, but I'm still new with Bluetooth so I wouldn't know where to begin. I'd be more than happy to post more code if need be

Yes. Every device has a discovery timeout. Best place to start is bluetooth.com, with huge amount of videos and documents. There is timeout for every activity in Bluetooth such as discovery, connection, data transmission etc.

Related

Why am I not able to connect to device via Bluetooth android?

I am able to pair devices with the android studio app but I get the tag
"CouldNotConnectToSocket" even though the device is paired.
I am new to android studio so I am really stuck with where to go next.
I also get
getBluetoothService() called with no BluetoothManagerCallback
The UUID I created is:
private final static UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Can anyone please help me?
new Thread() {
#Override
public void run() {
device = BA.getRemoteDevice(address);
try {
BTSocket = device.createRfcommSocketToServiceRecord(BTMODULEUUID);
//BTSocket = createBluetoothSocket(device);
Log.d(TAG, "Device Connected");
BA.cancelDiscovery();
BTSocket.connect();
} catch (IOException ex) {
Log.d(TAG, "CouldNotConnectToSocket");
closeSocket(BTSocket);
}
}
}.start();
The issue I found out was that the devices I was trying to connect to send data back and forth require Bluetooth Low Energy support from the app.

Android WifiInfo.getIpAddress returns 0 Android on Nexus 5X with Android 6

Here is what I am doing:
I register a BroadcastReceiver like this:
mConnectionChangeReceiver = new ConnectionChangeReceiver();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mContext.registerReceiver(mConnectionChangeReceiver, filter, null, handler);
Then I automatically try connect to a specific WiFi. Something like this:
if (!mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(true);
}
mWifiManager.enableNetwork(mCurrentNetworkId, true);
I get the broadcast receiver events as expected. Inside onReceive() I check for the SSID and for SuplicantState. The problem is when I try to get the phone ip address. WifiInfo.getIpAddress returns 0 if the cellular network is enabled on the phone but it works if it is disabled.
Please note that this will work if the device was already connected to SSID in both cases (with/without cellular network). For this to happen wifi must de off or the phone must be connected to another wifi before running the code.
Here's the code:
public void onReceive(Context context, Intent intent) {
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
//..... Here's the code that compares SSID
if (isConnectedToSSID() && (wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {
mIpAddress = NetworkHelper.getIpAddress(wifiInfo);
}
}
public static String getIpAddress(WifiInfo pWifiInfo) {
int ipAddress = pWifiInfo.getIpAddress();
if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
ipAddress = Integer.reverseBytes(ipAddress);
}
byte[] ipByteArray = BigInteger.valueOf(ipAddress).toByteArray();
String ipAddressString = null;
try {
ipAddressString = InetAddress.getByAddress(ipByteArray).getHostAddress();
} catch (UnknownHostException ex) {
ex.printStackTrace();
}
return ipAddressString;
}
Any ideas why this happens?

Optimal way for a daily network operation

I am kinda confused at the moment. What is the "correct" / "optimal" way for a daily network operation in an android app?
Pseudocode:
If newDay
HTTP Request to server
If responseOfRequest equals something
Do something
If HTTP Request is unsuccessfull (no internet, server down, ...)
Try again in 1 hour
How can I achieve that? I thought about a JobService but my minSDK is below Android 5.
Cheers,
DDerTyp
What you need is a service to run the logic in the background and an alarm.
A little bit of theory first:
https://developer.android.com/training/scheduling/alarms.html#tradeoffs
A repeating alarm is a relatively simple mechanism with limited flexibility. It may not be the best choice for your app, particularly if you need to trigger network operations. A poorly designed alarm can cause battery drain and put a significant load on servers.
If you own the server that is hosting your app's data, using Google Cloud Messaging (GCM) in conjunction with sync adapter is a better solution than AlarmManager.
https://developer.android.com/training/sync-adapters/running-sync-adapter.html
By default, all alarms are canceled when a device shuts down.
You will need to set up the alarm somewhere in your app, at the beginning, but saving a flag because you don't want to set up this alarm every time the user opens the app
if (!appSettings.isAlarmSetUp()) {
final AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
final Intent i = new Intent(context, CustomService.class);
final Intent intentNotRepeat = new Intent(context, CustomService.class);
final PendingIntent pi = PendingIntent.getService(context, 0, i, 0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_DAY, pi);
appSettings.setAlarmSetUp(true);
}
Here more info about alarms:
https://developer.android.com/training/scheduling/alarms.html#type
As you can see, this alarm is waking up a CustomService, where you will do all your logic
public class CustomService extends IntentService {
public CustomService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
// Request to server
client.requestToServer()
.subscribe(response -> {
// Successful response
doSomething(response);
}
},
error -> {
// Error
createAlarmInOneHour();
});
}
}

android connecting to wifi WifiManager.SUPPLICANT_STATE_CHANGED_ACTION strange issue

I am having an issue when try to connect to wireless network.
My code works ok I sucessfully connect to the network whit the problems described below.
I have a listview whit the wifi scan results.
When I click the first time my receiver is not getting the "completed" state.
After clicking the second time , and , without chosing any network it get connected and my code inside the "complete" is executed.
The code below is called from another class that thre reason why it is static
Coonect Code:
public static boolean connect(String ssid,String password)
{
String networkSSID = ssid;
String networkPass = password;
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";
conf.preSharedKey = "\""+ networkPass +"\"";
//WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
int netid=mainWifi.addNetwork(conf);
mainWifi.disconnect();
mainWifi.enableNetwork(netid, true);
//mainWifi.reconnect(); <-- exact the same issue discommenting this line
return true;
}
On the class were the connect is been called I have registered BradcastReceiver as follow:
public void onClick(View v)
{
mainWifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiinfo = mainWifi.getConnectionInfo();
AuthWifi authWifi = new AuthWifi();
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
getApplicationContext().registerReceiver(authWifi, mIntentFilter);
ClientManager.scan(CameraActivity.this, mainWifi);
}
my broadcast receiver
public class AuthWifi extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
SupplicantState supl_state = ((SupplicantState) intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
switch (supl_state) {
case COMPLETED:
/////////////IF I AM CONNECTED THE WIFI SSID I CHOSE FROM A LISTVIEW THEN ---->
if(wifiinfo != null & wifiinfo.getSSID()!=null & ClientManager.getSSID() !=null& !conectado ) {
if (wifiinfo.getSSID().contains(ClientManager.getSSID().trim())) ///I know here is better .equals() /// I have contain for my own reasons
conectado = true;
/*HERE I DO SOME THINGS WHEN CONNECTED (I CALL A RUNNABLE TO MAKE A SERVER SOCKET)*/
}
}
break;
case DISCONNECTED:
Log.i("SupplicantState", "Disconnected");
conectado = false;
if (ClientStartReceive.isStopped)
{
ClientStartReceive.stop();
}
break;
default:
Log.i("SupplicantState", "Unknown");
break;
}
int supl_error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
if (supl_error == WifiManager.ERROR_AUTHENTICATING) {
/////HERE I MANAGE AUTHENTICATION ERROR
}
}
}
}
Hope someone is able to help :( if you need more code to troubleshoot please let me know.
If you have some reference to help me even if i need to rebuild the code is accepted also.. My goal is be able to connect to a network ,show for authentication errors and execute some code on connection susscess.
Sorry for my english I think you have gessed I am not native.
Regards
As doc indicate that “COMPLETED“ use as follow:
This state indicates that the supplicant has completed its processing for the association phase and that data connection is fully configured. Note, however, that there may not be any IP address associated with the connection yet.
You should not rely this state to ensure your connection is completed. Instead, you can register an BroadcastReceiver listener for network status change.

How to retrieve Bluetooth Address through Name from Paired/bonded device list?

I actually do this when I'm discovering devices:
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mDiscovery, filter);
And in my in my Broadcastreceiver:
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
And then I can do device.getName() and device.getAddress().
My problem is, I only know how to do this with an intent for the discovery. So, android devices as fair as I know have list with paired devices with their names as respective addresses.
Given the name, how can I directly (without discovery and so without a broadcast receiver) get the address?
After you created an object of your BluetoothAdapter ( let's say mBluetoothAdatper) you can get a list with all of the bonded(paired) devices with mBluetoothAdapter.getBondedDevices().
More information on this link.

Categories

Resources