Challenges with multiple Android keyboards in Keyman Engine 12 and 13, font trouble in KME 14

I see that the 14 betas of Keyman Engine for Android use a new keyboard object and take a KMP file instead of a JS file. I love that idea (especially including the docs for my KB), and would like to implement it as I update my Android app from Engine 11.

I tried embedding the keyman-engine.aar 14.0.181 file in my android app, putting the KMPs in assets, and re-coding to use the Keyboard object as shown in KMsample2, but the new com.tavultesoft.kmea.data.Keyboard object in SystemKeyboard.java only expects one parameter (not 11).

Is there something that I’m missing, or is this not even ready for testing?

Edit: This initial problem has been solved, more problems described in the last post.

~Matthew

@darcy can you take a look at this?

Hi @Matthew_Lee

We’re still a few weeks away before Keyman 14 goes to beta.
In the meantime, you can refer to the latest keyman-engine-android-14.0.182.zip at https://downloads.keyman.com/android/alpha/14.0.182/keyman-engine-android-14.0.182.zip

Can you verify you’re looking at a current 14.0 version of KMSample2? The KMSample2 project should have SystemKeyboard.java with the following:

  @Override
  public void onCreate() {
    super.onCreate();
    KMManager.setDebugMode(true);
    KMManager.addKeyboardEventListener(this);
    KMManager.initialize(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_SYSTEM);
    interpreter = new KMHardwareKeyboardInterpreter(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_SYSTEM);

    // Add a custom keyboard
    Keyboard kbInfo = new Keyboard(
      "basic_kbdtam99", // Package ID - filename of the .kmp file
      "basic_kbdtam99", // Keyboard ID
      "Tamil 99 Basic", // Keyboard Name
      "ta",             // Language ID
      "Tamil",          // Language Name
      "1.0",            // Keyboard Version
      null,             // URL to help documentation if available
      "",               // URL to latest .kmp file
      true,             // Boolean to show this is a new keyboard in the keyboard picker

      // Font information of the .ttf font to use in KMSample2 (for example "aava1.ttf").
      // basic_kbdtam99 doesn't include a font. Can set blank "" or KMManager.KMDefault_KeyboardFont
      // KMEA will use the font for the OSK, but the Android device determines the system font used for keyboard output
      KMManager.KMDefault_KeyboardFont,  // Font for KMSample2
      KMManager.KMDefault_KeyboardFont); // Font for OSK
    KMManager.addKeyboard(this, kbInfo);

    // Add a dictionary
    HashMap<String, String>lexicalModelInfo = new HashMap<String, String>();
    lexicalModelInfo.put(KMManager.KMKey_PackageID, "example.ta.wordlist");
    lexicalModelInfo.put(KMManager.KMKey_LanguageID, "ta");
    lexicalModelInfo.put(KMManager.KMKey_LexicalModelID, "example.ta.wordlist");
    lexicalModelInfo.put(KMManager.KMKey_LexicalModelVersion, "1.0");
    KMManager.addLexicalModel(this, lexicalModelInfo);
    KMManager.registerAssociatedLexicalModel("ta");
  }

Yes, I see that the kmsample2 with version 13 uses hashmap, and the kmsample2 with version 14 uses the keyboard object.
My app currently uses the 13-style code (hashmap), but I was attempting an update following the pattern you just showed.

When I put in the km14 aar, and import the kmea Keyboard object, my linter throws an error on this code, telling me that the Keyboard constructor only accepts one argument. Unless I’m misunderstanding something (this is possible), this leads me to believe that the KM 14 .aars still have an old version of com.tavultesoft.kmea.data.Keyboard; .

hmm, is your project up to date on GitHub? I could take a look tomorrow.
I tried to rebuild the kmsampl2 project from the archive, and note I need to remove references to version.gradle.

Did you also add this to your build.gradle? (from KMSample2)

    // Don't compress kmp files so they can be copied via AssetManager
    aaptOptions {
        noCompress "kmp"
    }

We’ll be trying to update the relevant help.keyman.com docs in the upcoming weeks

Yes, I noticed the compression tweak. I’m trying again, and it might work. I think I just needed to run a gradle sync again to let AS know I had changed out the keyman-engine.aar file.

Upgrading from Keyman Engine 11, I was surprised to find that KeymanEngines 12 and 13 for Android introduced bugs when adding more than one keyboard to the engine. KeymanEngine 14 Alpha works for me except the font, but I don’t want to use an alpha in production yet.

Ok, so I created a minimal test project for you from KMSample2 to be able to compare various results.


The readme.md explains it all.

@Darcy, please work through my test cases to fix the stable KM engine 13 or help me to correct my code. I had to revert to KME 11 in my Android App until these are fixed.

Wow, thanks! For those that read this later, Darcy has made edits in my code to fix the problems I had with KME 13 and 14. I can now go fix the “real” app code.

In KM 13, he removed the setKeyboard from onKeyboardLoaded. Since this was included in KMSample2, I thought it was setting the “default” keyboard so that we didn’t end up with EuroLatin, but it runs on every keyboard load. If I understand this now, that probably means that this line was already unnecessary in KMsample2:

In KM14, he set the font name to the font included in the package. This works, but @darcy, I still don’t understand the difference between the 2 fonts defined in the keyboard. If one is OSK, where does the other one show up?

Also, @darcy, why do I still get this error in my log every time I change keyboards on both projects, even when it seems to work?
“D/KMKeyboard: KMW JS Log: Line 638, file:///data/user/0/com.keyman.kmsample2/app_data/keyman.js:No keyboard stubs exist - cannot initialize keyboard!”

This is a known error that you can ignore. Tracked at https://github.com/keymanapp/keyman/issues/664

The second font is used to set the font for input fields (some keyboards use a special OSK font to ‘undo’ complex shaping etc for presentation (e.g. multiple diacritics on a single key would result in two dotted circles in some cases; see for example my blog). As we cannot install fonts globally on Android, it is of somewhat limited use at present here. A future improvement may allow us to provide these fonts to apps that are Keyman-aware.