Show alert message if the internet connection speed is slow in android - android

I have implemented a method to check for internet connection
public boolean isInternetWorking() {
boolean success = false;
try {
URL url = new URL("https://google.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(10000);
connection.connect();
success = connection.getResponseCode() == 200;
} catch (IOException e) {
e.printStackTrace();
}
return success;
}
The code works fine. However, I came across many cases where my app would not work properly due to slow internet connection.
Is there any way to show an alert message when the internet connection is slow and the data takes a long time to load?

Facebook has released a library for checking connection, Network Connection Class
Here the excerpt:
Network Connection Class is an Android library that allows you to figure out the quality of the current user's internet connection. The connection gets classified into several "Connection Classes" that make it easy to develop against. The library does this by listening to the existing internet traffic done by your app and notifying you when the user's connection quality changes. Developers can then use this Connection Class information and adjust the application's behaviour (request lower quality images or video, throttle type-ahead, etc).
Or maybe you can use Speed Test library
Read the near similar QA:
Best way to evaluate connection speed
Calculating Internet Speed in android
How to detect Internet connection speed with Java?

For WiFi link speed check WifiInfo.getLinkSpeed()
For Mobile Data Link you can only check
TelefonyManager.getNetworkType() to determine the current Mobile Data
Link type. You should then aproximate to actual speed by link type
(i.e. for GPRS up to 128 kbps, for EDGE up to 236.8 kpbs, for 3G up
to 2 Mbps, for HDSPA up to 7.2 Mbps). Take into consideration that
this is only an aproximation. Your could be conneting using HDSPA but
your carrier limiting the top speed to 2 Mbps.
Now , you have to get speed and put condition whether below 100kbps , "low internet connection"

Related

How can I clear the Bluetooth cache easily and regularly?

I am working on an application that makes multiple BLE connections in a minimum amount of time. I developed my application in Java Android. I set up a statistics-based system so that, among a group of phones, each phone makes connections on half the group and receives connections from the other half. This gives a pretty even distribution of BLE servers and clients. If a connection was made and failed or could not be launched, the other device that should have been a server will become a client and make the connection for the other in order to waste a minimum of time.
My problem arises when the number of devices present to make connections is greater than 5. When there are only two or three connections left to make, it takes a lot of tries to succeed. A lot of 133 errors or timeouts are thrown before getting a connection. The only time it is possible to speed up this is by clearing the Bluetooth cache. This is only possible by reflection and on the current connection. This operation doesn't work all the time and I'm trying to find out how to clear my own Bluetooth cache without it, faster and more reliably. Does anyone have any advice or idea to help me?
Here is the reflexive method we use to clear another's cache through a Gatt connection:
/**
* Method to refresh cache device
*/
private boolean refreshDeviceCache(BluetoothGatt gatt){
try {
Method localMethod = gatt.getClass().getMethod("refresh");
return (boolean) (Boolean) localMethod.invoke(gatt, new Object[0]);
}
catch (Exception localException) {
Log.e(TAG, "An exception occurred while refreshing device");
}
return false;
}
This method not being recommended, we had no choice since there is no other solution, and for the moment we haven't found one yet.

HttpURLConnection.connect() fails after network reconnection on Android 10

My app connects to an external device using it's WiFi (the device works as a server). With introduction of Android 10 I needed to implement separate WiFi connectivity flow for different plaftorms (WifiNetworkSpecifier for Android 10+ and wifiManager.enableNetwork for < Android 10). The connectivity flow itself works fine, but I have some problems with stream communication.
In the app I have the ability to upload files to that external device. To do that I need to use HttpURLConnection. So I run:
val url = URL(UPDATE_FIRMWARE_URL)
val connection = (url.openConnection() as HttpURLConnection)
with(connection) {
doInput = true
doOutput = true
useCaches = false
requestMethod = METHOD_POST
//setRequestProperty(HEADER_CONNECTION, "Keep-Alive")
setRequestProperty("Connection", "close")
connectTimeout = 6000
setRequestProperty(HEADER_USER_AGENT, "Android Multipart HTTP Client 1.0")
setRequestProperty(HEADER_CONTENT_TYPE, "multipart/form-data; boundary=$boundary")
}
connection.connect()
val outputStream = connection.outputStream
DataOutputStream(outputStream).use { outputStream ->
// actual file upload
}
Now, the actual update consists of two files, and after first upload the device restarts, and I need to reconnect to it's wifi and upload the second file.
On Android < 9 the entire upload flow (with two files) works fine but on Android 10, after I send the first file and reconnect to the device's WiFi, when I call connection.connect() I get ConnectExcpetion with internal cause connect failed: ENETUNREACH (Network is unreachable) (which really makes no sense, cause I'm connected to that network...)
java.net.ConnectException: Failed to connect to (...)
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:1409)
at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:1359)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:221)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:144)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:106)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:400)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:333)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:483)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:135)
Initially I had a problem also with connecting for the first time on Android 10, but I found this article, and adding the connectTimeout helped, but now the connection still fails when I try to connect for the second (and every next) time. The only thing that helps is restaring the entire app (which is no real solution).
What may be the problem, that the next connections fail despite I always execute the same code?
After a few days I finally found an answer to my question. It turns out that on Android 10 when you connect to the Access Point that does not offer the internet (eg. my external device) the standard API calls (using Retrofit) works fine, but when trying to use HttpURLConnection the system tries to use some network with internet connection, and as there is none, the connection fails.
The only way for the connection to work is to force the system to use our network by using ConnectivityManager.bindProcessToNetwork(network). This solution was proposed here and I've got no idea why someone downvoted that answer. It's correct.
What's interesting is that if we connect to the no-internet network via device settings, the connection works just fine even without binding.

