Espresso tests failing due to repainting the screen by Android Camera Intent - android

I am having an activity which has camera, and having a mask over the camera which is done by onDraw() method, I was writing test cases for the navigation drawer which is above the camera screen, but getting error as
Perhaps the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen. Or the activity is doing network calls on creation? See the threaddump logs. For your reference the last time the event queue was idle before your activity launch request was 1472804618974 and now the last time the queue went idle was: 1472804618974. If these numbers are the same your activity might be hogging the event queue
I have already turned off the animation as already mentioned over
https://google.github.io/android-testing-support-library/docs/espresso/setup/index.html
Don't know what needs to be done.

I have already turned off the animation as already mentioned over
https://google.github.io/android-testing-support-library/docs/espresso/setup/index.html
This problem occurs not because of turned of animations, but because of Espresso framework character: Espresso depends on your actual application context.
Espresso for Android is perfect and fast test automation framework,
but it has one important limitation - you are allowed to operate only
inside your app under test context.
That means that it is not possible to automate tests for such app
features like:
application push notifications
contact synchronization
navigating from another app to your app under test,
since you have to deal with other apps from the mobile device -
Notification Bar, Contacts or People app, etc.
From: http://qathread.blogspot.com/2015/05/espresso-uiautomator-perfect-tandem.html
It means that Espresso tests are based on UI thread and waiting when the main thread is idle().
Perhaps the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen. Or the activity is doing network calls on creation? See the threaddump logs. For your reference the last time the event queue was idle before your activity launch request was 1472804618974 and now the last time the queue went idle was: 1472804618974. If these numbers are the same your activity might be hogging the event queue.
This means that your main thread is actually busy and Espresso can't perform any new actions, it's waiting for free idling resources to run.
To solve this problem you have these options:
write your own custom Espresso IdlingResource to say Espresso when he can perform action, in other words: IdlingResource tells Espresso when the main thread is idle and ready to take a new actions.
exclude appcompat and support-v4 from espresso libs : https://github.com/googlesamples/android-testing/issues/56
I suppose that you're running Camera using an Android Intent, so it isn't included in your actual app context, it's not displayed on your apps activity/fragment. If it is true, try to use UiAutomator along with Espresso framework. Read: http://qathread.blogspot.com/2015/05/espresso-uiautomator-perfect-tandem.html
instead of Espresso try to use Robotium, Appium or another instrumentation framework without this limitation.
Already, I'm using along Espresso, Robotium and UiAutomator, so don't be afraid to work with mix of them.
Hope it help

So i was able to solve my issue.
The problem was occurring due to continuous calling method invalidate() from onDraw().
Instead i replaced it with postInvalidateDelayed(), and for certain conditions(like animations) only used invalidate().
It helped! :)
Avoid continuous repainting screen.

Related

Why Robo tests gets marked as passed so quickly?

TL;DR
The app has tons of flows, but sometimes runs get passed faster than 2 mins...
Is there any way to keep it running until the timeout period (e.g. 1hr) is almost consumed? Attached a screenshot for a quick termination e.g.
Although the app is very big with tons of flows, sometimes runs get passed after 2min, 5mins but what is the critieria which decides that the running robo test should terminate now with a passed result? any idea what makes the recorded graph decides to go to this node? n.b. I assumed it's the terminal node
Why Robo tests get marked as passed so quickly?
It turns out that due to having a varying b.e. responses, the app journey gets changed. If there're 3 disconnected components (as in gif), what happens is sth like the app can start in any of the 3 flows resembling the 3 components. Which implies how long the journey will be
Is there any way to keep it running until the timeout period (e.g. 1hr) is almost consumed
Guiding the robo tests as explained here is a promising way to let journey bigger by following some sequence of actions which make the graph bigger
What is the criteria which decides that the running robo test should terminate now with a passed result?
Robo tests are simply applying flood fill on the app (as in gif). Where the graph nodes are represented by screens, e.g. onboarding screen, and edges are represented by actions, e.g. click on next button
Most likely it is always more or less the same time duration ...while the only difference may be the test's position in the queue (you're not the only user there, which is why it may appear as if the duration would vary). And that TerminatedActivity-33 only confirms that the Activity under test had been successfully terminated ...which is "The End" of the story.
For reasons of efficiency, the test will terminate as soon as possible - the timeout value can only be reached when it's stuck.
That the queue may also run in parallel might be another possible cause; while then, even if the real-time duration would indeed vary, the processing time (CPU shares) would still be about the same. Disclaimer: I have no clue how it internally works, just tried to apply some common sense.

Can you indicate to Android the time to wait or tell it that the app is still "active" before displaying "App isn't responding? If so, how?

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

Espresso UI tests running when I execute single test, but fails when I execute set of tests

