Android Accessibility Service Focus EditText - android

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.

Related

Xamarin Android change accessibility focus

In Android Studio, using Java, to set the accessibility focus on a certain view after, for example, pressing a button, you have to do myview.sendAccessibilityEvent(AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED). In Xamaring, using C#, the closest thing that I found is myview.SendAccessibilityEvent(EventTypes.ViewAccessibilityFocused); but it doesn't work that good, infact, it only read out the myview accessibility name, without actually setting the focus on that, the focus remain on the button pressed. I also tried myview.SendAccessibilityEvent(EventTypes.ViewFocused); but it doesn't work either.
Another thing that I found is myview.SendAccessibilityEventUnchecked(AccessibilityEvent.WindowsChangeAccessibilityFocused); but I got an error saying Argument 1: cannot convert from 'Android.Views.Accessibility.WindowsChange' to 'Android.Views.Accessibility.AccessibilityEvent' even if it is said that SendAccessibilityEventUnchecked takes an AccessibilityEvent as argument.
Any idea on how to solve?
Or any idea on how to set the accessibility focus to a certain view after some event?
(Note if needed, I am just testing it on Android native, than I will need to use that in a Forms project using Dependency Service)
WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED is a sub type for TYPE_WINDOWS_CHANGED, which should only be dispatched by the system. And the accessibility focus won't be changed by sending accessibility event.
Actually, send accessibility event triggers Accessibility Service, and you can change the accessibility focus in the service's onAccessibilityEvent method with:
public override void OnAccessibilityEvent(AccessibilityEvent e)
{
//you can use event type and source node to see if the event is sent by you
AccessibilityNodeInfo sourceNode = e.Source;
AccessibilityNodeInfo targetNode = sourceNode.FocusSearch(FocusSearchDirection.Down);
targetNode.PerformAction(Android.Views.Accessibility.Action.AccessibilityFocus);
}
See more information about Accessibility Focus and Input Focus here.
Problem solved, the right way to achieve that should be myview.SendAccessibilityEvent(EventTypes.ViewHoverEnter) that has the same integer value of the Android value WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED.
Another way is to do myview.SendAccessibilityEvent((EventTypes) (int) WindowsChange.AccessibilityFocused) so you have to do a double cast, int and EventTypes, on WindowsChange.AccessibilityFocused because WindowsChange is a different enum from EventTypes.
I leave the github issue that I opened where I got these answers git issue.

Xamarin | Android | Custom Keyboard Android.Views.KeyCode

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

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.

Prevent android webview soft keyboard to lost focus

I have a problem since a long time and I have not find a way of solving it.
My app as a webview that loads an url where the user can fill certain text inputs, also, the app produces sounds in certain situations(to help/assist the users), the problem is that, sometimes when the user is writing in an input and some sound is triggered the soft keyboard hides because the input lost its focus.
This is quite annoying to the users because they have to touch the input again to continue writing.
Any ideas about how to solve it?
I was confused on this same issue but I learned that it is common practice to call search.blur() (assuming we are talking about a search text input field) when a window.resize event is triggered for desktop, but sometimes that same code causes issues on mobile because the virtual keyboard triggers a resize event as well. If this is the case, you may have to use something like modernizr to determine if you are in a mobile device context and if so don't call that search.blur(). Search your code base for the blur() pattern to see if that is what is happening for you.
To fix, try something like this:
window.onresize = function () {
if (!isMobile) {
search.blur()
}
}

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."

Categories

Resources