CN1 Connectivity - Concerns when internet is unstable in Public places - android

I'm using Connectivity library to see the internet(Wifi or network data) is active and saving the data in Storage if there is no connectivity(Offline) and synchronize with server when connected to internet. I'm having issues in public places where the internet is consistently unstable(esp. in basements, offices, stores, Coffee shops etc., where there is internet connects in and out). When I check the Connectivity is active but by the time I started synchronizing internet goes offline (Something like this). this leads inconsistent /partial updates to the server. Also, in coffee shops and Airports where wifi gets connected but there will be "Agree Terms and Conditions" page to connect. Not all the browsers will take you to that page directly after joining the Wifi. In that case I see the wifi is active in Mobile but actually it is not activated until I accept the terms and Conditions in IE or some specific browser. Any one else having difficulty in handling these kind of issue from Mobile App?
My App - Hangs on Login screen if I'm trying to login when there is in-stable/in consistent internet.It thinks wifi is there but not.
IF I'm on a screen where I will display list, screen will show blank for infinite time. Adding timeout for server request/response or something will help such scenario.
I know I'm not handling this case in code to show some kind of error message but I need some guidance to detect these conditions suing CN1 API to handle through my app.Please advise.
Code:
public boolean isOffline() {
if (Connectivity.isConnected() && forceOffline) {
relogin();
}
return forceOffline || !Connectivity.isConnected();
}

The problem is that it's impossible to detect online/offline properly as you might be connected to a local wifi/network but it might be a bad connection that won't let you reach the server. As far as the library is concerned you are connected... But in reality you don't have a connection.
First set the timeout values in NetworkManager to lower values to improve the experience although this won't solve a situation where data starts downloading and stops in the middle.
Next you need to handle these cases one by one and provide the user with a way to toggle the offline mode. Unfortunately there is no silver bullet for network reliability. You just need to go through every path and try to detect these things.

Related

Ping 8.8.8.8 every 1 minute, after some pings the ping times out