I'm using IdlingResource to synchronize a few network related tasks. I register and unregister idlingresource in the #Before and #After methods. The instrumentation is AndroidJUnitRunner.
The basic sequence of steps are:
Espresso clicks a button which makes a network request
When I get response, espresso clicks another button which starts a new activity.
Make more network requests via the new activity.
What actually happens though, is that the first network request is made but new activity is not started. I have a feeling that the main thread is looping somewhere, but I can't pinpoint it.
When I execute a single test (right click method, click on "Run testmethod..") it works, but when I try to execute all the test methods in the class, it fails.
The cool thing is even if every method is empty, save for one which actually does the UI testing, it still fails.
A similar question is in this thread, but has no answers: Espresso 2 on Android, intermediately tests fail after failing to start the activity under test while activities from previous tests are still alive
Any help will be appreciated.

Starting singleTask activity every few seconds gives ANR in Android

In the app I have an activity which has launch mode as singleTask. There are number of use cases which pass through this activity and hence it's called number of times. On stress testing the app by running monkeyrunner script and calling this activity every few seconds causes ANR's.
I guess, the way it's designed where most of the use cases pass through this activity is not correct but I am not in a position to change this design.
Is there anyway ANR's can be suppressed? I mean, adding UI operations to event queue so that it doesn't block main UI thread and doesn't give ANR.
It is unclear from the question what your activity is (or should be) doing. Probably you need a service instead.
It is common to perform time-consuming operations in background threads and deliver the results to the UI thread.
You may use the classes Handler/Looper (it it easir to send Runnables rather than messages), or use an AsyncTask. The AsyncTask is nevertheless tricky, this is discussed here: Is AsyncTask really conceptually flawed or am I just missing something? . AFAIK Google tried to fix the typical bugs and made the new behavior incompatible with the old one (namely, I have seen some misbehavior on the newer Androids that may be explained by the assumption that since some version threads doing asynctask jobs get killed after the activity that started them goes out of the screen).
I can guess that singleTask is your way to fight the fact that an activity dies when the screen turns, and a new one comes. I suggest you use singletons (they survive screen rotation but do not survive a process restart, one more thing that sometimes happens in Android). (The user switches to an app like Camera, takes a big photo, returns back -- and the activity is restarted because Camera needed memory. Have seen this in practice, but that time I did not try to find out if the whole process was restarted.)
Anyway, please add logging telling you when your activity in entered and left, including onNewIntent() and other lifecycle functions (to be on the safe side, I recommend to print the thread names as well). Then you will probably see what is going on.

android design considerations: AsyncTask vs Service (IntentService?)

