Check For Internet Connectivity Causes Android Not Responding Error - android

This is my first app, so I'm still learning. I created a class (Check Network) that I call on to check for internet connectivity before I display an ad. The method in the class returns a boolean, here is the first method - a test connection to Google:
public boolean isConnectedToGoogle() {
Runtime runtime = Runtime.getRuntime();
boolean reachGoogle = false;
try {
Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
int exitValue = ipProcess.waitFor();
if(exitValue == 0) {
reachGoogle = true;
} else {
reachGoogle = false;
}
} catch (IOException e) {
//e.printStackTrace();
reachGoogle = false;
} catch (InterruptedException e) {
//e.printStackTrace();
reachGoogle = false;
}
return reachGoogle;
}
Next, I use the above method in the method below to test the network, and return true or false:
public boolean isNetworkNull(Context context) {
boolean isNetWorkNull;
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if(activeNetwork != null) {
if(isConnectedToGoogle()) {
isNetWorkNull = false;
} else {
isNetWorkNull = true;
}
} else {
isNetWorkNull = true;
}
return isNetWorkNull;
}
So, throughout my app I use the code to test the connection:
boolean isNetworkNull = checkNetwork.isNetworkNull(getApplicationContext());
if(isNetworkNull) {
// do this
} else {
// do that
}
In my Google Play Console I've discovered numerous "Android Not Responding" events due to the isConnectedToGoogle() method. The console states:
nameOfApp.CheckNetwork.isConnectedToGoogle
input dispatching time out
The best I can understand is the call to Google is taking too long (maybe the phone has a weak internet connection) and thus it times out and the app records an android not responding error.
If this is accurate, is there a way to say "listen" and if no response received from Google after time X have the isConnectedToGoogle skip the check and just return a true or false? Or is there a better approach to this? Any assistance would be greatly appreciated.

I think I found the answer after doing a bit more research. I changed the code as such for the isConnectedToGoogle() Method:
Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
// int exitValue = ipProcess.waitFor(); // original
boolean wasGoogleReached = ipProcess.waitFor(1000, TimeUnit.MILLISECONDS);
if(wasGoogleReached) {
reachGoogle = true;
} else {
reachGoogle = false;
}
I believe this should handle the time out. This link also helped.

Related

Android Internet connectivity check better method

