Robotium Solo - wait for broadcast - android

I want to create a condition to wait for a broadcast upon a button press
right now I am just doing solo.sleep(10000)
but I dont want to sleep solo for nothing
How do I formulate the condition "broadcast received" ?
Ok explanations
Robotium Solo is an instrumentation framework with nice api
It has a method called "solo.waitForCondition(Condition, int timeout)"
I want to formulate (the word formulate means say what i want to say in correct words)
the correct condition that will tell me that the broadcast was indeed received
I want to write some code (I don't know which exactly) to know that the broadcast was indeed sent
for example, if i want to know that a button is now visible i would write
solo.waitForCondition(new Condition(){
public boolean isSatisfied(){
Button b = getActivity().findViewById(R.id.myButton);
return b.getVisibility() == View.VISIBLE;
}
}
now back to my question - What (not how, but what) do I write in order to know for sure that the broadcast was sent inside the isSatisfied method

I suppose you meant that you don't want to sleep for 10 seconds, if you get the broadcast earlier. What you can do is
long beginTime = new Date().getTime();
while (new Date().getTime() - beginTime < 10000) {
solo.sleep(500);
if (conditionMet) {
// Do something
break;
}
}
This way you can do these checks on smaller intervals.
Ok, so in fact this is more or less how waitForCondition is implemented. Unfortunately I don't think you can listen for events with robotium. What you can do is monitor the view hierarchy. In your case, there should be some difference to the views that is triggered when the button is clicked, so that is what you need to check for in the Condition (and your example does that).
This is if you don't want to edit the code you are testing. If you are willing to change the code, you can add an onClickListener() and in that you can set a view's Tag to a boolean for example. Later in robotium you can check for that tag for being set. This is however not good way to do it, because you are adding more code just for the sake of the tests.

Related

switching xml layout causes crash in Android

I need to write an android application like a book. I have approximately 100 images and i need to show them with back, forward and another buttons.
I tried to create an xml-layout for each image and made images to layout's background.
While running application, if i press buttons fast, program crashes during switching xml-layout.. If i decrease image sizes my problem decreases also. Unfortunately, i need another solution in order to solve it because i cannot use smaller image-size but i have crash problem still.
Have one layout, with an ImageView in it. Then keep changing the source image for the image view whenever you need to cycle to the next or previous image.
Part of the problem is that clicking a UI button returns immediately / queues clicks, even though the action associated with that click has not yet completed. For reasons beyond the scope of this response, its worth noting that simply deactivating the button while "doing work" is ineffective. There are a couple solutions to this kind of problem: One is to use a boolean flag that gets set only after the underlying "work" has completed. Then within the button action handler, you ignore button clicks that occur before the flag is reset:
/**
* Button presses are ignored unless idle.
*/
private void onMyButtonClicked() {
if(idle) {
doWork();
}
}
/**
* Does some work and then restores idle state when finished.
*/
private void doWork() {
idle = false;
// maybe you spin off a worker thread or something else.
// the important thing is that either in that thread's run() or maybe just in the body of
// this doWork() method, you:
idle = true;
}
Another generic option is to filter using time; ie. you set a limit where the max frequency of button presses is 1hz:
/**
* Determines whether or not a button press should be acted upon. Note that this method
* can be used within any interactive widget's onAction method, not just buttons. This kind of
* filtering is necessary due to the way that Android caches button clicks before processing them.
* See http://code.google.com/p/android/issues/detail?id=20073
* #param timestamp timestamp of the button press in question
* #return True if the timing of this button press falls within the specified threshold
*/
public static synchronized boolean validateButtonPress(long timestamp) {
long delta = timestamp - lastButtonPress;
lastButtonPress = timestamp;
return delta > BUTTON_PRESS_THRESHOLD_MS;
}
Then you'd do something like this:
private void onMyButtonClicked() {
if(validateButtonPress(System.currentTimeMillis())) {
doWork();
}
}
This last solution is admittedly non deterministic, but if you consider that users almost never intentionally click button more than 1-2 times a second on a mobile device, its not so bad.

Android - Getting volume button long clicks

Can someone please show me a code example about how to get a long click (2 sec for example) on the volume up hardware key?
Thanks :)
EDIT
The class that i want to capture the long click with is a Service. How can i do that?
If you just need to capture long clicks, this answer might be helpful:
https://stackoverflow.com/a/5269673/1401257
EDIT:
I have never tried to have a key listener inside a service, but with a little help from Google I found this: Volume change listener?
It seems that normal key events can only be handled from Activities. I do not have time to try this out myself, but for capturing long clicks it might be possible to combine the answer from the link and Lukes answer.
From what I understand about BroadcastReceivers, you would want to create a receiver, that notify the Service whenever someone click the volume buttons.
Optionally you could do something like this:
if(clickedDown) {
if(beginningTime + 2000 < System.currentTimeMillis()) {
// Ok, the button has been clicked down for 2 seconds
}
}
else {
beginningTime = System.currentTimeMillis();
}
Applying something like this, you'll be able to define the amount of time to wait.

Android - Get EditText and show dialog

I want my application can get user's input of time (HH:mm) from EditText widget.
Based on this time value my app needs to show a dialog when current time matches entered time.
Gaauwe
*Edit*
I want to place an EditText widget in my app.
A user will fill it with some time value (e.g. 10:30).
Then when real time (10:30) come up a dialog will be shown.
I think you can use the AlarmManager for this.
I d suggest you have a look at some tutorials like these to help you get started
http://michael.theirwinfamily.net/articles/android/android-creating-alarm-alarmmanager
http://android.arnodenhond.com/tutorials/alarm-notification
That is not too difficult. When user finished editing you EditText, read the time value and create instance of AlarmManager with start time calculated as difference between current time and whatever user wrote in the EditText. Better to use TimePicker to avoid parsing user`s input. Add receiver for you AlarmManager, receiver will start Service which will show dialog or do anything you want. You need to use AlarmManager because if your device is sleeping nothing will wake it up except system call like AlarmManager. #Zortkun 's post with links will help you to figure out how manage AlarmManager.
try this :
use the service : then when user enter time starts a service when system time and user entered time match the shows..
You can pull the data out of the EditText with:
findViewById(R.id.yourEditText).getText().toString();
The rest of your question I didn't understand.
RAW WAY!
So when user put text inside edittext and click button, you could save text in this way:
String time = findViewById(R.id.yourEditText).getText().toString();
and start a thread that check for time, and when time is equal to user's string time, you can show a dialog :)
Thread t = new Thread(new Runnable(){
public void run(){
while(new Date().getLocalTime()!=usersTime){ // is just pseudocode
Dialog.show();
}
}
});
I'll try to understand...
Seeing as you know how to pull the text from an EditText, you'll need an if statement.
Something that compares that time to the current time.
if (editTime == realTime) {
Toast.makeText(getApplicationContext(), "RING RING RING",
Toast.LENGTH_SHORT).show();
}
Use something like this:
Read this to figure out how to get a string of current time.

Measure time for rendering ListView

How can I measure time that ListView/ListActivity takes for rendering its list?
I have a ListActivity that takes a long time to show (on older devices it's ~3s) and I'd like to optimize that.
EDIT:
I already have time between Activity1 and Activity2. During this time, Activity2 is doing some stuff (initializing). Among other things, it renders its list. I want to get time this activity takes to render that list. If total time between activities is 3s, I want to know whether rendering list takes 2.9s or 0.5s....
You could simply ouput the time. For example you could use the logcat
final long t0 = System.currentTimeMillis();
// code to measure
Log.w(TAG, "TEXT" + System.currentTimeMillis()-t0);
Of course you could use any other system for the ouput like a dialog or stuff. Just use what you like.
EDIT:
If you don't want to use a debug message in your code all the time you could do it like this:
Create a class called settings:
public class Settings {
public static final boolean DEBUG = true;
// If you prefer you could do use an enum
// enum debugLevel {SHOW_EVERYMESSAGE, ERRORS, IMPORTANT_MESSAGES, ...}
// In your classes you would have to check that DEBUG is less or equal than
// the debugLevel you want
}
In classes where you want to use a debug message simply do this
import xxx.yyy.Settings
class foo {
final static boolean DEBUG = Settings.DEBUG;
if(DEBUG){
// Debug messages
}
}
Now if you want to disable DEBUG messages you could simply set DEBUG = false in your Settings class.
If you want to measure between two activities you could use intents and send t0 with an intent to the other activity to compute the time. Of course you could include this with if(DEBUG){ /* code */ } statements to spare the sending of the intent in the final release. The if statements should not increase the computation of your code too dramatically.
I cannot tell if Java offers a better implementation using System.currentTimeMillis() or System.nanoTime(). Nevertheless, you should give the TimingLogger class a try. Take a look at this article describing the usage of the TimingLogger helper class.

"realtime" search using AsyncTask?

I am writing an application that searches a database in "realtime".
i.e. as the user presses letters it updates a search results list.
Since the search can take a while, I need to do the search in background and allow new key presses to re-start a search. So that is a user presses 'a' (and the code starts searching for "a"), then presses 'b' - the code will NOT wait for "a" search to end, then start searching for "ab", but rather STOP the "a" search, and start a new "ab" search.
To do that I decided to do the search in an AsyncTask. Is this a wise decision ?
Now - whenever a keypress is detected, I test to see if I have an AsyncTask running. If I do - I signal it (using a boolean within the AsyncTask) it should stop. Then set a timer to re-test the AsyncTask within 10 mSec, to see if it terminated, and start the new search.
Is this a smart method ? Or is there another approach you would take ?
TIA
First yes, AsyncTask is a good way to do this. The problem I see with your approach is the timer waiting to watch something die. When you invoke the asyncTask hold onto a reference of it. Let it keep state for you so you know if it's out searching or it's has returned. When the user clicks another letter you can tell that asyncTask to cancel. Something like this:
public void onClick() {
if( searchTask != null ) {
searchTask.cancel();
}
searchTask = new SearchTask( MyActivity.this ).execute( textInput.getText() );
}
public class SearchTask extends AsyncTask<String,Integer,List<SearchResult>> {
private boolean canceled = false;
protected onPostExecute( List<SearchResult> results ) {
if( !canceled ) {
activity.handleResults( results );
}
}
public void cancel() {
canceled = true;
}
}
This is safe because onPostExecute() is on the UI thread. And cancel() is only called from the UI thread so there is no thread safety issues, and no need to synchronize. You don't have to watch a thread die. Just let the GC handle cleaning up. Once you drop the reference to the AsyncTask it will just get cleaned up. If your AsyncTask blocks that's ok because it only hangs up the background thread, and when the timeout hits it will resume by calling onPostExecute(). This also keeps your resources to a minimum without using a Timer.
Things to consider about this approach. Sending a new request everytime a new letter is typed can overload your servers because the first few letters are going to produce the largest search results. Either limit the number of results you'll return from the server (say 10-50 results max), or wait until they've entered enough characters to keep results down (say 3). The cons of making the user type more characters is the feedback doesn't kick in until 3 chars. However, the pro is it will dramatically reduce the hits on your server.

Categories

Resources