Xamarin | Android | Custom Keyboard Android.Views.KeyCode - android

I am creating a custom keyboard for a Xamarin Android Application. I have it working, and my listener receives the input. My issue is the parameter Android.Views.Keycode. This enumeration does not have all of the possible keys. I have found some of them generate the correct keystroke if the KeyEvent is created with MetaKeyStates.ShiftOn. But even in that I have not found the right combination for the {} keys. There also doesn't appear to be a clear answer to which key or key/MetaState combination maps to backspace, Next, Done, etc.
I have not found documentation that shows which Keyode in conjunction with the required MetaState will generate which key strokes. Does such documentation exists? Does anyone have an exhaustive example showing which Keycode and which metastates create which characters?
Also, in the case of my keyboard, the ! and ? characters will appear on the screen with the normal text. Do I need to use a custom Keycode for them so I can tell the difference between them and the character that would have the same Keycode without a metastate?

Why are you using keycodes? Those are for hardware buttons. Software keyboards usually use InputConnection.commitText and skip keycodes entirely.
Next, Done, etc are the action button. That's another call on InputConnection- performEditorAction.
Delete is generally done by InputConenction.deleteSurroundingText.
Shifts are generally an internal state and not connected to any keycode.
You're doing everything the wrong way, basically. Here's the android implementation, I assume xamarin has its wrappers. https://developer.android.com/reference/android/view/inputmethod/InputConnection

Related

Is there a way to use UIAutomator to enter cyrillic letters?

I'm trying to test my company's browser's auto suggest functionality for the Russian language with UIAutomator and am hitting a snag:
There are no KeyEvent.KeyCode_* code for Russian letters and UiDevice.pressKeyCode(KeyEvent.KEYCODE_LANGUAGE_SWITCH) doesn't appear to help. What documentation I found inside the KeyEvent class seems to suggest that I just need to use the same KeyCodes as the english letters but magically they would be mapped across to the letters of of the other languages. That does not appear to actually happen however as I'm still seeing the English letter show up when I try that.
Normally with Russian I just use UiObject2.setText(...) but that method does not trigger auto suggestions.
I've tried delving into what UiDevice.pressKeyCode is doing and attempting a couple workarounds such as:
KeyEvent eventsб2 = new KeyEvent(SystemClock.currentThreadTimeMillis(), "б", KeyCharacterMap.VIRTUAL_KEYBOARD, 0);
Instrumentation.sendKeySync(eventsб2);
or
KeyEvent[] eventsа = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD).getEvents(new char[] {'a'});
Instrumentation.sendKeySync(eventsа[0]);
But they either don't enter the letter or throw a permission exception regarding needing the INJECT_EVENTS permission. Overall I'm feeling like I'm stumbling in the dark and would love some advice on how to proceed.
I tried this and worked.
/**
* ##Test comment here##
*
* #throws Exception
*/
#Test
public void culebraGeneratedTest_CyrillicKeyBoardAndSelectSuggestion() throws Exception {
mDevice.pressHome();
mDevice.findObject(By.res("com.android.quicksearchbox:id/search_widget_text").clazz("android.widget.TextView").text(Pattern.compile("")).pkg("com.android.quicksearchbox")).clickAndWait(Until.newWindow(), DEFAULT_TIMEOUT);
mDevice.findObject(By.desc("й").clazz("com.android.inputmethod.keyboard.Key").text(Pattern.compile("")).pkg("com.android.inputmethod.latin")).clickAndWait(Until.newWindow(), DEFAULT_TIMEOUT);
(new UiScrollable(new UiSelector().resourceId("com.android.quicksearchbox:id/suggestions").index(1).packageName("com.android.quicksearchbox"))).getChildByText(new UiSelector().className("android.widget.RelativeLayout").packageName("com.android.quicksearchbox"), "йемен", true).click();
}
I have to admit that I don't know Russian or what I was selecting on the Cyrillic keyboard, so bear with me.
To generate this test I used CulebraTester as it seems to be an interesting use case for the tool.
The steps were:
start recording the test (generating Java UiAutomator, can also generate python and other languages)
press Home
select the Quick Search Box
Press the key
Select one of the suggestions
You will be able to create a similar test using AndroidViewClient/culebra in python but because this tool is based on the information obtained from uiautomator dump it won't be able to detect the letters on the keyboard, but you can also touch them using DIPs
vc.dump(window=-1)
vc.findViewByIdOrRaise("com.android.quicksearchbox:id/search_widget_text").touch()
vc.sleep(_s)
vc.dump(window=-1)
device.touchDip(15.33, 393.33, 0)
but this is not as device independent as the first solution.
Hope this helps you.

How to include suggestions in Android Keyboard