I am having an Android app which needs continuous network monitoring and I require to be notified when I have internet and when not. I have tried Android connectivity manager, which only tells if the internet wifi is connected or not, but doesn't tell if there is reachability. So I used the following ping method to check the reachability.
private fun isOnline(): Boolean {
return try {
val timeoutMs = 1500
val sock = Socket()
val socketAddress = InetSocketAddress("8.8.8.8", 53)
sock.connect(socketAddress, timeoutMs)
sock.close()
true
} catch (e: IOException) {
Logger.e(TAG, e.toString())
false
}
}
Now to keep checking this every 1 minute I am using a fixedRateTimer which will call this method every 1 minute and notify accordingly.
Now the problem I am facing is, this works fine for few hours and I get proper connection status. But after few hours the ping starts timing out. I get a timeout exception every alternate ping.
I want to understand few things,
First thing, is it okay to ping for every 1 minute to check the network?
Can the client be blocked by Google for frequent pings?
Or is it anything related to the ISP?
Is there a better approach in android to achieve what I want?
Any advice would be appreciated. Thanks in advance!
PS : I have also tried onCapabilitiesChanged and the callbacks are not immediate for every connection and disconnection, though the google documentation says callbacks will be immediate.
but doesn't tell if there is reachability. So I used the following ping method to check the reachability
First, that is not a ping. That is opening and closing a socket.
Second, it can only tell you if you can open a socket connection to that IP address. It does not tell you if you can access anything else. So, this is subject to false positives (you can reach 8.8.8.8 but not your real server) and false negatives (8.8.8.8 is blocked by network management, but your real server is not).
Now to keep checking this every 1 minute I am using a fixedRateTimer which will call this method every 1 minute and notify accordingly.
That will only work so long as your process is running, and only until you lose Internet access due to Doze mode/app standby/manufacturer-specific power management solutions.
First thing, is it okay to ping for every 1 minute to check the network?
It has flaws. "Okay" is a subjective measure; only you can decide whether it is "okay" for you.
Can the client be blocked by Google for frequent pings?
This is not a ping. It is certainly within Google's power to take action for buggy clients like this.
Or is it anything related to the ISP?
There are lots of pieces involved in an Android device reaching 8.8.8.8:
The network management for whatever WiFi network the phone is using for connectivity (where relevant)
The mobile carrier or ISP
The various other ISPs between you and Google
Google's own network management
Any of them could take steps, if they so chose.
Is there a better approach in android to achieve what I want?
I would aim to eliminate the "need" entirely, as Android and device manufacturers will be fighting you every step of the way.
At minimum:
Do a valid expected operation, such as an actual ping; and
Do it against a relevant server
IIRC, 8.8.8.8 is a DNS server. If your app is a DNS client, you are welcome perform a valid, useful DNS operation against 8.8.8.8. If your app is not a DNS client, quit messing with somebody else's server. Run your own server and test reaching it. For example, you could run a Web server and test whether you can retrieve your robots.txt file.
Most of the question has been answered, but I want to pick up on the most important one.
First thing, is it okay to ping for every 1 minute to check the network?
No. It is not OK.
It is wasteful
You are consuming Google's resources. Resources that you are not paying for. If everyone did what you are doing it would cost Google a lot of money ... to run a much larger fleet of DNS servers, etc to cope with bazillions of vacuous connections.
You are also consuming resources in the along the route from the user's app to Google with the (unnecessary) network traffic.
This would also apply if you were doing real (ICMP) pings, though not to the same extent.
And bear in mind, this is also consuming electricity. And that means more fossil fuel is burned.
It may be incurring costs for the user
Depending on the what their mobile phone plan is, this may be costing the user of your app network charges. Each of those connections your App is making probably being metered. If they are not aware of this ... or they can't turn this (mis-)feature off, they could get rather annoyed about this. (I would be!)
It doesn't actually work
What you are doing doesn't actually test if the internet is available. What you are actually doing is seeing if your App can connect to the Google DNS services. But the fact that the DNS server is accepting connections doesn't mean that the real services that the user wants to use will be accessible and working. (And vice versa!)
As you noted, connections will occasionally fail for reasons that are probably due to transient problems that resolve themselves. There is nothing you can do about that. That could be a false negative for the internet being "up".
Even if there was a reliable way to find out if the internet is "working", your "pinging" is only giving you a single sample. The internet could go "down" (or come back "up") any time in the up to 60 seconds between your pings. More false negatives and positives.
And as noted, Google DNS is not the same as "the internet", and "the internet" is not the same as the service that the user of you App is really interested in.
Your app doesn't REALLY need this information
The user does not need to know minute by minute that the internet is available.
Most of the time a typical user is doing something else.
They only actually need to know if they are actively using some service. And even then, knowing that the internet was up 60 seconds ago is probably no help to them.
Unfortunately, the only way that the user can tell if the service they are talking to is available right now ... is to actually try to use it.
So what is the real solution?
IMO, there are two approaches:
Forget it. In most cases, the user really doesn't need to know. It is not actually going to materially effect the user if your App does not distinguish "service down" from "internet down".
If you can't forget it.
Implement an end-point on your service that you can ping ... and pay the bills!
If you are trying to implement this in an App where you are talking to someone else's services, stop free-loading on Google. If you want an "internet is up/down" feature in your App, implement your own service for doing this ... and pay the bills.
Note that you will still have false positives and false negatives to deal with. There is no solution to that. It is a fundamental property of the internet.

How to prevent users from turning off GPS, Wifi and Bluetooth?