How test if an open connection is working?

We are developing some internal apps for mobile devices that are connected to internal wifis. We have some problems because we are only checking if the devices are connected using ConnectivityManager. But we need to check not only if there is connection, we need to check that the connection between the device and the server is working.
The problem is that ConnectivityManager tell us that the wifi is connected. But if the device is in an area with little coverage the app have errors trying to connect.
How can we easily check that the connection we have open against the server is still responding correctly? For example, one of the applications the connection is open against a SQL Server. Is there any way to check that we get to the server and it gives us an ok, and that we are not losing the connection and the packages because of the low coverage?
Thanks!!
You can try pinging the server if you receive a NullPointerException or IOException most likely there is no connection or connection timed out.
you can read more here an answer to similar question by syb0rg. Also remember to wrap this piece of code in an AsyncTask or a Thread to prevent your app from crashing.
try {
//replace URL with your domain
URL url = new URL("http://www.google.com");
HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
urlConnect.setConnectTimeout(1000);
urlConnect.getContent();
System.out.println("Connection established.");
} catch (NullPointerException np) {
np.printStackTrace();
} catch (IOException io) {
io.printStackTrace();
}

How to detect if system is connected to ad hoc or infrastructure wifi?

I am working on an application that checks, before enabling a download, that the connection is reliable (basically the connection should be an infrastructure wifi and not data pack) But in case the user is either
using an ad hoc network, or
mobile device's internet connection as WAP
and then connecting and starting the download on desktop, it is still undesired. Is there a way to detect if some wifi connection is actually not from ad hoc or using phone's WAP?
You can detect...
...the Ad-Hoc Network by checking if you actually can access a server on the internet - usually, Ad-Hoc does not include fully connectivity so if you have network but no internet access, a download won't work
...the usage of a phone access point by measuring the round-trip time of a request - they are usually quite high on mobile broadband.
long start = System.nanoTime();
HttpGet requestForTest = new HttpGet("http://m.google.com");
try {
new DefaultHttpClient().execute(requestForTest); // can last...
}
catch (Exception e) {
}
long rtt = System.nanoTime() - start;
// ... evaluate the rtt
This table may be relevant for the evaluation (source)
Generation | Data rate | Latency
2G | 100–400 Kbit/s | 300–1000 ms
3G | 0.5–5 Mbit/s | 100–500 ms
4G | 1–50 Mbit/s | < 100 ms
Apart from those two options: why do you specifically ban Ad-Hoc or mobile broadband? Shouldn't you either
ban nothing and let the user decide if they want to wait for ages
or
ban ALL slow connections, i.e. monitoring the transfer rate for a couple of seconds and cancel the download automatically if it is too small
Essentially, you're writing an Application on layer 7 of the ISO/OSI model and you want to know contents of layer 2. That is explicitly not how it should work.
If your download is big, you should protect the user from burning up their mobile contract's data volume and notify the user before executing the download.
That is also how the Google Play store handles downloads bigger than a few MBytes.
you could have an option in the preferences of your app to only allow downloads when on Wi-Fi so users can be sure to save their data plan.
If you absolutely don't want a user to download your files over mobile network, only allow Wi-Fi and then do a pind and a download of a 1MB file to measure the bandwidth before deciding if the actual download will take forever or not.
All the rest should be handled by the system and doesn't need to concern you.
to check if its connected to wifi:
ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (wifi.isConnected()) {
// is connected to wifi
}
don't forget to add permission to Manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>

Force HttpURLConnection to use mobile network and fallback to WiFi

My application uses HttpURLConnection to connect to my REST services. I log errors and noticed that what happens occasionally is that user get's WiFi connection but it has proxy.
For example, those airport wifi's that redirect you to pay pages and then let you use internet. My code does not follow redirects.
What I really want is to ignore presence of WiFi and force communication over 3G/4G/E whatever. How can I do that on Android?
Switch to mobile network:
As soon as you detect a proxy, pop up a dialog telling the user that your app cannot use that network and hence you are switching to the mobile network. You can switch to a mobile network using ConnectivityManagerclass.
ConnectivityManager cm;
cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
cm.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
and switch back to the default when you are done:
cm.setNetworkPreference(ConnectivityManager.DEFAULT_NETWORK_PREFERENCE);
Detect a proxy:
Detect proxy using the following snippet
HttpURLConnection conn;
...
if (conn.getResponseCode() == HTTP_PROXY_AUTH){
// You got a '407: Proxy authentication required' response.
// Set the networkPreference() here and retry when
// network connection changes to TYPE_MOBILE.
}
You can check this post to know how to use a HttpURLConnection through a proxy : How do I make HttpURLConnection use a proxy?
Detect a 'network change':
To know how to detect 'network change' see this post :
Android, How to handle change in network (from GPRS to Wi-fi and vice-versa) while polling for data
Update:
If you cannot show a dialog, at least send a status bar Notification so that user knows about the network switch sometime later.
In your activities, Whenever you try to make call to your Web Services
Just Disable the WIFI if it's enabled. There will be many code snippets available on Internet for that like this
Now also Check that if Mobile data network is available or not, and If available make your call, otherwise show user a dialog that this app will require mobile data networks to do the tasks.
and as soon as you complete your HTTP Calls turn the WIFI ON again.

Categories

Resources