I am working on Android SoftKeyboard. I've created layout for keyboard but dont't know how to include suggestions which appears if we type some word in EditText.
For example if i write "Kn" then "Known" and "Known" are shown in Suggestions.
So my questions are -
1) How to include suggestions in Android Softkeyboard?
2) Is there any way to include our own list of suggestions?
Thanx a lot in advance.
I've already checked this and this but not able to find any proper answer. Any help would be appreciated.
EDIT
I want to include suggestions directly above Keyboard as shown in picture below.
You can use the static method UserDictionary.Words.addWord(....): Link
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// On JellyBean & above, you can provide a shortcut and an explicit Locale
UserDictionary.Words.addWord(this, "MadeUpWord", 10, "Mad", Locale.getDefault());
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
UserDictionary.Words.addWord(this, "MadeUpWord", 10, UserDictionary.Words.LOCALE_TYPE_CURRENT);
}
You will need to add this permission to your manifest:
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY"/>
Added words will appear in Settings > Language & input > Personal dictionary.
If you are implementing your own soft keyboard, I suggest you go through Creating an Input Method. The suggestions are usually shown in the Candidates View. By default, InputMethodService#onCreateCandidatesView() returns null. You should override this method to return your implementation of the suggestions bar.
Here's a sample project that implements the Candidates view: SoftKeyboard.
More info:
Word and phrase suggestions go in the candidates view. Info about how to create & populate it are in the sample project mentioned above.
As far as I know, the selection of what words/phrases to suggest is developer's responsibility. Android does not provide those for you. You will probably need a set of dictionaries - one for each language/locale you plan on supporting. You may also want to maintain a dictionary of user-specified words.
Android's default keyboard uses these: Link
If you download one of these, unpack it and open with a text editor:
dictionary=main:en,locale=en,description=English,date=1402373178,version=47
word=the,f=222,flags=,originalFreq=222
word=to,f=215,flags=,originalFreq=208
word=of,f=214,flags=,originalFreq=214
word=and,f=212,flags=,originalFreq=212
word=in,f=210,flags=,originalFreq=210
.... 165,635 more lines
As apparent, the frequency plays a pivotal role in determining the suitability of a word as a suggestion. You probably don't want to suggest tachometer when the user types ta. You probably do want to suggest take - frequency helps you there.
Autocorrection:
word=id,f=99,flags=,originalFreq=99
shortcut=I'd,f=whitelist
The flags indicate appropriateness:
word=goddamn,f=0,flags=offensive,originalFreq=62
Even if you decide to use these dictionaries, the code to parse them and obtain meaningful suggestions will have to come from you.
Two articles (both by Peter Kankowski) that talk about predictive text input & spelling correction:
Using DAWG for predictive text input
Using Ternary DAGs for Spelling Correction
CandidatesView:
The first thing you should know about the CandidatesView: it is optional. In fact, LatinIME (android's default soft keyboard) does not use it. Instead LatinIME has its own implementation - SuggestionStripView - which is similar. The default behavior of InputMethodService#onCreateCandidatesView() is to return null. If you choose to provide your own implementation, don't override this method.
You need to decide what your CandidatesView should look like. One possible implementation can be a HorizontalScrollView. After you evaluate your suggestions (for example, user start writing "as", and your suggestion-logic gives you a List<String> containing "has", "was", "assist", "ask", "asked", "asking", "assume"), create & add TextViews holding these strings to the HorizontalScrollView(LinearLayout). This way, user can scroll horizontally and choose the intended word by clicking on it.
It is up to you to decide whether to use the API or handle the CandidatesView yourself. If you want to use the API, override InputMetodService#onCreateCandidatesView(), inflate your custom layout, then return it. Hold a reference to it, so you can update it when required. To control CandidatesView's visibility, use the method setCandidatesViewShown(boolean).
If you are creating a custom keyboard, I suggest you go through Creating Input Method, there is a sample code that you can go over. CandidateView is probably what you are looking for. It is explained in the link above.
If you want to provide inline spell checker, you would want to check out Spellchecker framework
Hope this helps.

Android Accessibility Service Focus EditText

I am writing an accessibility service. I've been trying to focus EditText fields in a way that pops up the software keyboard and I have been unsuccessful. I am able to get the cursor into the EditText field, but the soft keyboard doesn't pop up. Given EditTextNode is an AccessibilityNodeInfo that I have gotten from various accessibility events and that said nodeInfo isEditable, isFocusable, isVisibleToUser and isClickable when I attempt all of these actions and they all return true upon completion.
editTextNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
In my mind the above should simply work, and the fact that it does not is a bug in the Accessibility API, if not for my entire android version, at the very least on my device (Droid Ultra, Android 4.4.4). I have also tried:
editTextNode.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
Puts focus into the field so I can see the input cursor, but no keyboard.
editTextNode.performAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Doesn't really do anything unless talkback is enabled.
editTextNode.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, someBundle);
Along with appropriate arguments this will work, but only if there is already text in the editText field. I need to pull the keyboard up on empty text fields as well. Yes, I tried inputing 0,0 for start and end text selection arguments. The SET_SELECTION method only works with text in the field!
This has been frustrating me for a couple days, hopefully you guys can help. Though I believe I've stumbled onto a bug and am going to have to wait for Android to update. Because the ACTION_CLICK method should really be all that is needed. But, I could be missing something silly, Accessibility API Doc is somewhat scant. Am willing to attempt anything.
To restate #alanv's comment in answer form:
You are correct, it is a bug in accessibility services prior to API 21.

Problems intercepting space key in EditText