I'm developing a tracking application and I need to prevent users from turning off the basic sensors used to determine the location. I can not modify the devices ROM or have root access (or at least it would be very desirable to had not), but I thought of using the Device Administration API to perform these functions through the Profile Owner or Device Owner modes. I'm basically looking for a method to block these functions in Android settings.
I'm unsure about whether this is possible and how to do it, I have not found examples in GitHub for applications that have implemented this. Could anyone give me a light, some example or specific documentation?
I tried to follow these three documentations, without success in finding a solution to this specific feature:
https://source.android.com/devices/tech/admin
https://developer.android.com/guide/topics/admin/device-admin
https://developers.google.com/android/management/introduction
This is an excerpt from what I've been trying:
setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true);
setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, active);
setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, active);
private void setUserRestriction(String restriction, boolean disallow){
if (disallow) {
mDevicePolicyManager.addUserRestriction(mAdminComponentName, restriction);
} else {
mDevicePolicyManager.clearUserRestriction(mAdminComponentName,
restriction);
}
}
DISALLOW_CONFIG_BLUETOOTH
Added in API level 18
public static final String DISALLOW_CONFIG_BLUETOOTH
Specifies if a user is disallowed from configuring bluetooth. This does not restrict the user from turning bluetooth on or off. The default value is false.
This restriction doesn't prevent the user from using bluetooth. For disallowing usage of bluetooth completely on the device, use DISALLOW_BLUETOOTH.
This restriction has no effect in a managed profile.
Key for user restrictions.
Type: Boolean
You cannot prevent them from turning GPS, WIFI and Bluetooth off. What you can do is have an implementation as below or use this library.
https://github.com/KI-labs/gps-permission-checks-livedata
You can't, obviously for security reasons. If you want to achive something like that you'll probably need to modify the devices ROM. You should create a BroadcastReceiver and keep tracking Internet and Bluetooth connection changes, than you can properly handle it when user disconnect them pausing the service, showing a dialog, finishing the application or whatever you need to do.
It would be pretty weird if an app could have some control of user settings, imagine if you install an app, then suddently you can't disable wi-fi anymore until you unistall it. You can't do that for a good reason
Preventing bluetooth/wifi disconnection will also prevent usage of aircraft mode, that is a security issue bounded in the ROM and not overridable.
As suggested above your option is to monitor for wifi/bluetooth/gps deactivations and prompt the user with an alert.
By the way, GPS is not affected by aircraft mode, as it's a pure receiver and doesn't make active transmissions. In that case GPS will be always active and collecting informations (if active and the phone is not in power save mode, aka relying on wifi location). I suggest you to check if the user activated aircraft mode, in order to be less annoying with your alerts (air mode is mandatory in same situations, and should be considered "legal" by your application, and maybe less critical than an user voluntary disconnection
In simple words, You cannot, but you can listen to when wifi is enabled/connected, and you can prompt a dialog stating the reason.
This way it gives the user a more concise grip on what needs to be done.
Just a suggestion

How to calculate when the network card opens a connection on Android

I am trying to figure out if there is a way to know when an app opens an internet connection and thus wakes up the network card.
So for example, I have the phone off and I decide to search http://www.cnn.com
In this case, lets imagine that no background data is going on from any app, so the connection is IDLE at the time I call the website. I want to know when the network card opened the connection to load the page.
I have found no APIs for this. Originally I was looking at the TelephonyManager which has different states of the network card (DORMANT, INOUT, NONE, etc), but I found my phone never goes to dormant, I believe this is due to fast dormancy. I have also been looking at linux filesystem files that might contain this information from the driver, but I have found none.
I read this nice article from ATT which explains about mobile networks
http://www.research.att.com/articles/featured_stories/2011_03/201102_Energy_efficient?fbid=xEv4RTIfUL9
Thanks.
Ok so the answer is to use the SignalStrength class and the PhoneStateListener's onSignalStrengthsChanged in order to measure the radio signal. This helps detect when a connecdtion is made. Referenced from ATT's ARO app:
https://developer.att.com/application-resource-optimizer
http://developer.android.com/reference/android/telephony/SignalStrength.html
http://developer.android.com/reference/android/telephony/PhoneStateListener.html#onSignalStrengthsChanged(android.telephony.SignalStrength)

Detect bad network connectivity on android

I am building an android app that exchanges data with our server through http api calls. In many cases users are complaining that the app is slow or doesn't work at all.
The most common cause of that is bad network connectivity (low 3g/wifi signal or congested public wifi).
What is the best way to detect bad connections? Once i can detect bad connectivity an icon or toast message can be used to inform the user about the situation.
I am using HttpUrlConnection for the api calls.
I think you can make use of ConnectivityManager. Call getActiveNetworkInfo() and then call getDetailedState() on the NetworkInfo object received. You can check the state of the connection and whether it is VERIFYING_POOR_LINK, though I don't know in which conditions this state is active.
Also you might want to listen to network changes as described in Detect Connection Changes.
I'd probably use latency. Save the time when you get the request, and when the request finishes. If you're seeing numbers that are too high, pop up the warning. If you're downloading large files, you may wish to switch to throughput (how many kbps you're transfering).
as far as i remember http is "connectionless"..
you should try concentrating on minimizing the size of your traffic.. (compress, divide.. etc)
if you really want to test connectivity i guess you should do pings.. every x seconds.. then if the ping is bad you could warn the user..

Android detect no data connection

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?

Categories

Resources