According to the Android developer site, Determining and Monitoring the Connectivity Status, we can check there is an active Internet connection. But this is not working if even only Wi-Fi is connected and not Internet available (it notifies there is an Internet connection).
Now I ping a website and check whether Internet connections are available or not. And this method needs some more processing time. Is there a better method for checking Internet connectivity than this to avoid the time delay in ping the address?
Try this:
It's really simple and fast:
public boolean isInternetAvailable(String address, int port, int timeoutMs) {
try {
Socket sock = new Socket();
SocketAddress sockaddr = new InetSocketAddress(address, port);
sock.connect(sockaddr, timeoutMs); // This will block no more than timeoutMs
sock.close();
return true;
} catch (IOException e) { return false; }
}
Then wherever you want to check just use this:
if (isInternetAvailable("8.8.8.8", 53, 1000)) {
// Internet available, do something
} else {
// Internet not available
}
The first problem you should make it clear is what do you mean by whether internet is available?
Not connected to wifi or cellular network;
Connected to a limited wifi: e.g. In a school network, if you connect to school wifi, you can access intranet directly. But you have to log in with school account to access extranet. In this case, if you ping extranet website, you may receive response because some intranet made auto redirect to login page;
Connected to unlimited wifi: you are free to access most websites;
The second problem is what do you want to achieve?
As far as I understand your description, you seems want to test the connection of network and remind user if it fails. So I recommend you just ping your server, which is always fine if you want to exchange data with it.
You wonder whether there is a better way to test connectivity, and the answer is no.
The current TCP/IP network is virtual circuit, packet-switched network, which means there is no a fixed 'path' for the data to run, i.e. not like a telephone, we have a real connection between two users, we can know the connection is lost immediately after circuit is broken. We have to send a packet to the destination, and find no response, then we know, we lose the connection (which is what ping -- ICMP protocol -- does).
In conclusion, we have no better way to test the connectivity to a host other than ping it, that is why heartbeat is used in service management.
Try the following:
public boolean checkOnlineState() {
ConnectivityManager CManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo NInfo = CManager.getActiveNetworkInfo();
if (NInfo != null && NInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
Don't forget the access:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Else:
if (InetAddress.getByName("www.google.com").isReachable(timeout))
{ }
else
{ }
On checking this issue it found that We cannot determine whether an active internet connection is there, by using the method specified in the developer site:
https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html
This will only check whther ther active connection of wifi.
So I found 2 methods which will check whether there is an active internet connection
1.Ping a website using below method
URL url = new URL(myUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
// 30 second time out.
httpURLConnection.setConnectTimeout(30000);
httpURLConnection.connect();
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
isAvailable = true;
}
2.Check the availability of Google DNS using socket
try {
Socket sock = new Socket();
SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);
sock.connect(sockaddr, 1000); // this will block no more than timeoutMs
sock.close();
return true;
}
The second method is little faster than 2nd method (Which suits for my requirement)
Thanks all for the answers and support.
I wanted to comment, but not enough reputation :/
Anyways, an issue with the accepted answer is it doesn't catch a SocketTimeoutException, which I've seen in the wild (Android) that causes crashes.
public boolean isInternetAvailable(String address, int port, int timeoutMs) {
try {
Socket sock = new Socket();
SocketAddress sockaddr = new InetSocketAddress(address, port);
sock.connect(sockaddr, timeoutMs); // This will block no more than timeoutMs
sock.close();
return true;
} catch (IOException e) {
return false;
} catch (SocketTimeoutException e) {
return false;
}
}
//***To verify internet access
public static Boolean isOnline(){
boolean isAvailable = false;
try {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
URL url = new URL("https://stackoverflow.com/");
HttpURLConnection httpURLConnection = null;
httpURLConnection = (HttpURLConnection) url.openConnection();
// 2 second time out.
httpURLConnection.setConnectTimeout(2000);
httpURLConnection.connect();
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
isAvailable = true;
} else {
isAvailable = false;
}
} catch (IOException e) {
e.printStackTrace();
isAvailable = false;
}
if (isAvailable){
return true;
}else {
return false;
}
}
ConnectivityManager will not be able to tell you if you have active connection on WIFI.
The only option to check if we have active Internet connection is to ping the URL. But you don't need to do that with every HTTP request you made from your App.
What you can do:
Use below code to check connectivity
private boolean checkInternetConnection()
{
ConnectivityManager cm = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// test for connection
if (cm.getActiveNetworkInfo() != null
&& cm.getActiveNetworkInfo().isAvailable()
&& cm.getActiveNetworkInfo().isConnected())
{
return true;
}
else
{
return false;
}
}
And while making rest call using HTTP client set timeout like 10 seconds. If you don't get response in 10 seconds means you donot have active internet connection and exception will be thrown (Mostly you get response within 10 seconds). No need to check active connection by pinging everytime (if you are not making Chat or VOIP app)
Maybe this can help you:
private boolean checkInternetConnection() {
ConnectivityManager cm = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// Test for connection
if (cm.getActiveNetworkInfo() != null
&& cm.getActiveNetworkInfo().isAvailable()
&& cm.getActiveNetworkInfo().isConnected()) {
return true;
}
else {
return false;
}
}
Try this method, this will help you:
public static boolean isNetworkConnected(Context context)
{
ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null)
{
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected())
{
return true;
}
}
return false;
}
You can try this for check Internet connectivity:
/**
* Check Connectivity of network.
*/
public static boolean isOnline(Context context) {
try {
if (context == null)
return false;
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm != null) {
if (cm.getActiveNetworkInfo() != null) {
return cm.getActiveNetworkInfo().isConnected();
} else {
return false;
}
} else {
return false;
}
}
catch (Exception e) {
Log.error("Exception", e);
return false;
}
}
In your activity you call this function like this.
if(YourClass.isOnline(context))
{
// Do your stuff here.
}
else
{
// Show alert, no Internet connection.
}
Don't forget to add ACCESS_NETWORK_STATE PERMISSION:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Try this if you want to just ping the URL:
public static boolean isPingAvailable(String myUrl) {
boolean isAvailable = false;
try {
URL url = new URL(myUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
// 30 second time out.
httpURLConnection.setConnectTimeout(30000);
httpURLConnection.connect();
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
isAvailable = true;
}
} catch (Exception e) {
isAvailable = false;
e.printStackTrace();
}
return isAvailable;
}

Unable to get data roaming status on Moto Devices Android?

