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).
Related
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)
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
}
)
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 !
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
I'm writing an Android messaging application, and 1 class is calling another class, and I wish for the calling class to wait for the callee class to complete before carrying on.
Caller Class (MessageManagement) code snippet is as follows:
private static Messenger myMessenger;
try {
Message msg = Message.obtain();
msg.arg1 = constructedMessage.length();
msg.arg2 = -1;
msg.obj = constructedMessage;
Log.d(TAG, "Calling myMessenger.send()");
myMessenger.send(msg);
Log.d(TAG, "Sent");
} catch (Exception e) {
e.printStackTrace();
}
// Wait here until myMessenger completes its task
doOtherStuff();
Right now, doOtherStuff() starts and finishes before myMessenger starts. I need myMessenger to complete before doOtherStuff() starts.
I've read about wait() and notify() but I'm not sure how to implement it here, or whether it's the right choice.
Some background about the flow of the program. It's basically a messaging app that I inherited, so I'm not exactly sure of its framework. From what I can tell tracing the flow of the code:
When an SMS message is received, the SMS receiver BroadcastReceiver(SmsReceiver) handles it, getting the sender address and message body, then calling a SMS handler service(HandleSmsService), which then calls the caller class in a runnable with the following code:
HandleSmsService
public class HandleSmsService extends Service {
private String message;
private MessageManagement messageManager;
private Handler timeoutHandler = new Handler();
#Override
public void onStart(Intent intent, intent startid) {
message = intent.getExtras().getString("message");
messageManager = new MessageManagement(this);
timeoutHandler.postDelayed(runnable, 10);
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
try {
messageManager.handleMessage(message);
stopSelf();
} catch (Exception e) {
e.printStackTrace();
}
}
};
MessageManagement is my caller class, and MessageManagement.handleMessage() is the top most code snippet presented earlier.
The MessageManagement.handleMessage() apparently calls another Handler in the callee class when it calls myMessenger.send(msg). This Handler code is as follows:
private Handler smsHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// do some stuff
}
};
I'm assuming the posted code is running on the MainThread and the reason why you are using a handler is that something asynchronous is done on another thread when receiving that message.
In that case, you can't use wait on the thread, as it will lock up the UI and probably cause an application not responding error.
Without changing too much of your code, one way to do it is to nest a listener in your constructedMessage for e.g.
public class DoStuffRequest {
private OnFinishListener mOnFinishListener;
private boolean isCanceled;
private String mMessage;
public interface OnFinishListener {
public void onFinish();
}
public DoStuffRequest(String message) {
mMessage = message;
}
public OnFinishListener getOnFinishListener() {
return mOnFinishListener;
}
public void setOnFinishListener(OnFinishListener onFinishListener) {
mOnFinishListener = onFinishListener;
}
public void cancel() {
isCanceled = true;
}
public void notifyFinish() {
if (!isCanceled && mOnFinishListener != null) {
mOnFinishListener.onFinish();
}
}
public String getMessage() {
return mMessage;
}
}
then use some along the line of this to get the ball rolling:
private static Messenger myMessenger;
private DoStuffRequest mRequest;
...
private void send(String message) {
mRequest = new DoStuffRequest(message);
mRequest.setOnFinishListener(new ConstructedMessage.OnFinishListener() {
#Override
public void onFinish() {
doOtherStuff();
}
});
try {
Message msg = Message.obtain();
msg.arg1 = constructedMessage.length();
msg.arg2 = -1;
msg.obj = constructedMessage;
Log.d(TAG, "Calling myMessenger.send()");
myMessenger.send(msg);
Log.d(TAG, "Sent");
} catch (Exception e) {
e.printStackTrace();
}
}
private void doThisIfYouWantToCancel() {
if (mRequest != null) {
mRequest.cancel();
}
}
your Handler/Service code can now call constructedMessage.finish() when the async stuff is done. Depending on what doOtherStuff() does (e.g. when manipulating the UI), you might want to do this on the MainThread (the code i've written above is NOT thread safe and i assume you are calling the listener on the MainThread).
Also remember to call constructedMessage.cancel() in case you do not want to get notified any more (e.g. you are leaving the activity/fragment).
this is just one way to do it, depending on your needs, some other methods might be a better choice.
I guess it should look something like this:
try {
Message msg = Message.obtain(handler, new Runnable() {
#Override
public void run() {
doOtherStuff();
}
});
msg.arg1 = constructedMessage.length();
msg.arg2 = -1;
msg.obj = constructedMessage;
Log.d(TAG, "Calling myMessenger.send()");
msg.sendToTarget();
Log.d(TAG, "Sent");
} catch (Exception e) {
e.printStackTrace();
}
The other way to do this using native means:
private static Messenger myMessenger = new Messenger(new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
// do something what you need
if (msg.getTarget() != null) {
msg.sendToTarget();
}
return false;
}
}));
try {
final Message msg = Message.obtain();
msg.setTarget(new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
doOtherStuff();
return false;
}
}));
msg.arg1 = constructedMessage.length();
msg.arg2 = -1;
msg.obj = constructedMessage;
Log.d(TAG, "Calling myMessenger.send()");
myMessenger.send(msg);
Log.d(TAG, "Sent");
} catch (final Exception e) {
e.printStackTrace();
}