I'm having trouble with the case where a SocketChannel.connect times out. The code bellow works fine in my old Android 2.3 phone and my old Android 3.2 tablet but crashes in Android 4.2.2:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult = (TextView) findViewById(R.id.tvResult);
btnTest = (Button) this.findViewById(R.id.btnTest);
btnTest.setOnClickListener(doTest);
}
protected View.OnClickListener doTest = new View.OnClickListener() {
@Override
public void onClick(View v) {
new AsyncTest().execute();
}
};
private class AsyncTest extends AsyncTask {
private String result = "";
@Override
protected Void doInBackground(Void... params) {
InetSocketAddress addr = new InetSocketAddress("192.168.0.13", 4040);
boolean bConnect = false;
try {
SocketChannel clntChan = SocketChannel.open();
bConnect = clntChan.connect(addr);
if (bConnect) {
clntChan.close();
result = "Connected";
} else {
result = "Did not connected";
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e.getMessage());
result = "Exception " + e.getMessage();
}
return null;
}
@Override
protected void onPostExecute(Void ret) {
tvResult.setText (result);
}
}
I am testing the case where there is no one is listening on port 4040 at 192.168.0.13. In Android 2.3 the try/catch will catch a "Connection timeout" exception (as expected). In Android 4.x I get the following:
FATAL EXCEPTION: AsyncTask #1 java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:299) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352) at java.util.concurrent.FutureTask.setException(FutureTask.java:219) at java.util.concurrent.FutureTask.run(FutureTask.java:239) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:838) Caused by: java.lang.AssertionError: java.net.SocketTimeoutException: failed to connect to /192.168.0.13 (port 4040) after 90000ms at libcore.io.IoBridge.connect(IoBridge.java:102) at java.nio.SocketChannelImpl.connect(SocketChannelImpl.java:177) at br.com.dqsoft.testeconnect.MainActivity$AsyncTest.doInBackground(MainActivity.java:63) at br.com.dqsoft.testeconnect.MainActivity$AsyncTest.doInBackground(MainActivity.java:1) at android.os.AsyncTask$2.call(AsyncTask.java:287) at java.util.concurrent.FutureTask.run(FutureTask.java:234) ... 4 more Caused by: java.net.SocketTimeoutException: failed to connect to /192.168.0.13 (port 4040) after 90000ms at libcore.io.IoBridge.connectErrno(IoBridge.java:176) at libcore.io.IoBridge.connect(IoBridge.java:112) at libcore.io.IoBridge.connect(IoBridge.java:100) ... 9 more
A could not find a way to catch this exception, the app is closed by the OS. While a timeout is not a normal condition, I should be able to detect that and present an error message to the user instead of just crashing.
The case where the connect succeeds works fine in all the devices.
Edit: The initial paragraph erroneously mentioned Android 2.4 instead of 4.2.2.
Edit: Simplified the code as suggest by Jarred and added additional information.
Update: Tested on a Android 4.4.4 device and it worked. I will close this as a bug of Android 4.2.2 (maybe on this specific device).