Wondering if there is any way to build and fire an event (e.g. on click event) in android applications programmatically.
Thanks.
sorry, it seems question is not clear enough, let me explain a bit more:
I have an Activity (lets call it A) with multiple views (5 ImageView for example).
And a normal Java class (lets call it B) which is used by my Activity.
There is an instance of B in my Activity.
If user click on a View (Image View) the view OnClickListener calls a method in B
In B, if operation is successful, it will call back a method in activity again.
in activity method, It will change image or state for clicked ImageView.
in the other hand:
click on view (x) in Activity -------> B.doSomething() --------> A.bIsDone() -----> change image for view (x)
with normal execution, its working and there is no problem.
the problem is that I want to simulate this process to be automatic, my code looks like this:
while (!b.isFinished()) {
try {
b.doSomething(<for View x>);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The issue is that, it won't render anything, until the end of the loop.
I tried to put the loop in another Thread, but its throwing exception:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
what can i do for this issue? i was think generate an click event on view (by code), to see it can help or not.
what is your solution?
Thanks
In Your Activity B, create a Handler
Handler mHandler = new Handler();
In your doSomething() inside B update your ImageView using mHandler.post(Runnable r).
The Runnable should include code how to update UI.
The problem is likely caused because you're trying to update B Components using A Thread. I suppose you could also use runOnUiThread(Runnable r) aswell.
Original Answer before Question was edited.
dispatchKeyEvent(KeyEvent event) for Keys
dispatchTouchEvent(MotionEvent) for Touch
Refer to other dispatchXXX Functions. Google is your friend. :)
Here's a summary of dispatchKeyEvent from the docs.
public boolean dispatchKeyEvent(KeyEvent event)
Dispatch a key event to the next view on the focus path.
This path runs from the top of the view tree down to the currently focused view.
If this view has focus, it will dispatch to itself.
Otherwise it will dispatch the next node down the focus path.
This method also fires any key listeners.
If you are talking about Listeners, like OnClickListener, then yes: You can create your own listeners and trigger them.
Basically you start by defining an interface for that Listener. For a DaterTimePicker (which has a DaterPicker and TimerPicker) widget I once used
public interface OnDateTimeSetListener {
public abstract void onDateTimeSet(DatePicker datePicker, TimePicker timePicker);
}
The interface defines a single Method which has to be implemented by your listeners.
Then in your class you do something like
public class DateTimePickerDialog extends AlertDialog {
private OnDateTimeSetListener onDateTimeSetListener;
private DatePicker datePicker;
private TimePicker timePicker;
public void setOnDateTimeListener(OnDateTimeSetListener l) {
this.onDateTimeSetListener = l;
}
private onDateTimeSet() {
if(onDateTimeSetListener!=null)
onDateTimeSetListener.onDateTimeSet(this.datePicker, this.timePicker);
}
private doSomething() {
// Do your code here
// fire up the event once finished
onDateTimeSet();
}
}
setOnDateTimeListener() is used to set listeners from outside of the class (i.e. in your main activity).
onDateTimeSet is used internally (hence declared private) to fire the event and to check if onDateTimeSetListener was set or else we'd get a NullPointerException if it wasn't set. If it was set, call it's onDateTimeSet method.
And in your main Activity you simply add an listener to it and add the code you need, like:
DateTimePicker dateTimePicker = (DateTimePicker)findViewById(R.id.datetime);
dateTimePicker.setOnDateTimeListener(new OnDateTimeSetListener () {
void onDateTimeSet(DatePicker datePicker, TimePicker timePicker) {
// Date/Time was changed
Log.d("OnDateTimeSet", "Date/time was updated");
}
});
Here you set up the listener the same way you'd set up an OnClickListener.
It's quite a bit of code for a you have to do for a simple event, but as far as I know it's the right way to implement this.
I'm not sure what you mean by build and fire an event and on which context (i.e. from a View, Activity or Service) but will give it a try.
To create a key event just use the KeyEvent Contructors.
For MotionEvents you can use the static obtain method from [here][1]
If you want to fire them use the previously mentioned methods on the target Activity (which can be fetch as the context (getContext()) if inside of a View)
Hope it helps, if it doesn't please provide with more details and/or example code.
[1]: http://developer.android.com/reference/android/view/MotionEvent.html#obtain(long, long, int, float, float, int)
Related
I'm trying to create a program which will randomly and continuously display circles all over the screen that will change sizes. I've created a method that will draw circles but I'm not sure how to call it. In the past I've only done buttons which will call a method when clicked, but I don't know how to just call a method out of the blue. Is there a 'main method equivalent' in android which is automatically run?
The onCreate method of the activity showing the circles will be automatically run. From here you can start a background timer thread to randomly call the method creating the circles.
There is a main method, but you can not touch it simply. In Android , the UI thread would be the main method you want though they are not the same thing.
You can run action in UI thread like this:
public static void runInUiThread(Runnable action) {
if (Looper.myLooper() == Looper.getMainLooper()) {
action.run();
} else {
new Handler(Looper.getMainLooper()).post(action);
}
}
But according to your question ,you want to display something. It is not a google idea that draw it directly on Activity, you can create a class and extends View. The Override the onDraw method , you can put your drawing code into onDraw. This function will be called automatically when it need to be display.
Now you can put your custom view into layout and if the custom view need to be display in screen , it would.
You can create your own class enxtends View, and put the code that controlls the appearance of the circle in the mothod onDraw() which you should override.When you want to get the size of your circle changed, call invalidate().As a result, the method onDraw() is called and the appearance just changes.
I have a source code of an app for android which get location from network or gps. There is the next code:
// Callback method for the "both providers" button.
public void useCoarseFineProviders(View v) {
mUseFine = false;
mUseBoth = true;
setup();
}
There is a button, and on the onClick event call to "useCoarseFineProviders", my question is that I want to delete this button and call this method from the onCreate method, but I don't know how to do this.
I need to learn so much things. Thanks for your help.
Your code isn't actually doing anything, or using the view parameter passed in. so if you want to move it to onCreate, just do it- take the body of the function, paste it into the bottom of onCreate, then delete this function and the code (probably in your xml) telling it to call this function in onClick.
I am working on a game that involves using the accelerometer to control the character. My problem is this: I need to use the values recieved by the sensor in classes and methods that are not accessible inside OnSensorChanged(). I believe I need to implement a Callback from inside the OnSensorChanged, but I don't know how to do that. Can anyone help me out?
I believe the answer in this post (How to Define Callbacks in Android?) will help you out.
To summarize, create the callback interface:
// The callback interface
interface MyCallback {
void callbackCall(SensorEvent event);
}
Implement the call back interface in the class that is supposed to do calculations:
class Callback implements MyCallback {
void callbackCall(SensorEvent event) {
// callback code goes here
}
}
Make the call from your Activity where you have the onSensoreChanged():
// The class that takes the callback
class Worker extends Activity implements SensorEventListener {
MyCallback callback;
public void onSensorChanged(SensorEvent event) {
callback.callbackCall(event);
}
}
I hope this helps.
UPDATE:
I assume you already know about processes and threads (if not, please have a look at the Android doc about Processes and Threads).
The onSensorChanged method is an I/O and it is a good practice to do I/O operations in a separate thread (instead of the main UI thread).
Once the callback method is called, you can store the event in another variable and use those local variables in that class.
Since you are writing a game, it is unlikely for your app to require every single event. Therefore, while the app is busy calculating data for your game, the other events can be dropped. You can do this by setting a "busy" flag (boolean) and include the code for calculation within this if block.
void callbackCall(SensorEvent event) {
if (!busy) {
// Set the busy flag to block other event changes
busy = true;
// callback code goes here
// Once finished, reset the busy flag to allow other events to come in
busy = false;
}
}
I put a list view inside a linearlayout,and I want to override onkeydown() method in ListView
,and I don't control the focus, just change some variables in onkeydown(),I want system do as if I haven't override the onkeydown method.what should I do?return false? or return super.onkeyDown()?.It will be very nice for any help. thank you in advance.
there are three listviews,and a b c are three item of listviews. when c is focused, when I press left arrow on keybord, then a get focus by default. And I want the first item in listview2 get focus how can I do?
ntc is not exactly correct. OS does not use reflection to get your base class' handler.
If you return false, you explicitly tell OS that you do not want to handle this event; OS calls the View's parent handler then (as your test shows); this happens until event got handled or top View is reached.
If you call super.OnKeyDown() you allow your base class to process event. Note that it's a base class' handler serving same view, not parent view; don't confuse here.
So, using one or the other depends on your view's behavior desired.
I supose in your case you need return super.onKeyDown();
super.onkeyDown()- this puts the burden on super class to handle the onKeyDown event by your own wish (You explicitly say to handle it). when you return false, android assumes that you have not handled the onKeyDown event and super.onKeyDown() gets called by default (without you calling it).
In our application we have a custom view (that extends ImageView) and in it we handle the touch events to record data. I wanted to add context menu functionality to this view and followed the guidelines in the official Android documents.
The onTouchEvent code works fine by itself. The context menu code also works fine. However, if I add them both, the context menu code stops working. I found out that with both pieces of code added, onCreateContextMenu is never called, therefore context menu is never displayed.
According to my interpretation of the Android documentation, returning false from onTouchEvent indicates that the event is not consumed, so it should be used for further processing. For some reason, it is not happening here. I would appreciate if anybody can tell me what I am missing. BTW, the target is Nexus One running 2.3.4 ROM.
Here's the code for the onTouchEvent in the custom view:
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
// Add event coordinates to an arraylist
break;
}
return false;
}
Thank you in advance for any help.
Elaborating on hackbod answer, you should probably have as last method statement return super.onTouchEvent(event);.
I guess that if you don't process the event, and if you don't invoke the default View behavior, than no one will do anything, and nothing will happen.
The point of return value might be for example to invoke some ancestor' default behavior, and let the derived class know if the ancestor processed the event or not.
After doing some search on Android Developers, referring to the topic override an existing callback method for the View here it says :
This allows you to define the default behavior for each event inside your custom View and determine whether the event should be passed on to some other child View.
Hence the main idea behind the return value is to let Android know whether the event should be passed down to child Views or not.
HTH
Edit:
Regarding the "directions" you mention in your comment, generally speaking (i.e. not only on Android) the UI event handling process goes on something like this:
At some point your derived custom control receives the event. In your event hook implementation, it's up to you whether to involve your ancestor's behavior or not. That's all you got regarding the class inheritance direction.
Then, there's the other direction, the one related to the UI controls hierarchy. Your custom control might be contained in one larger control container, and your control might as well contain other inner controls (textboxes, buttons, ...). Regarding this direction, if you declare not to process the event (returning false) then the UI event handling mechanism will pass the bucket to the containing (?) control (think the one on the background of yours).
You could call, from your long click listener,
openContextMenu(View view)
http://developer.android.com/reference/android/app/Activity.html#openContextMenu(android.view.View)
Do not register for context menu in OnCreate(), do it in onTouch() before
return true;
registerForContextMenu(View v);
openContextMenu(View v);
return true;
Returning false tells the parent that you didn't consume the event. The default implementation of View implements touch handling for that view; if you want that to execute, you must call super.onTouchEvent(event);
I encounter similar problem recently. When I enable long clickable in RecyeclerView's child, the ACTION_DOWN event can't not be received in RecyclerView's onTouchEvent.
If I changed to RecyclerView's dispatchTouchEvent, I would works. The ACTION_DOWN event can be received.