I need to get access to the Data Roaming Status on Moto Device(5.0.1)
if (Settings.Secure.getInt(context.getContentResolver(),Settings.Secure.DATA_ROAMING) == 1) {
//Data Roaming Enabled
flag = true;
} else {
// Data Roaming Disabled
flag = false;
}
I found problem with this when using a Motorola device. Secure Settings in this device are found in android.provider.MotorolaSettings.Secure where as in other devices it's android.provider.Settings.Secure.
Is there a way to resolve this or any other way to get roaming status?
One solution here, use reflection to check if Motorola classes are availables.
If they're not here, you need to use the default api, then call getInt on the available system.
Not able to test it on a Motorola device.
public static boolean isEnabled(Context context){
Class<?> baseSettingsClass = null;
// Retrieve the 'default' settings api
try {
if (android.os.Build.VERSION.SDK_INT >= 17){
baseSettingsClass = Class.forName( "android.provider.Settings$Global");
}
else{
baseSettingsClass = Class.forName( "android.provider.Settings$Secure" );
}
}catch(Exception e){}
Class<?> secureClass = null;
// Try retrieve the motorola class
try{
secureClass = Class.forName("com.motorola.android.provider.MotorolaSettings$Secure" );
}catch(Exception e){}
// If it failed, use the 'default' api class
if (secureClass == null){
if (baseSettingsClass != null){
secureClass = baseSettingsClass;
}
else{
return false;
}
}
try {
// Retrieve the getInt method
Method getIntMethod = secureClass.getDeclaredMethod("getInt", ContentResolver.class, String.class);
// Execute getInt(context.getContentResolver(), Settings.Secure.DATA_ROAMING)
int result = (Integer) (getIntMethod.invoke(null, context.getContentResolver(), (String)baseSettingsClass.getField("DATA_ROAMING").get(null)));
return result == 1;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

Android: Check network and real internet connectivity

Below is the piece of Android code which works fine to check if network is connected or not.
public static boolean isNetworkAvailable(Context context)
{
ConnectivityManager mConnectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
return (mConnectivityManager != null && mConnectivityManager.getActiveNetworkInfo().isConnectedOrConnecting()) ? true : false;
}
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
But having an active network interface doesn't guarantee that a particular networked service is available.
A lot of time happens that we are connected to network but still not reachable to common internet network services, e.g. Google
Common scenario:
Android device connected to a Wi-Fi, which turns out to be a private
network. So isNetworkAvailable will return that network is connected, but could
not be connected to any other service
Some times the phone signal shows it is connected to service provider data plan. so network connectivity is true , but still cannot access Google/Yahoo.
One way is to check if "isNetworkAvailable" function returns TRUE, then run following code
HttpGet request = new HttpGet(url));
HttpParams httpParameters = new BasicHttpParams();
int timeoutConnection = 60000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
int timeoutSocket = 60000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
request.addHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null)
{
result = EntityUtils.toString(entity);
}
}
catch (SocketException e)
{
return "Socket Exceptiopn:" + e.toString();
}
catch (Exception e)
{
return "General Execption:" + e.toString();
}
But I think this is not an good way because it may consume lot of time
So is there any alternative efficient (in terms of time taken,speed) way ensure that we are connected to network as well as reachable to most common internet services ?
check this code... it worked for me :)
public static void isNetworkAvailable(final Handler handler, final int timeout) {
// ask fo message '0' (not connected) or '1' (connected) on 'handler'
// the answer must be send before before within the 'timeout' (in milliseconds)
new Thread() {
private boolean responded = false;
#Override
public void run() {
// set 'responded' to TRUE if is able to connect with google mobile (responds fast)
new Thread() {
#Override
public void run() {
HttpGet requestForTest = new HttpGet("http://m.google.com");
try {
new DefaultHttpClient().execute(requestForTest); // can last...
responded = true;
} catch (Exception e) {}
}
}.start();
try {
int waited = 0;
while(!responded && (waited < timeout)) {
sleep(100);
if(!responded ) {
waited += 100;
}
}
}
catch(InterruptedException e) {} // do nothing
finally {
if (!responded) { handler.sendEmptyMessage(0); }
else { handler.sendEmptyMessage(1); }
}
}
}.start();
}
Then, I define the handler:
Handler h = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what != 1) { // code if not connected
} else { // code if connected
}
}
};
and launch the test:
isNetworkAvailable(h,2000); // get the answser within 2000 ms
Code from Gilbou https://stackoverflow.com/a/5803489/2603719
I hope i can Help you
Issue #1:
Android device connected to a Wi-Fi, which turns out to be a private network.
So isNetworkAvailable will return that network is connected, but could not be connected to any other service.
Issue #2:
Sometimes the phone signal shows it is connected to service provider data plan. so network connectivity is true , but still cannot access google/yahoo.
I'm not sure about Issue #1 but I'm sure that following approach will solve Issue #2.
Ultimately, you will need to Monitor the change in Network connection,
Step 1:
Just register a BroadcastReceiver for following action
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
Step 2:
when you get callback on onReceive(Context context,Intent intent) method ,check for connectivity status.
i.e:
boolean isConnected = getIntent().getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY);
//apart from EXTRA_NO_CONNECTIVITY, there are other parameters also which will be useful to monitor
Reference:
Examples:
Working Example of Step1,Step2: how-to-monitor-network-connectivity-in-android
Android-getting-notified-of-connectivity-changes
Github: Example for network-detect-notify
Android Docs:
Connectivity Monitoring
Connectivity Manager
I hope it will be helpful !!
Use This code to check internet connection, it check all the internet connection over device. And Make Sure you have added Internet Permission in menifest.
boolean flag=false;
ConnectivityManager connectivity = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
for (int i = 0; i < info.length; i++)
if (info[i].getState() == NetworkInfo.State.CONNECTED)
{
flag=true;
}
}
if(flag==true)
{
Log.e("TAG","Internet Is Connected");
}
else
{
Log.e("TAG","Internet Is Not Connected");
}

