Is there a way in Android where an android application when active will catch and process all key events (and maybe touch events) before they are delivered to the actual view which is supposed to be handling it?
I know that we can have onKeyDown or similar method in Activity to handle the keyevent, but it is fired only if none of its child views handles it internally.
These view are usually ListView, GridView, ScrollView, etc..
I want to find a way that my keyHandler method is called before that keyEvent is delivered to these views.
Implementation in my keyHandler will be very simple. It will just play a tone upon each event, just like keypress tone, and then forward it to be handled the way it was meant to be by those views or Android framework.
Want to know if its possible beacuse I don't want to write onKeyListener to each and every view in every activity as I have lot of activities and lots of views and it will just become difficult to write the same code everywhere. If there is a way, i can implement that in BaseActivity and derive all my activities by that and go on my way of having default key handler.
I don’t try it myself but I think this one will help you: (just scroll a little bit down to the method mentioned in the text)
Input Event: Event Handlers - Activity.dispatchTouchEvent(MotionEvent)
Looks like this is the chance to catch events before they get to the window. Read the detailed Description here.
Related
I've been working on a project which needs to capture keystrokes from an external keyboard (a handheld barcode scanner really) anywhere in the app. Using react-native, this should be trivial, especially with the library react-native-keyevent.
Works perfectly on the initial load. I then navigate to another part of the app (using react-navigation) and try to scan a barcode; nothing happens. I replaced the react-native-keyevent overrides MainActivity.java with some simple Log.d("KeyEvents", "..."), overriding dispatchKeyEvent, onKeyUp, onKeyMultiple and onKeyDown. I only log, then call super.
Same behaviour. Logs fine until I navigate, then it stops. After investigating the Android docs, it seems Views can override key handlers, and thereby 'steal' keystrokes. However I'm stuck finding out which view steals the focus. Also there's really no keyboard handling in react-native by default, so to my understanding, everything should be passed on to the activity.
Wandering hopelessly around in the react-native codebase, I stumbled upon TVEventHandler which I use to log if a view requests focus:
import TVEventHandler from 'react-native/Libraries/Components/AppleTV/TVEventHandler';
(new TVEventHandler).enable('foo', function(){
console.log(arguments);
})
Right before the handlers stop working, this line indeed logs some focus events with a view tag. However, I don't know how to find out which view has a certain tag.
Can someone point me in the right direction where to look?
In my app, i have two buttons that send an event with an ID using an event bus (Otto). Depending on this ID, the app goes to a different level of the navigation between differents fragments. Is possible to avoid that the event bus sends the same event (with different ID) in the same millisecond when the user taps over two different button at the same millisecond?. I attach an image in order to show my Logcat.
Thanks!
EDIT 1:
Using syncronized both onClick method as subscribe method, i continue receiving the events in the same millisecond. Now, the myth about "syncronized" has down for me. O_o
There are posts where they explain how avoid very fast clicks, but here, the clicks are in the same millisecond...rare, but you can see the logs.
I attach new images with the method that i am using. Thanks!
Yes, use synchronized keyword with the method which is generating events (or also with the method which receive events).
For example:
public synchronized void genEvent(){
}
See following related links
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
When to use synchronized in Java
Is there an advantage to use a Synchronized Method instead of a Synchronized Block?
I have a simple Apache Flex view based application that runs on Android as follow:
<f:MyView xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/sparks"
activate="activateHandler(event)"
deactivate="deactivateHandler(event)"/>
I expect the activateHandler() should execute only once when the view is activated, however after I pop and then push the same view back the number of activateHandler() execution increased by how many times I did the pop and push operation. Why would this happen and how to force it to operate as expected (i.e only once)?
Expanding on #JileniBouguima's answer, changing activate to creationComplete will resolve this because of how those events work. Your expectation that activateHandler() executes only once is a little off; according to the Activate event documentation, activate fires
every time your application gains operating system focus and becomes active.
By contrast, creationComplete fires once per object, once the component is created.
I am not sure what code exactly is written in the handlers activateHandler and deactivateHandler but in Flex this is a standard practice to remove event listener if you do not need it any more. I am assuming that whenever you pop and push the same view it is adding and removing the listener. I can help you more if you share the handlers code.
Change activate to creationComplete.
I have a 'trick' that I do sometimes in Java/Swing in which I create a swing component that is always invisible and have property change event listener(s) attached to it. When a variable(s) changes value, the code will cause that component to change and fire an event and anything listening will know that those variable(s) have changed.
I want to do this same thing in Android or AndEngine. What would I use instead of the swing component? I'm was thinking of overriding some subclass of org.andengine.entity.Entity, but I don't see any event to fire.
Sounds like you almost hit on it with your Swing idea. There is no event pattern built into andengine, and the reason for this is probably because of the event classes built into the android operating system.
You should have good luck implementing a Listener (Observer Pattern) into your app following the steps in this other Stack Overflow answer:
Custom event listener on Android app
or this simple example in which the broadcaster call a function on a single listener:
Android - event listener
As a footnote, neither example includes code to REMOVE listeners. Be sure your implementation does include that so that you can garbage collect objects you don't need any more.
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.