I know what causes a NetworkOnMainThreadException, as well as how to fix it, but for the purposes of improving the development experience, I'd like to be able to catch the exception and at least log the event or alert the user (who is still the developer at this point)...
Strangely, I'm not having any luck with this code (which sends and receives over my TCP socket):
try
{
toServer.println (msg.trim());
resp = fromServer.readLine();
}
catch (android.os.NetworkOnMainThreadException nex)
{ ... do something here ... }
Eclipse doesn't recognize that exception at all, and I copy-pasta-ed the exception type from the Android Developer website -- I'm pretty sure I spelled it right...
Is there something I don't know about Java (perhaps) that makes this exception uncatchable??
Thanks,
R.
Is there something I don't know about Java (perhaps) that makes this exception uncatchable??
Yes, StrictMode makes it uncatchable. Either way though, you should not catch this exception. Instead, you should implement your code correctly by wrapping your code in an AsyncTask. The reason why this exception is thrown is to prevent you from slowing down your application by blocking the UI thread.
Read my blog post for more info:
Why Ice Cream Sandwich Crashes Your App
Well I just tested this on my version of eclipse, and it works just fine.. I guess I would check which version of the api you are using? looks like to throw that exception you need a minimum api version 11. Otherwise perhaps eclipse is to blame? All I know is that this code is correct and should be executing without any issues.
Are you sure this is the first use of networking in your application?
If you are connecting to a server usually at that time NetworkOnMainThreadException should be thrown. Try adding a log statement before the try and see if it shows up. If it does not the Exception is thrown earlier.
Related
I've encountered a situation where anything that runs in a coroutine (database queries, network requests or response processing) and fails at some point, simply crashes the app without any logs at all. Is it the expected behavior or do I have something misconfigured?
Here's a simple piece of code that reproduces the error.
Nothing changes with different Dispatchers.
This is the only output I'm getting, followed by app termination
And these are the dependencies I'm using, the latest version at the moment of writing.
It's also reproducing in a simple CLI app without the Android framework.
Edit: Just to make it clear. I'm not trying to see the Exceptions that I'm throwing. I'm trying to get some output when my app crashes because of an unknown reason.
Edit2: To add some clarity, here is another example of the situation without any "throw" statements.
Since the exception in happening inside the coroutine, it makes sense to find it there also. Just surround it with try/catch and you will see the magic:
GlobalScope.launch{
try{
print("Your printing message")
throw Exception("Message here")
}catch(exception: Exception){
exception.printStacktrace()
}
}
During debugging of Android app, sometimes InterruptedException occurs and crashes the app. I've been able to set a break-point on default exception handler, but call stack is not informative.
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:1991)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2025)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1048)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:776)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1035)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1097)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:820)
What is telling is that the interrupted thread is always RxCachedThreadScheduler-4 (or some other number)
What would be a systematic approach towards finding the root cause of the exception?
Set breakpoint at the method Thread::interrupt and catch the offender. If you think that this interruption should not happen, and you cannot switch off the call which interrupts your thread, then you can override Thread::interrupt in your thread implementation, and force the the thread pool to use your implementation by providing your own ThreadFactory.
It looks like the crash is happening from a third party code package, you should post your issue with the source project as well for additional help. Please post any code related to how you use this package to help troubleshoot too. Make sure you're using the latest version of this package in case they already fixed this issue. The stack trace isn't very helpful because the other project is launching threads and the crash happens from within one of their threads. Likely, you're not using the package as intended or there is a bug in it that they need to fix.
https://github.com/ReactiveX/RxJava
My Android app uses the AWS Java SDK for uploading user photos to S3.
Whenever a user's phone's clock is 'skewed', this causes all transfers to fail. This is a well documented aspect of S3:
http://aws.amazon.com/articles/1109?_encoding=UTF8&jiveRedirect=1#04
It appears that the upstream S3 service reports this error quite clearly:
HTTP Status Code: 403 Forbidden
Error Code: RequestTimeToo-Skewed
Description: The difference between the request time and the server's
time is too large.
However when using the Java SDK, it seems as if the informative 403 code is lost ... and I have only an opaque "TransferState.Failed" to go by (which incidentally is the same error if internet connectivity is lost, if it times out, etc...).
As far as I can tell from the docs:
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/index.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferProgress.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Transfer.TransferState.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Upload.html
There is no way to get the additional "RequestTimeToo-Skewed" metadata about a transfer failure.
Am I missing it? Is there any way to get additional error information when an S3 transfer fails using Amazon's Java SDK?
UPDATE #1:
A commenter kindly highlighted that I should clarity two points:
I am actually using the AWS SDK for Android (which seems very similar to the Java SDK, but is nonetheless distinct)
I am using the TransferManager class to perform my upload. Apparently, this is a high-level class that wraps the lower-level AmazonS3Client ... and this lower-level class should expose the error reporting I need, but I am still investigating the exact tradeoffs involved between TransferManager and AmazonS3Client. As far as I can tell, there is no way to get progress information via the (synchronous) AmazonS3Client.putObjectRequest which would be a blocker for me...
UPDATE #2:
My sincere thanks to Jason (of the AWS SDK team) for stopping by and helping me out here. The important information is, indeed, available as properties on an AmazonS3Exception if you use certain methods. The docs had originally confused me and I thought that a manual Thread.sleep() loop was required to poll status (and thus I could not leverage waitForCompletion or waitForException), but if you use ProgressListener on PutObjectRequest you can get full progress callbacks and the error-fidelity of AmazonS3Exception.
these two methods should help you out:
Transfer.waitForCompletion()
Transfer.waitForException()
If you detect that your transfer has failed based on a transfer progress event, you can simply call Transfer.waitForException() to be returned the exception that occurred. That exception will be an AmazonServiceException in this case, with all of the info that you need to see that the real problem was a clock skew issue.
Alternatively, the Transfer.waitForCompletion() method will unwrap the original exception from an ExecutionException and directly throw the original exception, just as if it'd all been happening on one thread. This might be a more convenient approach if you want to use a catch blocks to catch different types of errors cleanly and elegantly.
I disagree that the "catch Exception" block is "brutally broad". The point of that code is to catch any error that happens, mark the transfer as failed and rethrow the error so that the application code can know about it. If it were less broad, then that's exactly the case where exceptions could sneak through and transfer progress wouldn't be updated correctly and would be out of sync with reality.
Give those two methods and shot and let us know if that helps!
Well, I have debugged Amazon's SDK and I'm sorry to say that this information is being swallowed internally. Perhaps I will try to submit a patch.
Details: an AmazonS3Exception is being thrown internally which does in fact accurately report this exact error scenario, but a brutally broad try catch ( Exception e ) consumes it and washes away the specificity.
Here is the guilty try-catch:
https://github.com/aws/aws-sdk-java/blob/master/src/main/java/com/amazonaws/services/s3/transfer/internal/UploadMonitor.java#L145
Here is a screenshot showing that an AmazonS3Exception is correctly thrown with the right info...
javaw.exe crashes when the communication between client and server is going on.
It does not show any pattern as it crashes anytime,and many times it does not crashes at all.
Use java.exe instead of javaw to get a windows trace at least. And use exceptions purposefully. Don't let any catch clause empty, you could even use a UncaughtExceptionHandler to know where things break.
Don't panic, Java is a very robust language.
I've released my second game project on the Android Market this week, and immediately had multiple 1-star reports due to force closes. I tested it on many handsets and many emulators with zero issues. I'm completely at a loss for how to proceed and looking for advice.
I use Thread.setDefaultUncaughtExceptionHandler to intercept and report uncaught exceptions, then close gracefully. The people reporting force closes aren't getting to any of that, even though it is the first thing set in the application's main task constructor, and everything is wrapped in try/catches throughout. They are also reporting that there is no "Send Report" option in the force close popup (providing the Developer Console error reports), so I have absolutely no way of knowing what the problem is.
Uses Android 2.0, with android:minSdkVersion="5". Only Permission required is INTERNET.
(on Android market as 'Fortunes of War FREE' if you want to test)
I'm a bit surprised about the missing "Send report" button. What API level did you build the game with? I usually build the level with your minimum API level to make sure you're not using any API calls beyond that, but then switch back to the highest API level so you can use functionality like "install to SD".
I'm sure there's at least one user who wrote you a mail. Can you ask them to install LogCollector and mail you the log?
Btw, in general, I wouldn't use Thread.setDefaultUncaughtExceptionHandler so there IS the option to send a report. (It's ominously missing in your case, but normally, it should be there.)
Btw btw, the exception handler applies to the current thread. If you have an OpenGL app, maybe the crash happens in the GL thread?
I'm not sure if I understood you correctly, but as far as I know Android only shows that report dialog if you use its default UncaughtExceptionHandler.
Try this:
In your UncaughtExceptionHander's constructor, call Thread.getDefaultUncaughtExceptionHandler and save the returned object in a variable (let's call it defaultHandler). In your Handler's uncaughtException() do the things you want to do, and then call defaultHandler.uncaughtException() afterwards.
Maybe something you should know:
In my experience, your Context isn't functional anymore at uncaughtException(). So, you can't send broadcasts, etc anymore.
By the way, if you really wrapped everything in try/catch, that could be the reason why error reporting doesn't work as expected? :P
Good luck
Tom
Perhaps the force closes are caused by stalls, rather than exceptions. Users may not notice the difference. This kind of problem can occur more often if users have CPU hogging services running at the same time as your application, which explains why you're not seeing the issue in your testing.
Permission Internet sounds a lot like you try to transfer data from the net, which is very fast in your local LAN, but all of a sudden becomes slow (and time consuming) when people try this over their GSM connections.
If you then do the data transfer in the UI thread, this one is blocked and the system detects the block - but then this should end up in a "Did not respond" -- but then I've seen one user report an error with in the market on my app that was such a slow down cause.