How to find out whether android device has cellular radio module?

How can I find out for sure that device really has gsm, cdma or other cellular network equipment (not just WiFi)?
I don't want to check current connected network state, because device can be offline in the moment.
And I don't want to check device id via ((TelephonyManager) act.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId() because some devices would just give you polymorphic or dummy device ID.
Actualy, I need to check cell equipment exactly for skipping TelephonyManager.getDeviceId and performing Settings.Secure.ANDROID_ID check on those devices that don't have cellular radio. I have at least one tablet (Storage Options Scroll Excel 7") which returns different IMEIs every time you ask it, although it should return null as it has no cell radio (the same situation here: Android: getDeviceId() returns an IMEI, adb shell dumpsys iphonesubinfo returns Device ID=NULL). But I need to have reliable device id that is the same every time I ask.
I'd be glad to hear your thoughts!
If you're publishing in the store, and you want to limit your application only being visible to actual phones, you could add a <uses-feature> into your manifest that asks for android.hardware.telephony. Check out if that works for you from the documentation.
Just in case somebody needs complete solution for this:
Reflection is used because some things may not exist on some firmware versions.
MainContext - main activity context.
static public int getSDKVersion()
{
Class<?> build_versionClass = null;
try
{
build_versionClass = android.os.Build.VERSION.class;
}
catch (Exception e)
{
}
int retval = -1;
try
{
retval = (Integer) build_versionClass.getField("SDK_INT").get(build_versionClass);
}
catch (Exception e)
{
}
if (retval == -1)
retval = 3; //default 1.5
return retval;
}
static public boolean hasTelephony()
{
TelephonyManager tm = (TelephonyManager) Hub.MainContext.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null)
return false;
//devices below are phones only
if (Utils.getSDKVersion() < 5)
return true;
PackageManager pm = MainContext.getPackageManager();
if (pm == null)
return false;
boolean retval = false;
try
{
Class<?> [] parameters = new Class[1];
parameters[0] = String.class;
Method method = pm.getClass().getMethod("hasSystemFeature", parameters);
Object [] parm = new Object[1];
parm[0] = "android.hardware.telephony";
Object retValue = method.invoke(pm, parm);
if (retValue instanceof Boolean)
retval = ((Boolean) retValue).booleanValue();
else
retval = false;
}
catch (Exception e)
{
retval = false;
}
return retval;
}

How to check internet access (INCLUDING tethering!) on Android?

I am looking for a piece of code that would check network connectivity, of an Android device, including tethering, not only the wireless channels.
I have spent hours online looking for such a thing, but without any result! All the functions I found out manage only wireless net tests. Nothing with tethering. So is it at least possible? Do you have some corresponding?
this checks if Tethering is enabled. Cut from a class I changed to get adbWireless working over a tethered connection:
// check if tethering is on
try {
Method[] wmMethods = mWifiManager.getClass().getDeclaredMethods();
for(Method method: wmMethods)
if("isWifiApEnabled".equals(method.getName()))
return (Boolean) method.invoke(mWifiManager);
return false;
} catch (Exception x) {return false;}
And you also need android.permission.ACCESS_WIFI_STATE
Check this out:
public static boolean isOnline(Context context) {
boolean isOnline = false;
try {
final ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo();
if(activeNetwork != null && activeNetwork.isConnected() && activeNetwork.isAvailable()) {
isOnline = true;
} else {
isOnline = false;
}
} catch(Exception e) {
Log.e(Config.LOG_TAG, e.toString());
isOnline = false;
}
return isOnline;
}
Also add such permission into AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Categories

Resources