I know that the following is against all Android best practices... So please be kind with me :-)
We have a big legacy software that is not easy to be transformed. The app does do way to much things on the UI Thread. So, under certain circumstances, it comes from time to time that Android considers our app is in deadlock state. So it prompts the user with an ANR ( Application not responding -> Wait, or Close ?)
Our users know that our software is bad architected on some parts and so the click Wait...
On Android 7 to 12 it was the case that the ANR then clears itself. The mainThread is responsive again and so the app is working.
But on Android 13 this is not the case. The mainThread is responsive again, the app can be used in a normal way, but the ANR message comes back every 5seconds.
In a simple Kotlin app this can be tried out with minimal effort.
Create an activity with two buttons and a label
First button increases a counter and refreshes the label
Second button has a sleep that is longer as 5 seconds ( make it 12 seconds, so you are 100% in the issue case )
If first the Sleep button is pressed and then the increase button multiple times,the app freezes in the first place and when the sleep time is over the label gets refreshed the number of times we pressed.
Then after 5seconds the ANR message comes.... Click wait.... ANR comes again.... Over and over again....
Sounds like an issue in Android 13 for us..
Is there a nifty way to clear the message queue of the main thread so Android does not try to deliver the message over and over again ?
Thanks for your help...
Related
I'd like to know the code or configuration needed to set that.
In my app, there are some places where I'm willingly make the app to sleep for several seconds, as it's needed for some reasons, with a Thread.sleep(long millis) function.
Problem is that on some Android APIS, at least on 25 and 26, usually that system message pops up in few seconds, confusing the user and maybe even causing the application not to fulfill the needed operations that need to happen while that sleep is happening if the user ends the app, which might cause even malfunctioning of the application.
I'd like to find a way of either forcing Android to wait for a good time like, for example, 1 minute, or to make Android aware that it's not that app isn't responding, that is willingly on a Thread.sleep function.
Is there any way to do that?
I'd like to find a way of either forcing Android to wait for a good time like, for example, 1 minute, or to make Android aware that it's not that app isn't responding, that is willingly on a Thread.sleep function.
TL;DR there is none.
Android apps should at all times be able to yield their position in the foreground to other apps. It's up to the users if they want to wait while some lengthy download is taking place or if they prefer to do something else and come back later.
You can't execute Thread.sleep() on the UI thread for long because this would "freeze the UI".
An example: Users should be able to leave your app by pressing the BACK Button at any time they wish to. If your method is blocking the UI thread, Activity#onBackPressed() can't be executed so the users can't quit.
What can you do? Move the heavy work to another thread (using e.g. AsyncTask or IntentService or some plain worker thread) and show some type of progress indicator to the users if necessary. You can/ should also toggle visibility or enabled state of Buttons etc. if required to avoid clicks which can't be processed at that point in time.
I think you have an implementation problem. The system message, known as ANR (Application Not Responding) occurs when the application cannot respond to user inputs, this may be caused by Ui thread blocking and that may be your case.
To avoid blocking the UI Thread just run your long time operations asynchronously. There are many ways to do that. You could use AsyncTask, AsyncTaskLoader, Thread, RxJava... Here you have some links to help you with that:
https://developer.android.com/training/articles/perf-anr
https://google-developer-training.gitbooks.io/android-developer-fundamentals-course-concepts/content/en/Unit%203/71c_asynctask_and_asynctaskloader_md.html
http://www.vogella.com/tutorials/RxJava/article.html
I am working on an Android app that displays a continuous custom-rendered animation on the title screen and thus doesn't really enter the idle state when it's done loading. On most devices I've tested, everything runs fine, but Samsung's Galaxy S2 kills the app after a few seconds. I don't get a stack trace or any output of the System.out output that I put into the onPause event handler and the default uncaught exception handler, so it doesn't seem to be a normal exit or an Exception in my code.
The only output I get in LogCat is the following:
Launch timeout has expired, giving up wake lock!
Sending signal. PID: 22344 SIG: 3
handleActivityTimeout pid=[22344] cnt=10
Process ... (pid 22344) has died.
There are several related posts here on SO (1, 2, 3, 4), but they all seem to trigger the issue slightly differently (alarm, recursive loops, network requests in the UI thread, ...). The last one links to a Google Groups discussion that says that this error message can simply be ignored. An approach I'd rather not take since it causes my app to actually crash on the Galaxy S2 (and maybe others?).
Basically what I did was to write a custom View that renders the next animation-frame in its onDraw() method and then calls postInvalidate() right before returning from onDraw(). In case it matters: My first postInvalidate() call happens during onCreate(...).
The rendering is very quick and runs at 40+ frames per second on that device and well over 60 fps on more modern phones. So control goes back to the event loop very frequently and the app is also very responsive. Yet, the Galaxy seems to think that it has crashed and kills it (if that is even the reason for my app dying there). The thing is: If I am quick enough to click on a menu-item in my app to end up on a screen without an animation to break out of the "tail-recursive" postInvalidate() once, everything runs fine. Even if I then go back to the title screen for a long time where the animation runs again.
So, of course, I could probably just use postInvalidateDelayed(...) once to break out of the start-up check, but that seems like a bit of a hacky solution and I don't know if there might be any other devices out there that might consider my app dead at a later stage (not just during start-up) and kill it.
Is there something fundamentally wrong with using postInvalidate() in the way I'm doing? Is there a way to fix it? I would like to avoid having to move to a separate thread since that opens a whole other can of worms as far as passing events back and forth between the UI and that thread. I know it wouldn't be the end of the world and using a SurfaceView, it might even lead to a slight performance improvement, but it's really just not necessary from a user experience point of view (everything runs perfectly smooth), so I'd like to avoid the involved additional opportunities for issues (multi-threading is notoriously difficult to debug).
I do have a more general question, without any specific code. I will explain what my application does and how and what issues I can monitor. Maybe one of you had the same issues and can lead me to the problem.
The App:
It reads car diagnostic data (OnBoardDiagnostics) over Bluetooth and shows them in real-time in a ListView. I can start the update function by a "update Button".
How:
Everytime a new value is received via Bluetooth, a background Class (which handles the Stringforming) sends an Intentto notify the UI to update the ListView.
The Adapter Class of my ListView has the listening BroadcastReceiver registered and if it gets triggered, it will notify the ListView by notifyDataSetChanged().
Issues:
1.If I use an WakeLock to keep the screen on, the UI refreshing slows down after approx. 10 minutes.
2.If I press the power button, so the screen is off, it still slows down (I can see that, because I send the values to an webserver) but furthermore: If I turn the screen back on. I see the ListView stops for about 20-30 seconds and than normally continues with normal speed (not slow anymore).
So.. I think this is a very general question. I searched for WakeLock and sleep behaviour, but I couldn't find any similar issues. Maybe one of you can give me a hint, what the problem could be. Maybe one of you had a similar problem.
Any hint is appreciated!
EDIT 1:
Maybe the problem of the 2. issue is based on the lifecycles of my objects / activity.
If I press the update Button, an AsyncTask is started, which sends the Data (JSON, which contains one new value for all list items) to my Webserver. If the device screen is off, I still get the data every 2 seconds. If I turn on the screen, it stops for these 20-30 seconds as well as the UI. So I think my UI works fine. The Update Intents were sent right.
I have to check if I still receive new values in that background class, mentioned above.
Thanks to zapl
Thanks!
Except all possibilities I checked, i came across this article:
AsyncTasks for long running Operations
Short: There are some points you need to keep in mind if you are using AsyncTasks in very long running operations (>20min). My Problem was, that I used the AsyncTask as an inner Class. After a long period, when the Activity that created the Task was destroyed, the AsyncTask still kept a reference of this activity.
After I used a Bus, described in the article above, the UI worked fine!!
So, if anyone else noticed performance problems of your App, I recommend that article.
Thanks for all the other hints!
Have fun coding!
I would like to know whether it is a good practice to write for loop that loops around 400-500 times inside android main thread or should i go for an another thread. Thanks in advance.
Since you say the loop is processing several hundred coordinates, it should definitely be an AsyncTask or a background thread. Even if the user cannot interact with the UI in that period, this will allow you to show a spinner or dialog for that duration. Further, if the UI thread is unresponsive for more than a certain amount of time, the OS considers the app to have crashed, and gives the user the 'This app has stopped responding' dialog box.
I recently began writing a phonegap android application and noticed that when the app is resumed from the background (so I deploy the app to an android tablet, press the home button and then reopen the app from the menu) it gives a timeout error (something to the effect of Error code =-6 The connection to the server was unsuccessful) and then crashes. From what I've tested this only seems to happen when the "Don't keep activities" option is checked in the developer options, when that option is not checked the app works as intended.
It's also worth noting that I recreated the default phonegap application, ran it and encountered the same issue.
Can anyone explain why this happens, or suggest a solution? Obviously I can get around this problem by simply leaving the Don't keep activities option unchecked, but I'm guessing the problem will persist on any android device that has this option checked, which just won't do.
I'm using phonegap 2.5.0 and testing on a device running Android 4.0.3,
Thanks,
Josh
"Don't keep activities" is a developer tool to simulate user activity that would be extremely hard to test for. I personally believe all apps should be tested a second time (at least run automated tests) with this setting turned on, and devs should turn it on / off during development.
Your issue (which I've just ran into on v2.7) comes from a silly implementation of a timeout feature. CordovaWebView.loadUrlIntoView creates and locks (wait()) a thread for 20 seconds (default value), after which time it checks a value to see if the url finished loading - if it hasn't finished, it shows an error message.
This thread exists outside of the lifetime of your activity, so if the activity stops running, the Webview can never finish loading the url, and when the thread wakes up, it does Bad Things trying to show the error.
The same crash could happen without using "Don't keep activities" by simply having the user leave the application and then the system reclaiming the activity's resources (because it is low on memory or something) within 20 seconds.
Using a Handler seems like a more appropriate way to handle this timeout, but without changing the source there are a couple of hacky work arounds.
Call System.exit(0) at the end of your Activity.onDestroy() - this is horrible, but if you only have the one activity and no services, it might be an option
Use reflection to change CordovaWebView.loadUrlTimeout - this is horrible, but it should work, this is the value that the thread checks to see if the url loaded (inc by 1).