I am creating a qml app for android and run into the following problem when trying to catch button presses:
When I press the volume up, volume down or the home button. The following snipped prints: 0 which means the key event is unknown (Based on the QKeyEvent docu)
Keys.onPressed: {
console.log(event.key);
}
I also see this warning in logcat when pressing the home button:
Unhandled key code 3 !
or this warning when pressing the volume up button:
Unhandled key code 252 !
My Question: How can I add a handler/mapper for this key codes ?
Example I want to map the key code 3 to Qt.Key_Home in order to receive the correct key event in Keys.onPressed
I was able to 'remap' the key codes my devices uses to the key codes Qt expects by:
Copy $QT/src/android/java/src/org/qtproject/qt5/android/binding/ into your proejct folder.
Change ANDROID_PACKAGE_SOURCE_DIR in your .pro to point to the this folder.
rename the package name of all the classes in your new android/binding/ folder to fit the package name of your qml app.
add your custom mapping code in onKeyDown():
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
//do the remapping for the home button
if(keyCode == 3) {
keyCode = 122;
}
if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null)
return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyDown, keyCode, event);
else
return super.onKeyDown(keyCode, event);
}
Not near my QML machine but of top of my head do something like this.
Create a global object with required key codes like..
QtObject {
id: key_code
property int volume_up: 252
property int volume_down: <key_code_val>
property int key_home: 3
}
Then use it like..
Keys.onPressed {
if (event.key === key_code.volume_up) {
//Do volume up handling..
event.accepted = true
}
}
Also take a look at this: http://doc.qt.io/qt-5/qt.html#Key-enum
Related
I want a way to detect the backspace and the enter key strokes.
The most recommended way I found was the OnKeyListener. but, that isn't working for me. I tried Logging and turns out it just wasn't detecting any keystrokes.
Even it's documentation says it won't get triggered always.
I use Microsoft's swiftkey keyboard.
I also got a suggestion for addTextChengedListener. but, that won't detect backspaces. So, can't use it.
here's the code that isn't working -
editText.setOnKeyListener { view, i, keyEvent -> //not working
Log.i(TAG, "onKeyListener working")
when (i) {
KeyEvent.KEYCODE_ENTER -> {
fileChanged(
position,
editText.text.toString(),
note.isAListItem,
note.listItemIsChecked
)
listAdder(position)
true
}
KeyEvent.KEYCODE_DEL -> {
fileChanged(
position,
editText.text.toString(),
note.isAListItem,
note.listItemIsChecked
)
if (editText.text.isNullOrEmpty() && position != 0) {
listRemover(position)
}
true
}
else -> false
}
}
Also, I think the code is being discarded while compiling because the setOnKeyListener function doesn't get highlighted [yellow highlight] as the addTextChangedListener function. This is after the code was compiled. see below -
There are a couple of SO posts that have already discussed similar issues, but I find them not much relevant or too complex. I am working with an Android TV which has a remote controller, and it is supposed to be used in an enterprise environment. Users should not be able to have much control, so I have to restrict some of the functions available on the remote.
I created a simple app that overrides onKeyDown() and displays pressed keys using the following code:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//Read the input and display its code
switch(keyCode) {
case KeyEvent.KEYCODE_HOME:
mTextView.setText("Home");
break;
default:
char c = event.getDisplayLabel();
String code = String.valueOf(keyCode);
String displayText = c + " " + keyCode;
mTextView.setText(displayText);
mTextView.setBackgroundColor(mColor^=Color.GREEN);
}
return true;
}
I am able to capture most of the keys and override their behaviors most notably 131, 132, 133, and 134 (used as Media, TV, Web, and App shortcuts respectively on the remote).
The only problem is the Home button which AOSP source code (KeyEvent.java) says is system-specific:
* This key is handled by the framework and is never delivered to applications. */
public static final int KEYCODE_HOME = 3;
A solution that struck me was to extend KeyEvent and override the method isSystem() to return false when the selected key is KEYCODE_HOME. But, this method is defined final and I cannot override it. Any ideas?
you need to use
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
in your manifest and
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
Toast.makeText(this, ""+event.getKeyCode(), Toast.LENGTH_SHORT).show();
return false;
return super.dispatchKeyEvent(event);
}
i think control home key is 3
i hope was helpful
in Android I can easily detect the ENTER character using the setOnEditorActionListener method so that when a barcode is scanned into a textfield I know when the whole barcode has been read.
[Here is the Android code as requested:]
scanEditText.setOnEditorActionListener(new TextView.OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
if ( (actionId == EditorInfo.IME_ACTION_DONE) || ((event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN )))
{
System.out.println(" *** ENTER!");
return true;
}
else
return false;
}
});
I have been trying to replicate this in Codename One but with no luck. I have tried
setDoneListener
addDataChangedListener
ActionEvent on the text field and text area
overriding the keyPressed and keyReleased methods
but with no joy. If I set a textField with setSingleLineTextArea(false) I can see the barcode characters appear in the box followed by what I am assuming is a
new line character as the next scan appears on a new line. None of the methods listed seem to catch this event. If I change the focus to another box the ActionEvent is triggered but I don't want to have to move the focus each time.
[Here is the Codenameone code]
gui_searchTextField.setSingleLineTextArea(false);
gui_searchTextField.setDoneListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
Dialog.show("KB", "doneListener " +
gui_searchTextField.getText().trim(), "OK", null);
}
});
gui_searchTextField.addDataChangedListener((evt1, evt2) ->
{
System.out.println("DataChanged " + gui_searchTextField.getText());
});
So, how do I catch the end of the barcode like I can easily in the Android SDK?
Text input is very much a special case for us in all OS's so the keys go directly into the native OS text editing and don't "travel" through Codename One API's. However, DataChangeListener should be invoked for every key input so I'm not sure how this is happening exactly.
I did notice you are using System.out instead of Log.p so you might miss the output from the device related to the changes. Also I would recommend overriding the key pressed/released events and not starting the text editing. Then adding the key value to the text field instead of letting the native input handle it e.g.:
class MyForm extends Form {
public void keyReleased(int key) {
if(isCrLf(key)) {
// do this...
} else {
myTextField.setText(myTextField.getText() + ((char)key));
}
}
}
I'm working on an input device that has a button that I'd like to act both as a home button when pressed by itself, but also work as a modifier for the other buttons on the device.
I know you can do this in the kcm file with other buttons, and have something like:
key ESCAPE {
base: fallback BACK
alt, meta: fallback HOME
ctrl: fallback MENU
}
Is it possible to have something like:
key CTRL_LEFT {
base: fallback HOME
{SOMETHING HERE}: CTRL_LEFT
}
so that I can press that button with another button and have it not fallback on HOME?
Thanks in advance! :D
This functionality is not possible on a system level: see
http://source.android.com/tech/input/key-character-map-files.html for a list of all options possible.
However, if you would like to have it on an application level, you could program it in as follows:
import android.view.KeyEvent;
private boolean home = false;
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (event.getScanCode() == 29) //29 == CTRL_LEFT
home = true; //if we release this button, HOME needs to be invoked
else home = false; //so CTRL_LEFT was used as a modifier: no need to invoke HOME
//allow the system to pass key handling to the next listener
return super.onKeyUp(keyCode, event);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
if (event.getScanCode() == 29 && home == true)
{
super.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HOME));
return true; //so we absorb the event
}
return super.onKeyUp(keyCode, event);
}
Then, as long as this application is set up to receive the keystrokes (usually a privacy issue unless you're coding it in for yourself), it can process the keystrokes and dispatch the HOME button when need be.
Should you decide to proceed thus, you'd have to remove the
base: fallback HOME
from your code.
The question is all I have to say about it. I need to know how to handle the special keypresses like back, menu etc. in android NDK. I am using Cocos2dX so if you could give me a Cocos2dX specif answer that would be great.
In cocos2dx, each CCLayer gets the following methods that can be overriden to add functionality to them:
class CC_DLL CCKeypadDelegate
{
public:
// The back key clicked
virtual void keyBackClicked() {}
// The menu key clicked. only avialble on wophone & android
virtual void keyMenuClicked() {};
};
CCLayer inherits from CCKeypadDelegate. And each screen can give implementation to these functions.
In Cocos2d-x
You have to do that
implement
virtual void keyBackClicked();
and also this
this->setKeyPadEnable(true);
in .cpp class
Enable keypad : this->setKeypadEnabled(true);
Override onKeyReleased method :
virtual void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event);
Check for keyCode:
void GameScene::onKeyReleased(EventKeyboard::KeyCode keyCode, cocos2d::Event *event)
{
if (keyCode == EventKeyboard::KeyCode::KEY_BACKSPACE) {
CCLOG("You pressed back button");
}
else if(keyCode == EventKeyboard::KeyCode::KEY_MENU)
{
CCLOG("You pressed menu button");
}
}
If your class is not inherit with CClayer, then you can handle this through JNI calls.
In Cocos2dxGLSurfaceView.java you handle back and menu key from onKeyDown function
public boolean onKeyDown(final int pKeyCode, final KeyEvent pKeyEvent)