How to properly use AsyncTask on Android? - java

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.

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.

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

Related

AsyncTask work not really correctly (Android)

I'm working on some "sockets-application" and i need help. I have a class with connection-method:
public class ClientSocketConnection {
private int port = 49150;
private String host;
public ClientSocketConnection(String host){
this.host = host;
}
public boolean connect(){
Boolean isConnected = false;
AsyncTask<Void, Void, Boolean> asyncProcess = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... voids) {
try {
Socket client = new Socket();
client.connect(new InetSocketAddress(host, port), 1000);
} catch (IOException ex) {
Log.d(TAG, "Client socket exception", ex);
return false;
}
return true;
}
};
asyncProcess.execute();
try {
isConnected = asyncProcess.get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return isConnected;
}
I'm trying to establish a socket-connection using AsyncTask in Application-class:
private void executeRequest(){
ClientSocketConnection client = new ClientSocketConnection(txtIPAddress.getText().toString());
AsyncTask<Void, Void, Boolean> connectionTask = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... voids) {
Log.d(TAG, "Begin");
boolean flag = client.connect();
Log.d(TAG, "End");//Not displayed
return flag;
}
#Override
protected void onPostExecute(Boolean isConnected) {
if(isConnected){
Toast.makeText(getApplicationContext(), "Connection established", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Incorrect IP-Address", Toast.LENGTH_SHORT).show();
}
}
};
connectionTask.execute();
}
But doInBackground-method in executeRequest() does not work completely (End-message isn't displayed). But, interestingly, everything is fine without using AsyncTask in Application class, when doing it in main (UI) thread...
What could be the problem? There are no errors in the log. The application continues to work...
Thanks in advance))
Because you're calling AsyncTask.get(). That's causing you to not be asynchronous and block until the task is finished. That function should never be called. There's very limited uses for it, and if you're not trying to do something very unusual its wrong. There's also no reason to have 2 async tasks here.
Which is your second problem- 2 async tasks. AsyncTasks all share the same thread, and are executed round robin. That means task 2 can't be exeucted until task 1 finishes- but you have task 1 waiting for task 2, which will never start. You basically deadlocked yourself.
Solution: do not use AsyncTask.get(). Rewrite this to use a single AsyncTask, or to use real Threads (this is generally preferable for networking, as if you use AsyncTasks elsewhere in the app they will all be blocked waiting for the network request to finish).

Execute Async Tasks one after another

