From b04e28a43824ecd48e8c4bd4215c46bea9cf72e8 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 13 Jul 2026 18:44:32 +0200 Subject: [PATCH 1/2] chore(android): log legacy cloud keyboards This adds a Sentry log if a user is still using legacy cloud keyboards. We do this so that we will learn if there are still users out there or if we can remove the code that deals with those keyboards. Test-bot: skip --- .../java/com/keyman/engine/data/Keyboard.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/data/Keyboard.java b/android/KMEA/app/src/main/java/com/keyman/engine/data/Keyboard.java index 844959fb54..c0a275bbef 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/data/Keyboard.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/data/Keyboard.java @@ -49,6 +49,9 @@ public class Keyboard extends LanguageResource implements Serializable { */ public Keyboard(JSONObject installedObj) { this.fromJSON(installedObj); + if (!FileUtils.hasFontExtension(this.font)) { + logLegacyKeyboard(this.font); + } } /** @@ -79,6 +82,10 @@ public class Keyboard extends LanguageResource implements Serializable { this.helpLink = keyboardJSON.optString(KMManager.KMKey_CustomHelpLink, KMString.format(HELP_URL_FORMATSTR, HELP_URL_HOST, this.resourceID, this.version)); + + if (!FileUtils.hasFontExtension(this.font)) { + logLegacyKeyboard(this.font); + } } catch (JSONException e) { KMLog.LogException(TAG, "Keyboard exception parsing JSON: ", e); } @@ -96,7 +103,11 @@ public class Keyboard extends LanguageResource implements Serializable { this.isNewKeyboard = isNewKeyboard; this.font = (font != null) ? font : ""; this.oskFont = (oskFont != null) ? oskFont : ""; - } + + if (!FileUtils.hasFontExtension(this.font)) { + logLegacyKeyboard(this.font); + } + } public Keyboard(Keyboard k) { super(k.getPackageID(), k.getKeyboardID(), k.getKeyboardName(), @@ -108,6 +119,23 @@ public class Keyboard extends LanguageResource implements Serializable { this.displayName = k.getDisplayName(); } + private void logLegacyKeyboard(String font) { + if (font == null || font.isEmpty()) { + return; + } + try { + // Create a Sentry log entry if there are still users out there that use + // legacy cloud keyboard. See KMKeyboard.makeFontObject(). + JSONObject fontObj = new JSONObject(font); + Object obj = fontObj.get(KMManager.KMKey_FontFiles); + if (obj instanceof String || obj instanceof JSONArray) { + KMLog.LogInfo(TAG, "Constructing legacy keyboard: " + this.packageID + "/" + this.resourceID); + } + } catch (JSONException e) { + // Not a JSON object, so it's not a legacy keyboard. + } + } + public String getKeyboardID() { return getResourceID(); } public String getKeyboardName() { return getResourceName(); } From 9bdfe0eaa9cea0bc09b0733e4f427a56ebe0843f Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 14 Jul 2026 16:48:46 +0200 Subject: [PATCH 2/2] chore(android): address code review comments Legacy cloud installed keyboards don't have a package, so we can check for `KMDefault_UndefinedPackageID` to identify them. --- .../java/com/keyman/engine/data/Keyboard.java | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/data/Keyboard.java b/android/KMEA/app/src/main/java/com/keyman/engine/data/Keyboard.java index c0a275bbef..896fb23e96 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/data/Keyboard.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/data/Keyboard.java @@ -49,9 +49,7 @@ public class Keyboard extends LanguageResource implements Serializable { */ public Keyboard(JSONObject installedObj) { this.fromJSON(installedObj); - if (!FileUtils.hasFontExtension(this.font)) { - logLegacyKeyboard(this.font); - } + logIfLegacyKeyboard(); } /** @@ -83,9 +81,7 @@ public class Keyboard extends LanguageResource implements Serializable { this.helpLink = keyboardJSON.optString(KMManager.KMKey_CustomHelpLink, KMString.format(HELP_URL_FORMATSTR, HELP_URL_HOST, this.resourceID, this.version)); - if (!FileUtils.hasFontExtension(this.font)) { - logLegacyKeyboard(this.font); - } + logIfLegacyKeyboard(); } catch (JSONException e) { KMLog.LogException(TAG, "Keyboard exception parsing JSON: ", e); } @@ -104,10 +100,8 @@ public class Keyboard extends LanguageResource implements Serializable { this.font = (font != null) ? font : ""; this.oskFont = (oskFont != null) ? oskFont : ""; - if (!FileUtils.hasFontExtension(this.font)) { - logLegacyKeyboard(this.font); - } - } + logIfLegacyKeyboard(); + } public Keyboard(Keyboard k) { super(k.getPackageID(), k.getKeyboardID(), k.getKeyboardName(), @@ -119,20 +113,9 @@ public class Keyboard extends LanguageResource implements Serializable { this.displayName = k.getDisplayName(); } - private void logLegacyKeyboard(String font) { - if (font == null || font.isEmpty()) { - return; - } - try { - // Create a Sentry log entry if there are still users out there that use - // legacy cloud keyboard. See KMKeyboard.makeFontObject(). - JSONObject fontObj = new JSONObject(font); - Object obj = fontObj.get(KMManager.KMKey_FontFiles); - if (obj instanceof String || obj instanceof JSONArray) { - KMLog.LogInfo(TAG, "Constructing legacy keyboard: " + this.packageID + "/" + this.resourceID); - } - } catch (JSONException e) { - // Not a JSON object, so it's not a legacy keyboard. + private void logIfLegacyKeyboard() { + if (this.packageID.equals(KMManager.KMDefault_UndefinedPackageID)) { + KMLog.LogInfo(TAG, "Constructing legacy keyboard: " + this.resourceID); } }