Im am working on a App that has to work in the Background, and it has to send Geolocation. It is allready in production and we sometimes have the problem that an App just stoppes sending information.
It seems that only a restart of the Phone helps.
Now I have to fix this somehow, it seems to me that resetting the Networkstack would solve the problem. My question is this, how can I programticlly reset the network connection? Or does anybody have any other suggestions for this problem.
how can I programticlly reset the network connection? Or does anybody
have any other suggestions for this problem.
You should not go for start a network connection programatically. I would suggest you to check for network connection before posting the location to server, and if device is disconnected show the notification to user to enable network connection.
Why I am not in favor of set network connection by code
This functionality can cost the user. So raise a notification and let the user to start network connection.
And yes if user dosn't start the network connection your application will not post location any more.
Update for Listen device network state
Register a Receiver to listen for CONNECTIVITY_ACTION
For example:
BroadcastReceiver sampleNetworkStateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.w("sampleNetworkStateReceiver", "Network State has Changed");
//For a disconnect event, the boolean extra EXTRA_NO_CONNECTIVITY is set to true if there are no connected networks at all.
// So you need to get EXTRA_NO_CONNECTIVITY extra from intent.
// that will tell you if device has loses the conectivity.
boolean noConnectivity =
intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (noConnectivity) {
//TODO: Task for Device has no connection
} else {
//TODO: Task for Device has connection
}
}
};
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(sampleNetworkStateReceiver, filter);
Ref : NetworkConnectivityListener and Determining and Monitoring the Connectivity Status
Related
I'm trying to connect to a specific wifi network in android 10. I already have the credentials available to me, and i'm adding the network suggestion:
val suggestion = WifiNetworkSuggestion.Builder()
.setSsid("ssid")
.setWpa2Passphrase("password")
.build()
wifiManager.removeNetworkSuggestions(mutableListOf(suggestion))
when (wifiManager.addNetworkSuggestions(mutableListOf(suggestion))) {
WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS -> {
networkAdded()
}
WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE -> {
networkDuplicate()
}
else -> {
networkAddFailed()
}
}
I'm able to see the notification (though only the first time the app requests this, which makes sense for the most part, since it's asking for permission really to be able to suggest networks). However, after I allow it, i can't seem to get connected to that network. In particular if i already have a wifi connection to some other network.
The new network does not appear in my list of saved networks, and if i find it in the wifi scan list, and click on it, it treats it like a new network.
I don't expect the app to be able to force the system to connect, but i would expect the user to be able to do it on their own via the wifi settings without having to configure it from scratch.
I've also tried using ConnectivityManager to forcibly connect, but that does not add an actual persistent wifi connection. It's only meant to force connection for a specific app while the app is in memory (at least that's my understanding of it).
I had the same issue but after I added this piece of code the device was connected to the network:
final IntentFilter intentFilter = new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (!intent.getAction().equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
return;
} else {
// Do something with success
}
}
};
context.registerReceiver(broadcastReceiver, intentFilter);
Hope that it helps. You can find the complete code example in: Wi-Fi suggestion API
I was looking for a way to react a case when:
I am connected to WiFi
the access point has just lost internet connection (e.g the cable from router has been removed)
In such cases, Android phones or notebooks are notified about that state and showing exclamation mark next to the WiFi icon.
Is it possible to be notified about that state in Android API? I was looking in the documentation but not found any.
IMPORTANT NOTE:
I am not looking for just checking internet connection manually or just listen for changing network connection status as I will not be notified when the WiFi access point that I am connected to has lost the connection.
So regarding above I was trying to just check the changes of the network connection, but as i explained it is not enough for my case:
override fun onReceive(context: Context, intent: Intent) {
val wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
DEFAULT_WIFI_STATE_VALUE)
wifiStateSubject.onNext(wifiState)
Timber.d("Current wifi state: $wifiState")
}
You can periodically try to access some resource with low ping and low timeout rate and if it throws some kind of NetworkException you can suppose that connection not available.
UPD:
You can use or inspect this library https://github.com/pwittchen/NetworkEvents
I want to establish a WiFi-Direct Connection with another device peered through NFC. My steps are as follows:
First, Device A gets its own WiFiP2P address and transmits it to Device B via NFC.
Then, Device B tries to establish a connection with Device A using the provided address.
As you can see I didn't involve discovering peers in the process. But when Device B is trying to connect, the result is always failed (reason 0, this should be ERROR).
I think this might be related to device visibility, but I don't know and can't find any code to make a device visible.
Here's my code:
//NOTE: These code should be executed on Device B
//Starting WiFi Direct Transmission
//First we should establish a connection
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = remoteWifiP2pDevice;
//remoteWifiP2pDevice is the address of device A obtained from NFC
config.wps.setup = WpsInfo.PBC;
mManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
//success logic
Toast.makeText(MainActivity.this, "success", Toast.LENGTH_SHORT).show();
if (!FILE_RECV)
{
new SendFilesTask().execute("");
}
}
#Override
public void onFailure(int reason) {
//failure logic
Toast.makeText(MainActivity.this, "failed" + reason, Toast.LENGTH_SHORT).show();
}
});
In OnCreate() I have
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
The WifiDirectBroadcastReceiver has code only related to getting Device A's address and can be considered empty.
So what's wrong with these and how can I fix it?
Thanks in advance.
P.S. If I connect Device A and B manually, and run my code again, it returns success.
WIfi Direct assumptions:
All the devices should be in discoverable (scanning mode)
simultaneously.
Devices scan for a 30 sec and after that
it stops by default.So we need to initiate scan programatically
using discoverpeers method.
Most important is displaying
nearby devices is device specific.ie sometimes devices wont show
nearby ones eventhough they are available.Thats why wifi direct
is not reliable and because of these, there wont be much wifi
direct apps in play store.
I have discovered that delaying several seconds will make the connection succeed. I don't know the reason, but this can be used as a workaround.
So after all is there a better solution to this? And why does the delay work?
I want my app to "do something" when a wifi is nearby. But the phone doesn't connect to it. I don't have the password. For example, if the wifi University0001 is reachable I would like to silent my phone but I don't have the password to University0001.
Is there a way to have a broadcast receiver that triggers when new (not connected) ssid are around?
I would not like to have a "timer" to periodically check new SSIDs. I am asking for a receiver to trigger when new networks are around and maybe then check for the one I want.
I hope to be clear.
Thanks
Is there a way to have a broadcast receiver that triggers when new (not connected) ssid are around?
yes there is.
if your WIFI is on, and you are not currently connected to a WIFI network - the system periodically scan for available access points. when it will detect new visible access point it will send the SCAN_RESULTS_AVAILABLE_ACTION broadcast.
you can register to that broadcast, and when it receives - get from WifiManager the scan results:
#Override
public void onReceive(Context context, Intent intent) {
WifiManager wifiManager (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
List<ScanResult> scanResults = wifiManager.getScanResults();
}
if you are already connected to a WIFI network - then you won't have any choice but to trigger the scan yourself periodically...
be careful:
performing from this receiver long operations (such network requests..) any time it receives is a bad approach - you'll drain the users battery very fast.
My app is running in the background (as a Service) and needs to be connected to a remote server all the time to receive and send messages.
This Service runs a Thread which manage the connection to the server (with Socket)
i'm trying to write an internet connection Broadcast Receiver which will run every time the internet state is changed and check if the state is connected of disconnected.
my problem is as follow: when i'm connected to Wi-Fi network the Broadcast Receiver Intent is fired few times which in all of them the state of the internet connection is true (with no disconnection between every fire, which means i have few new Threads using the Socket to connect the server.
How can i make sure i'm getting the state of the internet right, and by right i mean that the .isConnected() method will return if and only if the connection is connected ?
this is my code:
public void onReceive(Context context, Intent intent)
{
action = intent.getAction();
app = (AppVariables) context.getApplicationContext();
if (app.isApplicationInitilized())
{
if (action.equals(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)))
{
networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (networkInfo.isConnected())
app.getServerConnectionManager().startServer();
}
else if(action.equals(ConnectivityManager.CONNECTIVITY_ACTION))
{
networkInfo = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if(networkInfo.getType() == ConnectivityManager.TYPE_WIFI && !networkInfo.isConnected())
app.getServerConnectionManager().stopServer(false);
else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE && !networkInfo.isConnected())
app.getServerConnectionManager().stopServer(false);
else
app.getServerConnectionManager().startServer();
}
}
}
I've had the same issue for one of my apps, and the pattern we deployed (successfully) is as follows:
onReceive():
if( networkInfo.isConnected() )
fireTimerForSecondaryCheck();
else
not connected;
SecondaryCheck:
if( loadKnownUrl() )
is connected.
fire long timer for secondary check
else
fire short timer for secondary check
Basically what this does is attempt to access the internet once the network manager reports that wifi is up. If it receives the expected content, then the network connection is up and working, and I'll check again in two minutes. If I don't receive the expected content, it means either the network connection is not fully up, can't connect to the internet, or the wifi might have a landing page for TOS or similar. In that case, I check again in 10 seconds.
FWIW, my NetworkMonitorService broadcasts connectivity to my app, which registers for it, and updates the UI as necessary.
This was developed in 2.3.3, and I believe the newer Android versions (4+) have finer granularity in the network state, but I haven't seen the need to adjust this code yet in production. It works well from 2.2 devices all the way to 4.2.
If I understand correctly you need to know the state of connection.
You can obtain that by using networkInfo state:
State state = networkInfo.getState();
if (state == State.CONNECTED) do_something