sending a string to the server and receiving not updated response - java

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.

Related

Access Activity Method From AsyncTask Callback Interface

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 !

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 !

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

need to return value from AsyncTask [duplicate]

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
}
}

Categories

Resources