This question already has answers here:
AsyncTask return value
(4 answers)
Closed 9 years ago.
I am calling soap webservice and need to display what is returned. but I couldnt do it because AsyncTask is complex and I dont know how to use it properly. would you please tell me how to return data from the called function via asynctask?
here is my code
public class WebserviceTool {
private final String NAMESPACE = "http://tempuri.org/";
private final String URL = "http://192.168.0.11:9289/Service1.asmx";
private final String SOAP_ACTION = "http://tempuri.org/get_currency";
private final String METHOD_NAME = "get_currency";
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public String execute_barcode_webservice(String s1, String s2) {
//Create request
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("date",s1);
request.addProperty("cur_code",s2);
//Create envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.encodingStyle = SoapEnvelope.ENC;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
Object response;
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
response = (Object) envelope.getResponse();
Log.i("my_error", response.toString());
} catch (Exception e) {
Log.i("my_error", e.getMessage().toString());
}
return "testarif";
}
public class AsyncCallWS extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
try {
execute_barcode_webservice(params[0], params[1]);
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
#Override
protected void onPostExecute(Void result) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
}
this is the function execute_barcode_webservice() that does all the job and returns data. but since I call execute_barcode_webservice() view AsyncTask, I dont know how to return with it. how can I do it?
The result of the async task execution is the response object produced by execute_barcode_webservice(). However, don't think about the async task as something that will execute and return a value to you. Instead, inside the method onPostExecute() you must take the response object and process it (extract its values and display them in a list, or whatever you want to do with it). The async task is just a way to execute some code in a separate thread then go back to the main thread (the UI thread) and process the results, which is done in onPostExecute().
My suggestion: rewrite execute_barcode_webservice() to return a response object instead of a String (an object that can be null if the operation fails) and pass that object to the onPostExecute() method. You will have to change the async task to:
public class AsyncCallWS extends AsyncTask<String, Void, Object> {
#Override
protected Object doInBackground(String... params) {
Object response = null;
try {
response = execute_barcode_webservice(params[0], params[1]);
} catch (Exception e) {
// TODO: handle exception
}
return response;
}
#Override
protected void onPostExecute(Object response) {
if (response != null) {
// display results in a list or something else
}
}
Related
I have several activities and one asyncTask that uses the same interface for callback methods as below
The interface used by all
public interface AsyncTaskCallback {
void onCookie(CookieManager cookieManager);
void onResponse(String response);
void onProgress(String... values);
void onError(Exception e);
}
AsyncTask1 is called from all activities as follows
public void exec_taskt() {
alertDialog.SetText("Sending Request...");
AsyncTask1 task1 = new AsyncTask1("https://stackoverflow.com");
task1.setCookieManager(cookiejar);
task1.setCallback(this);
task1.execute();
}
Each Activity also implements the interface
#Override
public void onCookie(CookieManager cookieManager) {
cookiejar = cookieManager;
}
#Override
public void onResponse(String response) {
try {
PostProc(response);
}catch (Exception e){ // ERROR HERE
e.printStackTrace();
}
}
#Override
public void onProgress(String... values) {
alertDialog.SetText(values[0]);
}
#Override
public void onError(Exception e) {
///SAME ERROR HERE TOO
//Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
swipeRefreshLayout.setRefreshing(false);
}
private void PostProc(String response) {
//the response string is parsed and displayed in a recyclerview in this method
//this method is slightly different for each activity
}
AsyncTask1
public class AsyncTask1 extends AsyncTask<String, String, String> {
private String address = "";
private CookieManager mCookieManager;
private Exception mException;
private AsyncTaskCallback mCallback;
public AsyncTask1 (String page) {
this.address = page;
}
public void setCookieManager(CookieManager cm) {
this.mCookieManager = cm;
}
public void setCallback(AsyncTaskCallback cb) {
this.mCallback = (AsyncTaskCallback) cb;
}
#Override
protected String doInBackground(String... strings) {
try{
//all code here is executed without error
//code skipped for simplicity
// basically just loads the given url and then...
publishProgress("Page Loaded");
mCallback.onCookie(mCookieManager);
mCallback.onResponse(response);
return response;
} catch (Exception e) {
publishProgress("Error");
e.printStackTrace();
mCallback.onError(e);
return "";
}
#Override
protected void onProgressUpdate(String... values) {
Log.d(tag, TextUtils.join(",", values));
mCallback.onProgress(values);
super.onProgressUpdate(values);
}
}
The errors I get are marked
ERROR HERE
in the code above. and the message is as follows
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
My main suspect is the PostProc() method in the activity that does play with the UI component. But doesnt implementing the interface in the activity mean that part of the code runs in the main UI thread? I know you can pass the activity instance to the asyncTask and call the PostProc() method from postexecute of the asyncTask but I would like to explore an alternative way to it, since the same asynctask is accessed by other activities as well. the returns are the same for all activities. Only the PostProc Method is different.
Thanks in advance
Instead of using callback interface you can use a android.os.Handler() which is associated with the Looper.getMainLooper() to update the views like:-
AsyncTask1 task1 = new AsyncTask1(android.os.Handler(Looper.getMainLooper(), msg -> {
// handle message sent from asyncTask
return false;
}), url);
Then in task1 send the message using using the handler
public AsyncTask1 (Handler handler, String page) {
this.address = page;
this.handler = handler;
}
then ,
Message message = new Message();
message.obj = uiData;
handler.sendMessage(message);
The handler onHandleMessage will always execute on the main looper !
In the AsyncTask android. When calling a method in another class gets an exception which equals to null in the doInBackGround() task.
Even the hard coded inside the rest.request(url, method, json) doesn't work
protected JSONArray doInBackground(Void... arg0) {
try {
return rest.request(url, method, json); // <-- returns json array
} catch (Exception e) {
this.e = e;
}
return null; // <--- returning this null
}
Other things are like this,
private class doRequest extends AsyncTask<Void, JSONArray, JSONArray>
protected void onPostExecute(JSONArray data)
/*rest client class*/
public class AndrestClient {
// The client to use for requests
DefaultHttpClient client = new DefaultHttpClient();
public JSONArray request(String url, String method, String json) throws RESTException {
if (method.matches("GET")) {
return get(url);
} else if (method.matches("POST")) {
return post(url, json);
} else if (method.matches("PUT")) {
//return put(url, data);
} else if (method.matches("DELETE")) {
//return delete(url);
}
throw new RESTException("Error! Incorrect method provided: " + method);
}
public JSONArray get(String url) throws RESTException {
String jsonjr = "['Chanuthi','Damsith','Dunili','Isath','Minuka','Uvin','Vidath']";
JSONArray jsonAraay = null;
try {
jsonAraay = new JSONArray(jsonjr);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jsonAraay;
}
}
The exception I got is e=null. All the other things work properly. When I am hard coding the result inside in the doInBackGround it works properly. Also the rest client get method returns the exact thing.
It appears you're using AsyncTask improperly. Firstly, you must subclass/nest your AsyncTask as per the Android documentation:
http://developer.android.com/reference/android/os/AsyncTask.html
In addition, you should follow the fundamental rules for calling methods of an outter class from a nested class.
There are some alternatives, like:
Create the AndrestClient object in onPreExecute() of the AsyncTask
Pass the AndrestClient object to the doInBackground as a parameter, then call its methods by doing something like this in the outter class:
doRequest.execute(rest);
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
I'm writing an app for android in Java, and the server side also with Java.
The connection is through sockets. To send strings to the server I'm using asyncTask as follows:
public static void send(String content) throws IOException {
mConnectionHandler.new AsyncSendToServer().execute(content);
}
private class AsyncSendToServer extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
out.println(params[0]);
return null;
}
}
Now the response from the server is done as follows:
public static String receive() {
mConnectionHandler.new AsyncReceiveFromServer().execute();
return serverResponse;
}
private class AsyncReceiveFromServer extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
String result = null;
try {
result = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
protected void onPostExecute(String result) {
serverResponse = result;
}
}
Because the methods are async, the serverResponse does not get the appropriate value in receive(). When I execute AsyncReceiveFromServer, receive() return the value of serverResponse before it's get updated in the asyncTask. What can I do in order to send the updated serverResponse?
Execute your AsyncReceiveFromServer from the onPostExecute of your AsyncSendToServer.
This way, you are absolutely certain that the Send has finished.
I am trying to write a Http API in android. I am using a AsyncTask to run the calls to my web service.I am not interested in updating the UI, instead all I want is the data to use in my application logic. This is what I have so far:
public class DataManager{
public static String result;
public DataManager ()
{
}
public String get ()
{
User user = new User ();
user.execute("http://someuri/service/users/id/21001");
return user.getResult();
}
}
public class User extends AsyncTask <String,Void,String>{
private String result;
#Override
protected String doInBackground(String... arg0)
{
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet (arg0[0]);
try
{
HttpResponse response = client.execute (get);
if (response.getStatusLine().getStatusCode () == 200)
{
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}
}
catch (ClientProtocolException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
this.result = result;
}
public String getResult ()
{
return result;
}
}
I want a typical call to be:
DataManager manager = new DataManager ();
String value = manager.get ();
But when I run this I get back null. What is causing this and how can I refactor this code to get the desired behavior.
The whole idea of a thread is that it runs concurrently. Basically, here's what you're doing:
User user = new User (); // Create User object
user.execute("http://someuri/service/users/id/21001"); // Start thread
return user.getResult(); // Return thread result
However, there is no time for the thread to run between "start" and "return result".
I would suggest using some kind of callback; first, make get() return void, and remove the return statement. Then, you pass in some object which implements YourCallback, and then call onCallback(result) from within onPostExecute().
Your calling code would then look like this:
DataManager x = new DataManager();
x.get(new YourCallback() {
public void onCallback(String result) {
// ...
}
});
There is a much fuller example in this fantastic answer.