What´s the main difference between the WifiManager disableNetwork() and disconnect() method?
If I´m not guessing wrong, the disconnect() method makes it candidate for a reconnect when it enters inside the visibility of the wifi hotspot but disableNetwork() don't.
public boolean disableNetwork (int netId). Disable a configured network. The specified network will not be a candidate for
associating. This may result in the asynchronous delivery of state
change events.
public boolean disconnect () Disassociate from the currently active access point. This may result in the asynchronous delivery of
state change events.
I´ve a Wiko Darkmoon (Android 4.2.2) device for testing purposes and when I call disconnect() it reconnects some seconds later to the same wifi point without taking in mind higher priority networks neither the quality of the signal.
So my questions are:
What's the difference between disableNetwork() and disconnect() method?
It´s my guess right?
It´s the Wiko's implementation the right one or it´s the one misfiring?
When roaming between two wifi spots with same SSID and after calling disconnect() will it filter by SSID or MAC for the reconnect?
Thanks
disconnect() as name suggests just disconnects the device from current Wi-Fi network. If the device connects later to the same or another network is dependent on the device settings and is completely unrelated to the method call.
disableNetwork(int) will prevent automatic connection to the specified network.
Related
The moment I get on a wifi connection, the cellular network is completely lost even though the cellular network indicator is definitely on.
This is my network request
val request = NetworkRequest.Builder().run {
addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
build()
}
connectivityManager.registerNetworkCallback(request, callback)
I've tried looking in the connectivityManager.allNetworks list and it's no where to be found. Only the wifi network is in there.
What's even weirder is there is one other cellular network that is always there. It does not have the same ID as my cellular network. There's no connection that can be made with it. It never shows up with registerNetworkCallback. The capabilities on it always include "valid" and "internet"
What am I seeing here? Why is my cellular network lost? What is this phantom cellular network?
targetSdkVersion: 29
Device: Galaxy S10 - Android 12
I figured this out.
If you call registerNetworkCallback the above will happen, but if you call requestNetwork with TRANSPORT_CELLULAR,
connectivityManager.requestNetwork(request, callback)
Android will keep the cellular network around. I was so confused because the documentation was so lacking. Once you do that, it will ask you to add the CHANGE_NETWORK_STATE permission.
After this step, the network is available, but you won't be able to make any request with it. You have to call
connectivityManager.bindProcessToNetwork(theCellularNetwork)
to get any connection.
After this is done, the cellular network can be used in tandem with the wifi network. You can even send some traffic to one and some to the other. If you use OkHttp like I do, you just bind the client with the network's socketFactory
val client = OkHttpClient().newBuilder().run {
socketFactory(network.socketFactory)
build()
}
client.newCall(
Request.Builder().url("https://example.com").build()
).execute().let {
Log.i(TAG, "Fetched ${it.body!!.string()}")
}
The cellular network isn't lost, but your app isn't allowed to use it. Once WiFi is connected, everything is forced to use that connection. The only exception to this rule is if your phone has a feature called "Dual Acceleration", which allows the cellular connection to stay active (and obviously, the user would have to enable that feature). Alternatively, you may have a setting in your phone's Developer Options called "Cellular Data Always Active", which will do the same thing.
But needless to say, you can't rely on either of those 2 features being enabled in a production environment. So, just assume that when WiFi is connected, that's the only connection that your app can use
I have a ble device that I need to regularly extract data from securely and constantly. So on startup I want to make sure to bond the device if it is not already. I have the Mac address of the device in this case.
public void startApp(){
remoteDevice = bluetoothManager.getAdapter().getRemoteDevice(MAC_AD);
if(remoteDevice.getBondState()!=12){
remoteDevice.createBond();
}
}
What ends up happening is that the bond state will alternate between unbonded and currently_bonding but not fully bond.
The strange thing is that sometimes it will work, but usually not, particularly on my google pixel. Bonding through the settings is also very inconsistent.
Is there any way to retry this or some kind of Bluetooth reset that should be done so that I can bond consistently?
I've tried calling createBond() in intervals;
I've often found that calling createBond() directly can have hit-and-miss results depending on the platform (both ends). Logically it should use the same mechanism internally, but I've tended to get better results by calling read on a simple characteristic which has bonded requirements.
It either successes - meaning your connection is bonded - and you can continue. Or it fails, which internally triggers the bonding, and then you can try again after a short delay, at which point it should now be bonded.
I am creating a WifiP2pGroup with WifiP2pManager.connect(). This works fine but the group is always disbanded after thirty minutes, no matter whether data is being transferred or not. Does anyone know why this happens, or if it can be prevented?
I have tried sending data continuously between the devices and keeping the screens on the entire time with a wake lock but it makes no difference. I have made sure wifi is set not to sleep, and also obtained a wifilock, and turned off battery optimization for the app and for wifi direct, but these don't help either. After thirty minutes (or to be specific, 29m 18s - it's very consistent) I get the CONNECTION_STATE_CHANGE broadcast and the devices are no longer paired.
The devices are a Nexus 7 running Android 7 (LineageOS) and a Samsung Galaxy A5 running Android 6.
Thanks!
Edit: I have tried running with mobile data off and wifi not connected. The app is not being paused or destroyed and no other apps have permission to change the wifi state. In the wifi logs on one of the devices I found this event around the time of the disconnection:
E/DhcpStateMachine: DHCP renew failed on p2p-wlan0-0: Timed out waiting for DHCP Renew to finish
D/WifiP2pService: GroupCreatedState{ what=196613 }
E/WifiP2pService: DHCP failed
On the other device I found this at the beginning of the disconnect process:
552-813/system_process V/WifiHAL: event received NL80211_CMD_DEL_STATION
552-846/system_process D/WifiMonitor: Event [IFNAME=p2p-p2p0-11 AP-STA-DISCONNECTED b6:22:8b:b1:df:0f p2p_dev_addr=f2:62:6f:d1:5f:0c]
552-846/system_process D/WifiMonitor: p2p0 cnt=6442 dispatchEvent: AP-STA-DISCONNECTED b6:22:8b:b1:df:0f p2p_dev_addr=f2:62:6f:d1:5f:0c
552-629/system_process D/WifiP2pService: Client list empty, remove non-persistent p2p group
The following looks like the DHCP lease for the 2 peers is 30 minutes and the renew is failing.
E/DhcpStateMachine: DHCP renew failed on p2p-wlan0-0: Timed out waiting for DHCP Renew to finish
D/WifiP2pService: GroupCreatedState{ what=196613 }
E/WifiP2pService: DHCP failed
The service advertiser and service browser have IP addresses, the browser's issued by DHCP on the advertiser. If the DHCP fails to renew, then the connection is lost and the devices have to reconnect. It looks like the lease renewal is attempted at 29 min 18 sec, and times out at the 30-minute lease time. At this point the browser has to reconnect. If the DHCP server doesn't remember the browser's IP address,or if the framework always issues a new IP, then what you describe will happen. Hope this helps.
Edit: this post seems to validate that the group owner acts as a DHCP server: Get peer device's IP address in wifi-direct p2p connection . I don't know how you could increase the lease time on WiFi-Direct, though.
Edit: this link talks about some problems with DHCP on android: https://www.net.princeton.edu/android/android-stops-renewing-lease-keeps-using-IP-address-11236.html
Edit: Possible solution is contained in https://www.net.princeton.edu/android/android-11236-partial-workaround.html , appended below. The idea is to use settings on the group owner's device.
Procedure
Depending upon the version of Android on your device, there should be a "Wi-Fi sleep policy" setting, a "Wi-Fi disconnect policy" setting, or a "Keep Wi-Fi on during Sleep" setting. (Your device will have only one of these; the name varies.) It should be available at (only) one of the following locations:
Settings
-> Wireless & networks
-> Wi-Fi settings
-> Menu (button)
-> Advanced
-> Wi-Fi sleep policy
Settings
-> Wireless & networks
-> Wi-Fi settings
-> Wi-Fi disconnect policy
Settings
-> Wireless & networks
-> Wi-Fi settings
-> Menu (button)
-> Advanced
-> Keep Wi-Fi on during Sleep
If the Wi-Fi settings item is greyed-out, you may need to turn on Wi-Fi before you can select this item.
If your device has a "Wi-Fi sleep policy" or " Wi-Fi disconnect policy", it should offer several choices. These choices available vary among different versions of Android. At least one of the choices should be "After 15 mins" or "When screen turns off". Select that choice.
Otherwise, if your device has a "Keep Wi-Fi on during Sleep" setting, it should offer several choices. These choices available may vary among different versions of Android. At least one of the choices should be "Never". Select that choice.
If you have any software installed on your Android device which modifies the way Android turns Wi-Fi on or off, then reconfigure that software so it no longer controls the device's Wi-Fi interface. Alternatively, disable or remove that software.
An example would be an application designed to keep your device's Wi-Fi interface always turned on. Another would be an application configured to turn on your device's Wi-Fi interface based on certain conditions (for example, location, time of day, or battery charge).
These applications are not the cause of the bugs. However, they can prevent this partial workaround from being effective, because these may be configured to override Android's "Wi-Fi Sleep Policy" (or "Wi-Fi disconnect policy"), causing the Wi-Fi interface to remain connected to the wireless network for an extended period while the Android device is asleep.
Every time you upgrade the Android software/firmware in the future, verify that the setting you selected above (the "Wi-Fi sleep policy", "Wi-Fi disconnect policy", or "Keep Wi-Fi on during Sleep" setting) remains configured as described above. Such upgrades sometimes modify existing settings; you must make a point of checking (and if necessary, changing) this setting immediately after upgrading.
Take care that any software you install in the future does not modify the way Android turns on or off Wi-Fi.
Digging through the sources for p2, the bottom line is that dhcp stuff for p2p is done by ethernetworkfactory, bypassing the native dhcp server (see http://book2s.com/java/src/package/com/android/server/ethernet/ethernetnetworkfactory.html#199b9c81a59238cafe64b4e28b0c71ce), and here's an interesting code fragment:
/* Called by the NetworkFactory on the handler thread. */
public void onRequestNetwork() {
// TODO: Handle DHCP renew.
so it appears that the dhcp lease will never renew in the p2p framework (see below). Frankly, I'd have to check on that; this is a nontrivial bug if true. If it is true, then the solution of reconnecting every 25 mins as per the above post may be the only way. Note: dhcp renewal happens at 48% of the lease renewal time to run previous to the native dhcp renew (see https://android.googlesource.com/platform/frameworks/base/+/c3a2858/core/java/android/net/DhcpStateMachine.java); the relevant lines are
//Do it a bit earlier than half the lease duration time
//to beat the native DHCP client and avoid extra packets
//48% for one hour lease time = 29 minutes
So in p2pdirect, it looks like there is a layer that avoids the native dhcp renewal but doesn't implement it itself.
you can develop a service. and then reconnect after every 25 minutes programmatically.
or
public class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conMan.getActiveNetworkInfo();
if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI)
Log.d("WifiReceiver", "Have Wifi Connection");
else
Log.d("WifiReceiver", "Don't have Wifi Connection");
}
};
In order to access the active network info you need to add the following uses-permission to your AndroidManifest.xml:
And the following intent receiver (or you could add this programmatically...)
<receiver android:name=".WifiReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
[reference:] [Wifi Connect-Disconnect Listener1
thus you can solve your problem. :)
This appears to be a bug in the LineageOS build I am using, as it only happens when the tablet is the group owner. When the phone is the group owner, the disconnection doesn't happen.
You should specify that you want to create the group to be persistent, so for example on Linux, you would do something like this:
sudo wpa_cli p2p_group_add persistent
using the android 4.4 BLE APIs on my Nexus7, i'm able to successfully interact with a peripheral BLE device -- connect, disconnect, read, write....
if however an active connection breaks for whatever reason (in this case, the peripheral is reset), i observe the following behavior....
my peripheral (by design) begins advertising after any active connection is terminated (for whatever reason); i can see this via my bluetooth packet sniffer....
i receive the onConnectionStateChanged callback as expected in my android app, at which point i invoke close() on my active BluetoothGatt instance; this is the same procedure i follow during a "normal" disconnect initiated from the client...
shortly after this, the android BLE stack tries to re-connect to the same peripheral; through the packet sniffer i can see the BLE connection request going out over the air...
my app, however, did not initiate this re-connection; indeed, i see no information from any bluetooth log suggesting this even happened!!!!
is there some "mode" in the BLE stack where it attempts to re-establish busted connections automatically???
thanks....
This happens on various Android phones whether the autoConnect flag is set to false or true.
Couldn't yet find a complete solution, it seems as the android BLE stack is spontaneously re-initiating the connection once it is getting the advertising signal again, just ignoring that it was the app that disconnected on purpose...
A partial solution may involve not using the BluetoothGatt.connect() method as explained here:
https://stackoverflow.com/a/23749770/4144487
So, a sample connect method can look like:
void connect(Context context) {
if (mGatt != null) {
mGatt.close();
}
mGatt = mDevice.connectGatt(context, false, callback);
}
To explain the importance of this issue, when it happens the peripheral thinks it is connected and my "real" app can't find it any more. At some phones like Galaxy S3 and Redmi note 3 I found that closing the bluetooth switch from the notification bar is "releasing" the peripheral and allowing me to discover the device. At others like Nexus 5x only a phone reboot will do the trick.
I've observed this happening if you use autoConnect=true when calling BluetoothGatt#connectGatt(). Generally I've found that it is best to use autoConnect=false, but with some devices you simply cannot connect unless you use true, so I usually do both. I try false first and if that fails then use true and then the behavior you're describing is something you simply have to work around.
I know there are a few threads on this topic but non of them seem to answer my question. I want to be able to detect when the device has no data connection. I have tried the NetworkInfo route checking if its null, isConnected(), isAvailable() etc. The problem im having is that these work fine (return false or null) when wifi or mobile network are disabled however when they are enabled but there is no signal they return true. Is there any way to detect no data connection due to no signal?
build reciver and catch broadcast
Intent action for network events in android sdk
You could try pinging google.com. If there's no response, you can be fairly sure that there's no connection (unless the user is in a country where it is blocked).
I use ConnectivityManager.getActiveNetworkInfo.isConnectedOrConnecting()
I just tested it 5 minutes ago to make sure, and if everything is working and I then walk away from my house until my router is no longer within range and the network strength indicator on the status bar shows no network, a call to isConnectedOrConnecting() from within an app returns false.
I take it that's not the behavior you are seeing?