I'm attempting to make a way for a user to input text into a TextView from an EditText. However, if the user enters something, and wants to fix it, I want them to be able to press space on an empty EditText to get the last thing they wrote back. The first problem is, if they type in "hello", hit enter to add it to the TextView (which clears it from the EditText), then hit space, the EditText then has " hello". Not what I want, and I can't figure out why.
My code to place the entered text into a holding string:
b1 = ti.getText().toString();
Then, if the user hits the space key, I believe they should get b1 in the EditText. Instead, I get: " " + b1. Why is this added space in there?
if((event.getAction()==KeyEvent.ACTION_DOWN)&&(key == KeyEvent.KEYCODE_SPACE)){
if(ti.getText().toString().equals("")){
ti.setText(b1);
}
My second, bigger problem is that the above code only works on a hardware keyboard. What is the key event for a software keyboard pressing space?
This is all in an onKeyListener.
An easy way to solve the extra space problem is to just remove the space from the String before you put it into the EditText
b1 = b1.substring(1); //<--- cut out the first character, which is the " " in your case.
ti.setText(b1);
p.s. I strongly recommend more descriptive variable names. Your programs are likely to be confusing to work on if you use names like ti and b1. Perhaps these choices make more sense in the context of your program. But from what you've shown here it is not easy to tell what these names refer to.
For your first problem I suspect you need to return true from your onKey method in the onKeyListener when your 'if' condition is met, to indicate that the event is consumed, otherwise you get the default onKeyListener adding the space to the EditText. i.e.:
if((event.getAction()==KeyEvent.ACTION_DOWN)&&(key == KeyEvent.KEYCODE_SPACE)){
if(ti.getText().toString().equals("")){
ti.setText(b1);
return true;
}
}
This extract from the KeyEvent API docs should help with problem 2:
"As soft input methods can use multiple and inventive ways of inputting text, there is no guarantee that any key press on a soft keyboard will generate a key event: this is left to the IME's discretion, and in fact sending such events is discouraged. You should never rely on receiving KeyEvents for any key on a soft input method. In particular, the default software keyboard will never send any key event to any application targetting Jelly Bean or later, and will only send events for some presses of the delete and return keys to applications targetting Ice Cream Sandwich or earlier. Be aware that other software input methods may never send key events regardless of the version. Consider using editor actions like IME_ACTION_DONE if you need specific interaction with the software keyboard, as it gives more visibility to the user as to how your application will react to key presses."

Is it possible to define a suggestion list in webview applications?

When entering a string in a text type input element in a webview based app, a list of possible words is showed above the virtual keyboard.
In my application the user is not allowed to input arbitrary words, instead only words and phrases from a database are legal.
So, I want to set the list of words from my phonegap app and disable the automatic creation of this list.
Q: Is this possible to create the list - and how?
(This is a phonegap app and I am testing on android, but this might be a problem for webview / text input fields on different platforms)
EDIT:
Just found out (yes, I'm new to android development), that one can disable the suggestion list with: Settings / Language and Keyboard / Android keyboard / Show suggestions.
But of course, this setting should be made only for the app, from inside the app, without user interaction and not changing anything outside the app.
Any chance to get this done?
EDIT 2:
Instead of disabling the suggestion list I tried to use it.
The displayCompletions method of InputMethodManager sounded promising, so I tried the following code:
...
// data member
InputMethodManager mInputMethodManager = null;
...
...
// initialized
mInputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
...
public void showSuggestions(String[] words) {
Log.d(TAG, "showSuggestions (in Java!): " + words.length); // yes, this code is executed
CompletionInfo[] completions = new CompletionInfo[words.length];
for (int i=0; i<words.length; i++) {
completions[i] = new CompletionInfo(i, i, words[i]); // no idea, what the 2 extra integers mean
}
mInputMethodManager.displayCompletions(mView, completions);
}
The method is executed, whenever a new list is available (after the input has changed and the server has answered a request).
However, nothing has changed - the builtin mechanism is still doing its disadvantageous work.
Why don't you use something like the auto complete in jQuery UI.
http://jqueryui.com/demos/autocomplete/
Also, it's not too hard to whip this up yourself in JavaScript.
http://www.javascript-examples.com/autocomplete-demo/
In case there are different variants of virtual keyboard(swype and others) there might be no list of possible words. So, I suppose there is no general solution for not showing this list.
There is a parameter http://developer.android.com/reference/android/widget/TextView.html#attr_android:editorExtras editorExtras which defines parameters passed to input method implementation, but I'm not sure how would you use it in PhoneGap application
Edit:
I suppose you can extend default input method and make it not to show suggestions
inputmethod reference http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html
Providing Custom Software Keyboards
If you are interested in developing your own software keyboards, we highly recommend the following references:
IMEs are implemented as an Android service. Begin by reviewing the Android packages called android.inputmethodservice and android.view.inputmethod, which can be used to implement custom input methods.
The SoftKeyboard sample application in the Android SDK provides an implementation of a software keyboard.
The Android Developer technical articles on onscreen input methods and creating an input method.
found it here http://e-university.wisdomjobs.com/android/chapter-946-288/handling-advanced-user-input.html

Categories

Resources