Merge pull request #13546 from keymanapp/fix/android/banner-after-unlock

fix(android): Handle banner overrides independently when device is locked and unlocked
This commit is contained in:
Darcy Wong 2025-03-28 08:20:31 +07:00 • committed by GitHub
commit 5f0f4b4f5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 153 additions and 25 deletions

View file

@ -159,9 +159,11 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
Context appContext = getApplicationContext();
// Temporarily disable predictions on certain fields (e.g. hidden password field or numeric)
inputType = attribute.inputType;
KMManager.setMayPredictOverride(inputType);
if (KMManager.getMayPredictOverride()) {
KMManager.setPredictionsSuspended(inputType, KeyboardType.KEYBOARD_TYPE_SYSTEM);
if (KMManager.getPredictionsSuspended(KeyboardType.KEYBOARD_TYPE_SYSTEM)) {
KMManager.setBannerOptions(false);
// Set the system keyboard HTML banner
BannerController.setHTMLBanner(this, KeyboardType.KEYBOARD_TYPE_SYSTEM);
} else if (KMManager.isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_SYSTEM)){
// Check if predictions needs to be re-enabled per Settings preference
Keyboard kbInfo = KMManager.getCurrentKeyboardInfo(appContext);

View file

@ -244,6 +244,12 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
@Override
protected void onResume() {
super.onResume();
if (textView != null) {
// Reset inAppPredictionsSuspendedForSensitiveInput flag
KMManager.setPredictionsSuspended(textView.getInputType(), KeyboardType.KEYBOARD_TYPE_INAPP);
}
KMManager.onResume();
KMManager.hideSystemKeyboard();

View file

@ -165,12 +165,12 @@ public final class KMKeyboardWebViewClient extends WebViewClient {
// appContext instead of context?
SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);
boolean modelPredictionPref = false;
if (!KMManager.getMayPredictOverride() && KMManager.currentLexicalModel != null) {
if (!KMManager.getPredictionsSuspended(keyboardType) && KMManager.currentLexicalModel != null) {
modelPredictionPref = prefs.getInt(KMManager.getLanguageAutoCorrectionPreferenceKey(
KMManager.currentLexicalModel.get(KMManager.KMKey_LanguageID)), KMManager.KMDefault_Suggestion)
!= SuggestionType.SUGGESTIONS_DISABLED.toInt();
}
KMManager.setBannerOptions(modelPredictionPref);
KMManager.setBannerOptions(modelPredictionPref, keyboardType);
RelativeLayout.LayoutParams params = KMManager.getKeyboardLayoutParams();
kmKeyboard.setLayoutParams(params);
} else if (url.indexOf("suggestPopup") >= 0) {

View file

@ -257,10 +257,13 @@ public final class KMManager {
// haptic feedback disabled for hardware keystrokes
private static boolean mayHaveHapticFeedback = false;
// Special override for when keyboard is entering a password text field.
// When mayPredictOverride is true, the option {'mayPredict' = false} is set in the lm-layer
// Special flags to temporarily disable predictions when editing a password field.
// These are maintained independently for inapp keyboard and system keyboard.
// When true, the suggestion banner passes the option {'mayPredict' = false} to KeymanWeb in the lm-layer
// regardless what the Settings preference is.
private static boolean mayPredictOverride = false;
// API added Keyman 18.0
private static boolean inAppPredictionsSuspendedForSensitiveInput = false;
private static boolean systemPredictionsSuspendedForSensitiveInput = false;
// Determine how system keyboard handles ENTER key
public static EnterModeType enterMode = EnterModeType.DEFAULT;
@ -1409,25 +1412,49 @@ public final class KMManager {
}
/**
* Sets mayPredictOverride true if the InputType field is a hidden password text field
* (either TYPE_TEXT_VARIATION_PASSWORD or TYPE_TEXT_VARIATION_WEB_PASSWORD
* but not TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)
* Determine the predictions should be suspended for a given InputType field: hidden password text field
* (but not TYPE_TEXT_VARIATION_VISIBLE_PASSWORD).
* Also true for numeric text fields
* @param inputType android.text.InputType
* @return boolean
*/
public static void setMayPredictOverride(int inputType) {
mayPredictOverride =
((inputType == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD)) ||
(inputType == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD)) ||
isNumericField(inputType));
private static boolean shouldSuspendPredictions(int inputType) {
return ((inputType == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD)) ||
(inputType == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD)) ||
isNumericField(inputType));
}
/**
* Get the value of mayPredictOverride
* @return boolean
* Sets PredictionsSuspended true if the given InputType field for the keyboard is a hidden password text field
* (either TYPE_TEXT_VARIATION_PASSWORD or TYPE_TEXT_VARIATION_WEB_PASSWORD
* but not TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)
* Also true for numeric text fields.
* This is to temporarily disable suggestions in these text fields.
* API added Keyman 18.0
* @param inputType android.text.InputType
* @param {KeyboardType} keyboard
*/
public static boolean getMayPredictOverride() {
return mayPredictOverride;
public static void setPredictionsSuspended(int inputType, KeyboardType keyboard) {
if (keyboard == KeyboardType.KEYBOARD_TYPE_INAPP) {
inAppPredictionsSuspendedForSensitiveInput = shouldSuspendPredictions(inputType);
} else if (keyboard == KeyboardType.KEYBOARD_TYPE_SYSTEM) {
systemPredictionsSuspendedForSensitiveInput = shouldSuspendPredictions(inputType);
}
}
/**
* Get the value of PredictionsSuspendedForSensitiveInput based on KeyboardType.
* API added in Keyman 18.0
* @param {KeyboardType} keyboard
* @return boolean of inAppPredictionsSuspendedForSensitiveInput or systemPredictionsSuspendedForSensitiveInput
*/
public static boolean getPredictionsSuspended(KeyboardType keyboard) {
if (keyboard == KeyboardType.KEYBOARD_TYPE_INAPP) {
return inAppPredictionsSuspendedForSensitiveInput;
} else if (keyboard == KeyboardType.KEYBOARD_TYPE_SYSTEM) {
return systemPredictionsSuspendedForSensitiveInput;
}
return false;
}
/**
@ -1556,20 +1583,23 @@ public final class KMManager {
// When entering password field, maySuggest should override to disabled
SharedPreferences prefs = appContext.getSharedPreferences(appContext.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);
int maySuggest = mayPredictOverride ? SuggestionType.SUGGESTIONS_DISABLED.toInt() :
prefs.getInt(getLanguageAutoCorrectionPreferenceKey(languageID), KMDefault_Suggestion);
int suggestionPreference = prefs.getInt(getLanguageAutoCorrectionPreferenceKey(languageID), KMDefault_Suggestion);
RelativeLayout.LayoutParams params;
if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_INAPP) && !InAppKeyboard.shouldIgnoreTextChange() && modelFileExists) {
params = getKeyboardLayoutParams();
// Do NOT re-layout here; it'll be triggered once the banner loads.
InAppKeyboard.loadJavascript(KMString.format("enableSuggestions(%s, %d)", model, maySuggest));
int inappMaySuggest = inAppPredictionsSuspendedForSensitiveInput ? SuggestionType.SUGGESTIONS_DISABLED.toInt() :
suggestionPreference;
InAppKeyboard.loadJavascript(KMString.format("enableSuggestions(%s, %d)", model, inappMaySuggest));
}
if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_SYSTEM) && !SystemKeyboard.shouldIgnoreTextChange() && modelFileExists) {
params = getKeyboardLayoutParams();
// Do NOT re-layout here; it'll be triggered once the banner loads.
int maySuggest = systemPredictionsSuspendedForSensitiveInput ? SuggestionType.SUGGESTIONS_DISABLED.toInt() :
suggestionPreference;
SystemKeyboard.loadJavascript(KMString.format("enableSuggestions(%s, %d)", model, maySuggest));
}
return true;
@ -1621,6 +1651,25 @@ public final class KMManager {
return true;
}
/**
* setBannerOptions - Update KMW for inapp/system keyboard whether to generate predictions.
* For now, also display banner
* @param mayPredict - boolean whether KMW should generate predictions
* @param {KeyboardType} keyboard
* @return boolean - Success
*/
public static boolean setBannerOptions(boolean mayPredict, KeyboardType keyboard) {
String url = KMString.format("setBannerOptions(%s)", mayPredict);
if (keyboard == KeyboardType.KEYBOARD_TYPE_INAPP && InAppKeyboard != null) {
InAppKeyboard.loadJavascript(url);
}
if (keyboard == KeyboardType.KEYBOARD_TYPE_SYSTEM && SystemKeyboard != null) {
SystemKeyboard.loadJavascript(url);
}
return true;
}
/**
* Update KeymanWeb banner type
* @param {KeyboardType} keyboard

View file

@ -0,0 +1,29 @@
---
title: KMManager.getPredictionsSuspended()
---
## Summary
The **getPredictionsSuspended()** method returns a flag that determines whether predictions are temporarily disabled because the currently selected text field is a hidden password text field or a numeric text field.
## Syntax
```java
KMManager.getPredictionsSuspended(KeyboardType keyboardType)
```
### Parameters
`keyboardType`
: The keyboard type. `KEYBOARD_TYPE_INAPP` or
`KEYBOARD_TYPE_SYSTEM`.
### Returns
Returns `true` if predictions are temporarily disabled because the currently selected text field is a hidden password text field or a numeric text field. `false` otherwise.
## Description
Use this method to check if predictions are temporarily disabled because of the type of currently selected text field. This value takes precedence over the user preference in the LanguageSettings menu.
## History
Added syntax in Keyman Engine for Android 18.0.
## See also
* [setPredictionsSuspended](setPredictionsSuspended)

View file

@ -152,6 +152,9 @@ The KMManager is the core class which provides most of the methods and constants
[`getOrientation()`](getOrientation)
: returns the device's current orientation (Portrait vs Landscape)
[`getPredictionsSuspended()`](getPredictionsSuspended)
: returns whether predictions are temporarily disabled because the currently selected text field is a hidden password text field or a numeric text field.
[`getSpacebarText()`](getSpacebarText)
: returns the current text display pattern for the spacebar
@ -257,6 +260,9 @@ The KMManager is the core class which provides most of the methods and constants
[`setMaySendCrashReport()`](setMaySendCrashReport)
: sets whether Keyman Engine can send crash reports over the network to Sentry
[`setPredictionsSuspended()`](setPredictionsSuspended)
: sets whether predictions are temporarily disabled because the currently selected text field is a hidden password text field or a numeric text field.
[`setShouldAllowSetKeyboard()`](setShouldAllowSetKeyboard)
: sets whether Keyman Engine allows setting a keyboard other than the default keyboard

View file

@ -0,0 +1,36 @@
---
title: KMManager.setPredictionsSuspended()
---
## Summary
The **setPredictionsSuspended()** method sets a flag to temporarily disable predictions when the currently selected text field is a hidden password text field or a numeric text field.
## Syntax
```java
KMManager.setPredictionsSuspended(int inputType, KeyboardType keyboardType)
```
### Parameters
[`inputType`](https://developer.android.com/reference/android/text/InputType)
: An integer defining the basic context type of text being edited. If the text is one of the following InputTypes, this methods returns `true`:
* TYPE_CLASS_TEXT
* TYPE_TEXT_VARIATION_PASSWORD
* TYPE_CLASS_TEXT
* TYPE_TEXT_VARIATION_WEB_PASSWORD
* TYPE_CLASS_NUMBER
* TYPE_CLASS_PHONE
`keyboardType`
: The keyboard type. `KEYBOARD_TYPE_INAPP` or
`KEYBOARD_TYPE_SYSTEM`.
## Description
Use this method to temporarily disable predictions because of the currently selected text field. This value takes precedence over the user preference in the LanguageSettings menu.
## History
Added syntax in Keyman Engine for Android 18.0.
## See also
* [getPredictionsSuspended](getPredictionsSuspended)

View file

@ -135,9 +135,9 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
KMManager.setNumericLayer(KeyboardType.KEYBOARD_TYPE_SYSTEM);
}
// Temporarily disable predictions if entering a hidden password field
KMManager.setMayPredictOverride(inputType);
if (KMManager.getMayPredictOverride()) {
// Temporarily disable predictions on certain fields (e.g. hidden password field or numeric)
KMManager.setPredictionsSuspended(inputType, KeyboardType.KEYBOARD_TYPE_SYSTEM);
if (KMManager.getPredictionsSuspended(KeyboardType.KEYBOARD_TYPE_SYSTEM)) {
KMManager.setBannerOptions(false);
} else if (KMManager.isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_SYSTEM)){
// Check if predictions needs to be re-enabled per Settings preference