I know that there are already some discussions and I searched on the internet a lot for a solution, I have 3 get calls (volley) I want to execute one after another because the next get does need variables which were set on the get before this but it doesn't seem to work here. When I debug the whole process it worked fine of course but when running the app normally it doesn't get any data which I would have gotten when debugging it.
Now I tried to set static boolean variables to make this whole thing work but theres so far no success..
public class AsyncToken extends AsyncTask<String , Void, Void> {
private PacketBuilder pb = new PacketBuilder();
private Context context;
AsyncUser u = new AsyncUser(context);
#Override
protected Void doInBackground(String... params) {
while( task1finished == false )
{
try
{
Log.d("App", "Waiting for GetTask");
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
Log.d("App", "GetTask finished");
// Do what ever you like
// ...
pb.Get("token", "", params[0], context);
return null;
}
protected void onPostExecute(String ... params)
{
task2finished = true;
}
public AsyncToken(Context context)
{
this.context = context;
}
}
EDIT, the code:
When async task is completed onPostExecute() is called, so start another async task with computed values there. You can have global variables what should be computed or you can pass them through parameters.
//start first async task
new TaskOne().execute();
class TaskOne extends AsyncTask<Void,Void,String>{
String tmp;
#Override
protected String doInBackground(Void... records) {
tmp = computeNeededValue();
return tmp;
}
#Override
protected void onPostExecute(String result) {
new TaskTwo().execute(tmp);
}
)
class TaskTwo extends AsyncTask<String,Void,Void>{
#Override
protected Void doInBackground(String... records) {
//use computed value from first task here
}
#Override
protected void onPostExecute(Void result) {
//start another async task
}
)

Send a value from a listener interface to onPostExecute in AsyncTask class

I'm actually trying to build a WebSocket client application on Android with the nv-websocket-client.
But I'm stuck with interfaces in my doInBackground function.
I'm trying to use a AsyncTask for the WebSocket connetion, but I'm stuck when I have to pass to onPostExecute the message from onTextMessage :/
private class Reseau extends AsyncTask<Void, Void, String> {
// This is run in a background thread
#Override
protected String doInBackground(Void... params) {
socket.addListener(new WebSocketAdapter() {
#Override
public void onTextMessage(WebSocket websocket, String message) throws Exception {
// Here I want to return the String message to onPostExecute
// How to do it ? return message do not work because onTextMessage is void
}
});
try { socket = new WebSocketFactory()
.setConnectionTimeout(5000)
.createSocket(adresse[0] + adresse[1])
.connect();
}
catch (IOException e) { e.printStackTrace(); } catch (WebSocketException e) { e.printStackTrace(); }
return "I want to pass message from onTextMessage to onPostExecute";
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
zone.append(result);
}
}
I can use a RunOnUIThread or enable StrictMode but this is not the good method to do that job.
Thank you for your help !

Cancel AsyncTask without loop

I would like to cancel an AsyncTask in my Android application. The kicker is, my AsyncTask does NOT contain a loop, so I can't use break.
Here is my AsyncTask.doInBackground():
protected Void doInBackground(String... params) {
String location = params[1];
if(!location.matches("-?[0-9.]*,-?[0-9.]*")) {
try {
location = Util.getLatLngFromMapsQuery(location);
} catch (UnchainedAPIException e) {
setErrorCode(ERROR_GEO);
this.cancel(true);
}
}
UnchainedAPI unchainedAPI = new UnchainedAPI(YELP_KEY, YELP_SECRET, YELP_TOKEN, YELP_TOKEN_SECRET,
FOURSQUARE_ID, FOURSQUARE_SECRET, GOOGLE_PLACES_KEY);
try {
nonChains = unchainedAPI.getUnchainedRestaurants(params[0], location);
} catch (UnchainedAPIException e) {
setErrorCode(ERROR_API);
this.cancel(true);
}
if(nonChains.size() == 0) {
setErrorCode(ERROR_API);
}
return null;
}
What can I do here?
AsyncTask.cancel(boolean mayInterruptIfRunning)
does the trick.
or from inside the task:
cancel(true);
If you need to break the AsyncTask from doInBackground() just use
return null;
where you need to break. From onPostExecute() you can use
this.cancel(true);

Android return value in AsyncTask onPostExecute using Interface [duplicate]

This question already has answers here:
Android AsyncTask don't return correct Result
(3 answers)
Closed 8 years ago.
in this below code i want to return value from AsyncTask with using an Interface. but i get wrong value and i can not return correct value from onPostExecute.
i'm developed this link tutorials with my code. i can not use correctly with that.
Interface:
public interface AsyncResponse {
void processFinish(String output);
}
Ksoap Main class:
public class WSDLHelper implements AsyncResponse{
public SoapObject request;
private String Mainresult;
public String call(SoapObject rq){
ProcessTask p =new ProcessTask(rq);
String tmp = String.valueOf(p.execute());
p.delegate = this;
return Mainresult;
}
#Override
public void processFinish(String output) {
this.Mainresult = output;
}
}
class ProcessTask extends AsyncTask<Void, Void, Void > {
public AsyncResponse delegate=null;
SoapObject req1;
private String result;
public ProcessTask(SoapObject rq) {
req1 = rq;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(this.req1);
AndroidHttpTransport transport = new AndroidHttpTransport(Strings.URL_TSMS);
transport.debug = true;
try {
transport.call(Strings.URL_TSMS + this.req1.getName(), envelope);
this.result = envelope.getResponse().toString();
} catch (IOException ex) {
Log.e("" , ex.getMessage());
} catch (XmlPullParserException ex) {
Log.e("" , ex.getMessage());
}
if (result.equals(String.valueOf(Integers.CODE_USER_PASS_FALSE))) {
try {
throw new TException(PublicErrorList.USERNAME_PASSWORD_ERROR);
} catch (TException e) {
e.printStackTrace();
}
}
Log.e("------------++++++++++++++++-----------", this.result);
return null;
}
protected void onPostExecute(String result) {
/* super.onPostExecute(result);*/
delegate.processFinish(this.result);
}
}
please help me to resolve this problem
That can't work. You are creating and executing the AsyncTask (asynchronously!) and then call return Mainresult (synchronously!) when it hasn't received the result yet. The solution is to remove the redundant class WSDLHelper and access ProcessTask directly
Beside that, you're using AsyncTask incorrectly (saving the result in a class variable instead of passing it as a parameter). Here's the full version:
public class ProcessTask extends AsyncTask<Void, Void, String> {
public AsyncResponse delegate=null;
SoapObject req1;
public ProcessTask(SoapObject rq, AsyncResponse delegate) {
req1 = rq;
this.delegate = delegate;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(this.req1);
AndroidHttpTransport transport = new AndroidHttpTransport(Strings.URL_TSMS);
transport.debug = true;
String result = null;
try {
transport.call(Strings.URL_TSMS + this.req1.getName(), envelope);
result = envelope.getResponse().toString();
} catch (IOException ex) {
Log.e("" , ex.getMessage());
} catch (XmlPullParserException ex) {
Log.e("" , ex.getMessage());
}
if (result != null && result.equals(String.valueOf(Integers.CODE_USER_PASS_FALSE))) {
try {
throw new TException(PublicErrorList.USERNAME_PASSWORD_ERROR);
} catch (TException e) {
e.printStackTrace();
}
}
Log.e("------------++++++++++++++++-----------", result);
return result;
}
protected void onPostExecute(String result) {
/* super.onPostExecute(result);*/
delegate.processFinish(result);
}
}
Now you would execute ProcessTask from outside like this, which will make sure you receive the result asynchronously:
new ProcessTask(rq, new AsyncResponse() {
#Override
public void processFinish(String output) {
// do whatever you want with the result
}
}).execute();
Your result will always be null, because you return null in the doInBackground() method. The value you return in doInBackground() will be passed to onPostExecute(). Change your AsyncTask<Void, Void, Void> to AsyncTask<Void, Void, String>, and return the result. This will call onPostExecute(String result) with the correct result.
Perhaps this link might help you a bit: http://bon-app-etit.blogspot.be/2012/12/using-asynctask.html

Categories

Resources