简体   繁体   中英

How to properly use AsyncTask on Android?

I need help with checking if the phone my app is running on is connected to the Internet. I started with pinging an IP to check connection. It looked like this:

    protected Boolean checkInternetConnection(Void... params) {
        try {
            InetAddress ipAddr = InetAddress.getByName("https://www.google.com");

            if (!ipAddr.isReachable(10000)) {
                return false;
            } else {
                return true;
            }

        } catch (Exception e) {
            Log.e("exception", e.toString());
            return false;
        }
    }
}

However, it allways threw the NetworkOnMainThreadException, so I used AsyncTask:

private class CheckConnectionTask extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            InetAddress ipAddr = InetAddress.getByName("https://www.google.com");

            if (!ipAddr.isReachable(10000)) {
                return false;
            } else {
                return true;
            }

        } catch (Exception e) {
            Log.e("exception", e.toString());
            return false;
        }
    }
}

Is this code correct? Because I don't know how to call it. I tried:

new CheckConnectionTask().execute();

Is anything missing there? Because it doesn't work. Also please note that I've seen a lot of previous questions, but I didn't find any answer to this problem, so I asked my own question. If you've seen an answered question that can solve my problem you can link it here, but keep in mind that I am not experienced with Android or Java, so it might be unclear to me. I would preffer correct code as an answer, and a brief explaination why my didn't work. Also, I need to know if the phone is connected to the INTERNET, not a NETWORK, so ConnectivityManager won't wor for me.

EDIT - thank you all for your answers. First of all, I have all the permissions required. Also, I can't get any results currently, as Android Studio highlights the following code:

Boolean internetConnection;
internetConnection = new     CheckConnectionTask().execute();

As incorrect and it simply won't let me call the function. What is wrong with it? Is it missing any parameters? Because I've defined params as Void so that seems illogical.

Edit 2 - I've used onPostExecute, as suggested by @vandaics, and it looks like this now:

private class CheckConnectionTask extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            InetAddress ipAddr = InetAddress.getByName("google.com");

            if (!ipAddr.isReachable(10000)) {
                return false;
            } else {
                return true;
            }

        } catch (Exception e) {
            Log.e("exception", e.toString());
            return false;
        }
    }
    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        internetConnection = result;
    }
}

It works, and I call it when calling the onCreate method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new CheckConnectionTask().execute();
}

It works, my apps checks if the Internet is connected and reacts properly. If you think something might not work, or there is an easier way to do that, let me know. Many thanks to you guys, especially @vandaics and @Sunil. Also, do I need to use superclass like here?:

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        internetConnection = result;
    }

What does it do and is it necessary?

You currently are not seeing anything because you have no log statements or you are not really checking for anything.

The call

new CheckConnectionTask().execute()

is running the AsyncTask. It's just that there is no output for the task to show.

you can check for the output and see if it is what you want.

private class CheckConnectionTask extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            InetAddress ipAddr = InetAddress.getByName("https://www.google.com");

            if (!ipAddr.isReachable(10000)) {
                return false;
            } else {
                return true;
            }

        } catch (Exception e) {
            Log.e("exception", e.toString());
            return false;
        }
    }

    @Override
    public void onPostexecute(Boolean result) {
        // TO DO on the UI thread
        Log.i("AsyncTask", "Result = " + result");
    }
}

EDIT: The call:

new CheckConnectionTask().execute()

returns an instance of the AsyncTask that it is executing and not a Boolean (although you do specify that Boolean should be the output). Hence you are seeing a compilation error here. AsyncTask was designed to be self contained - it does everything it's supposed to do and then terminates. If you do have to modify a class level instance variable (from the class that contains the AsyncTask as an inner task) that can be done but not suggested.

If you are going to use AsyncTaks you're missing the onPostExecute method:

 protected void onPostExecute(Boolean result) {
     //your code here
 }

You can also add the optional onProgressUpdate method:

 protected void onProgressUpdate(Integer... progress) {
    //do something on update
 }

Then to execute you do:

new DownloadFilesTask().execute();

Here is a good example you can use: http://developer.android.com/reference/android/os/AsyncTask.html

to check if the internet connection is available, you can do this:

private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();
    //return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

You can't call

Boolean internetConnection;
internetConnection = new CheckConnectionTask().execute();

the return value of excute() is not what you want. If you want use asyntask you can set a boolean variable in onPostExecute(...) :

private boolean isConnect = false;
private class CheckConnectionTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... params) {
    try {
        InetAddress ipAddr = InetAddress.getByName("https://www.google.com");

        if (!ipAddr.isReachable(10000)) {
            return false;
        } else {
            return true;
        }

    } catch (Exception e) {
        Log.e("exception", e.toString());
        return false;
    }
}
@Override
protected void onPostExecute(Boolean result) {
    super.onPostExecute(aVoid);
    isConnect = result;
}
}

But, I never use this approach to get status of internet connection, beacause I must run this asyntask before everything to get exact status.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM