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

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 !

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 !

Android Runtime.getRuntime().exec command causes app to freeze before getting an output

I'am trying to Build an app that can ping servers and get latency. For which
Process process = Runtime.getRuntime().exec(pingCommand);
command calls a system/bin/ping -c command.
So, when I press Calculate (A button that i use) from UI, it freezes the app until the exec is completed. How do i fix the freeze so that it can allow me to close my keyboard while the answer is fetched?
To avoid UI freezes run in thread
new Thread(new Runnable() {
public void run() {
try {
// Send script into runtime process
Process process = Runtime.getRuntime().exec(pingCommand);
// ......
} catch (IOException e) {
e.printStackTrace();
} finally {
// .....
}
}
}).start();
}
Alternative
You can use AsyncTask like this:
private class YourTasksClass extends AsyncTask<Void, Void, String> {
private String cmd;
public YourTasksClass(String command) {
this.cmd = command;
}
#Override
protected String doInBackground(Void... voids) {
try {
Process process = Runtime.getRuntime().exec(cmd);
// ....
String someResult = "some kind of result";
return someResult;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(result != null) {
Log.d("tag", "Result: " + result);
}
}
}
Later in your code, you can call this by:
new YourTasksClass(pingCommand).execute();
you are doing network request in UI thread, so it is freezing because of waiting for response (and keeping connection alive)
use any of async ways to do network stuff, best way for you will be AsyncTask (move your network-related method calls to doInBackground method, publish results in onPostExecute)

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

sending a string to the server and receiving not updated response

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.

Categories

Resources