I'm designing an android app which will need to do the following steps:
user pushes a button or otherwise indicates to "sync data".
sync process will use REST web services to move data to and from the server.
the data will be stored locally in a sqlite database.
the sync process should provide status updates/messages to the UI
the user should not be allowed to wander off to other parts of the application and do more work during the sync process.
The first time the sync process runs, it may take 10-20 minutes.
After the initial sync, less data will be transferred and stored and
I expect the process to take 1-2 minutes or less.
I've been doing a lot of reading about android's AsyncTask and various examples of using a Service ... But I don't fully understand the design considerations and trade-offs of choosing one design over the other. I currently have my demo project stubbed out using an AsyncTask. After watching (most of) Developing Android REST client applications: http://code.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html# I'm left confused the design patterns described here feel overly
complex, perhaps because I just "don't get it" yet.
I come from a java, spring, web and desktop application background. Thinking and designing in terms of a handheld device is quite new to me. (What happens when the screen layout is changed? What happens when the phone rings while I'm running a sync?) Taking 2 steps back, if the initial sync IS going to be such a long running process, is there a better way for me to think about the problem->solution, the user experience, the user expectations of an application running on a phone?
Would love to hear from some more experienced android developers out there who have already wrestled with these questions.
In my opinion this is the most tricky/hard part of a mainstream/average Android development. For instance on BlackBerry this is IN TIMES easier.
Definitely you need to use a Service.
AsyncTask does not suit, because it is tightly "bound" to your Activity via a Context handle (otherwise you would not be able to update UI of the Activity from your AsyncTask). However an Activity can be killed by OS once the Activity went in background. An example reason of going to background can be an incoming call - user switches to Phone application so your Activity becomes invisible. In this case (depending on the current RAM state) OS may decide to kill one of the background (invisible to the user) activities.
Some devs workaround this by arranging a static stuff for having a long-running actions inside of. Some recommend to use Application instance. This is because static stuff and Application exist while the whole app process exists. However those are incorrect workarounds. Processes in Android are also may be killed when OS decides it is time to. Android OS have its own considerations about what it can kill and in what order. All processes are devided to 5 levels of "killability". Here is the doc where those levels are specified. It is interesting to read there:
Because a process running a service is
ranked higher than one with background
activities, an activity that initiates
a long-running operation might do well
to start a service for that operation,
rather than simply spawn a thread —
particularly if the operation will
likely outlast the activity. Examples
of this are playing music in the
background and uploading a picture
taken by the camera to a web site.
Using a service guarantees that the
operation will have at least "service
process" priority, regardless of what
happens to the activity.
Your Activity where users initiate a long-running action should show a ProgressDialog to make sure user does not do anything else while the action is running. The guide is here.
Also, you'd most likely want to use the NotificationManager for notifying the user about your long-running action completion (or failure) if your Activity is currently invisible. Here is the NotificationManager info to start from.
There are multiple considerations that you must weigh in order to best decide how to approach your situation. It sounds like you need a good comparison between the two approaches... So here is a list of similarities, and differences and additional considerations that must be taken into account when working on a handheld device.
A Service is a part of your Application that has no UI. It may be called by a UI(Activity) to be started, or may be started by any other component of your Application. When developing, you have the freedom to place it on a different thread, or even run it in a different Task or Process. This allows you to ultimately separate it from your UI. Additionally, you may start the Service to run independently (startService) or bind your activity to it (bindService) depending upon your needs. By using custom Handlers, you can set callbacks to update the UI with your progress. A Service does not necessarily end if a User changes Activities, but may be ended at ANY time by the OS.
A AsyncTask is always instantiated from the UI thread. It only allows specific callbacks, but simplifies the process of multi-threading for the purposes of relatively short transactions (as compared to dedicated separate threaded services) that are inherently tied to actions performed by an Activity. Whenever a User changes Activities, the AsyncTask is put on "pause" and may even die because there is no UI thread for your Activity any longer.
The thing that I would be most concerned about is if the app is going to take 10-20 minutes the first time, I would ASSUME that the User will either change tasks temporarily or set the phone down until it completes (which can cause all of the same complications if the phone sleeps). Given this consideration, a threaded service bound to your activity may be your best choice. To protect your UI, I would make a Progress Dialog for your Activity that receives your progress callbacks. This limits user input in YOUR app and allows your service to continue the way that it needs to. Then override the Activity onResume to check the status of your Service and if it is running. Then you can reset the Dialog immediately.
Given that this is my preferred method, I would also take into account that the OS may kill the App at any time anyway. So make sure to have some way to detect an incomplete or partial sync. Then you may resume automatically when your Activity or Service restarts.
With AsyncTask if the user goes to another Activity you can't transfer that object to the other Activity so it dies. There are tricks you can play when say the user rotates the screen or something like that, but that doesn't extend to general purpose destruction. AsyncTask can randomly die.
Google Sync is run as a Service in the background because syncing can take a while to complete. You might need to follow their path and create your own sync service that you can communicate with. Here is some thoughts how to accomplish that:
http://mylifewithandroid.blogspot.com/2008/01/about-binders.html
You can definitely communicate between Service and Activity, but it's tricky to do it right.
The choice is mainly dependent on the app design. Since both AsyncTask and IntentService stands their ground, what you may want from the app(user experience) is more important and then choose either or both. Some scenarios are mentioned below (mostly what I experienced while developing apps)
Assume apps that have feeds pages - where more than one api calls are made to make the page presentable ( /getFriends, /getDates, /getPictures etc.) you can warp all such api calls to a single AsyncTask with executor which is multithreaded and the sequence of execution doesn't matter. In contrast to IntentService which runs all calls in sequence in a single worker thread. For a high end device with multi-core the call from AsyncTask is more effective. And if you start the AsyncTask on UI thread then updating IU is a piece of cakes(read less boiler plate code). And even if an user leaves the page, with intelligent use of not holding on to the context the app doesn't crash.
Assuming you are trying to write an app which doesn't need the user to be on view/activity/fragment and the total execution time to show something is not mission critical (assume sync service or user notification/alarm) then IntentService is a better choice. (no hassle to start Asynctask on UI thread so that you don't need to write a Handler to force changes on UI etc. etc. and less boiler plate code)
From my experience - write small app for both and compare the pros and cons to get a better idea. (p.s I'd suggest take a look at the iosched app from google to get a better idea - they use both Asynctask and IntentService)
I tend to prefer the IntentService + BroadcastReceiver combo because they give you a really strong degree of control
You definitely have to make sure the UI is running if you are updating something on the screen. ASyncTask crashes were at once reported to be one of the top causes of Android crashes. This can be avoided by keeping some sort of "activityIsAlive" variable and skipping or delaying a UI update if the activity is dead.
The IntentService + BroadcastReceiver combo is a little more resistant to the crash because most tutorials tell you to shut off the BroadcastReceiver onPause or onStop. If you do not do this, again you'll have to turn off the UI update. There's a runOnUiThread command somewhere that will help you do UI updates.
The IntentService + BroadcastReceiver combo is also more extensible. You can create functions and extend BroadcastReceiver to make a more elegant REST processing solution. However, it does require more plumbing vs an ASyncTask
If you do delay the UI update, you may be able to rig it on OnWindowFocusChangedListener. When that function receives true, it means that the UI is alive.
tldr; Make sure the Activity and/or Fragment is alive before updating the UI if you are running something in the background
2015 Edit: check out Loaders as well. A little harder to grasp because there's a lot going on behind the scenes

Categories

Resources