diff --git a/.gitattributes b/.gitattributes index cd9921d963..22ad2cc2a3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,3 +7,4 @@ # EOF # ``` Dockerfile text eol=lf +*.sh text eol=lf diff --git a/.github/workflows/auto-merge-keyman-server-pr.yml b/.github/workflows/auto-merge-keyman-server-pr.yml index 0c920c2650..771fd6ae5e 100644 --- a/.github/workflows/auto-merge-keyman-server-pr.yml +++ b/.github/workflows/auto-merge-keyman-server-pr.yml @@ -1,10 +1,9 @@ # -# Automatically merges pull requests opened by keyman-server -# The initial use of this action is to increment the patch -# version of Keyman with resources/build/increment-version.sh. -# That script creates a PR and then this workflow will be -# triggered to approve the PR (from github-actions account), and -# then automerge it. +# Automatically merges pull requests opened by keyman-server The initial use of +# this action is to increment the patch version of Keyman with +# resources/teamcity/triggers/trigger-release-builds.sh. That script creates a PR and +# then this workflow will be triggered to approve the PR (from github-actions +# account), and then automerge it. # name: Auto Merge PRs from keyman-server on: @@ -17,12 +16,15 @@ jobs: if: ${{ github.repository == 'keymanapp/keyman' && github.actor == 'keyman-server' && startsWith(github.event.pull_request.title, 'auto:') }} steps: - name: auto approve PR from keyman-server - uses: hmarr/auto-approve-action@f0939ea97e9205ef24d872e76833fa908a770363 - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - name: auto merge PR from keyman-server - uses: "pascalgn/automerge-action@7854d3bd607dccdaf0b2c134b699a812c8960213" + shell: bash env: - GITHUB_TOKEN: "${{ secrets.AUTOINC_GITHUB_TOKEN }}" - MERGE_LABELS: "automerge" - MERGE_FORKS: false + GH_TOKEN: "${{ github.token }}" + run: | + gh pr review -R keymanapp/keyman --approve ${{ github.event.pull_request.number }} + - name: mark PR for auto-merge from keyman-server + shell: bash + if: contains(github.event.pull_request.labels.*.name, 'automerge') + env: + GH_TOKEN: "${{ secrets.AUTOINC_GITHUB_TOKEN }}" + run: | + gh pr merge -R keymanapp/keyman --merge --auto ${{ github.event.pull_request.number }} diff --git a/.github/workflows/deb-packaging.yml b/.github/workflows/deb-packaging.yml index a06d7ed3cd..a40fcb7259 100644 --- a/.github/workflows/deb-packaging.yml +++ b/.github/workflows/deb-packaging.yml @@ -86,7 +86,14 @@ jobs: shell: bash run: | THIS_SCRIPT="$GITHUB_WORKSPACE/.github/workflows/deb-packaging.yml" - . "${THIS_SCRIPT%/*}/../../resources/build/build-utils.sh" + if [[ -f "${THIS_SCRIPT%/*}/../../resources/build/builder-basic.inc.sh" ]]; then + . "${THIS_SCRIPT%/*}/../../resources/build/builder-basic.inc.sh" + else + # TODO: remove following block post v19 release (file was renamed in v19 alpha) + if [[ -f "${THIS_SCRIPT%/*}/../../resources/build/build-utils.sh" ]]; then + . "${THIS_SCRIPT%/*}/../../resources/build/build-utils.sh" + fi + fi echo "KEYMAN_VERSION=${KEYMAN_VERSION:-${VERSION}}" >> $GITHUB_OUTPUT - name: Set prerelease tag as output parameter diff --git a/.gitignore b/.gitignore index 6c8fbfbec8..97c28ac83b 100644 --- a/.gitignore +++ b/.gitignore @@ -152,8 +152,8 @@ # Atom/Nuclide compile_flags.txt -# Auto-generated resource script -resources/environment.sh +# Auto-generated resource script for xcode +resources/build/mac/xcode-environment.inc.sh # Copy of the master VERSION.md used for Linux packaging /core/VERSION.md @@ -164,7 +164,7 @@ tsconfig.tsbuildinfo # Windows system files Thumbs.db -# Temporary file for logging scripts in xcode runs, see build-utils.sh for +# Temporary file for logging scripts in xcode runs, see builder-basic.inc.sh for # details /xcodebuild-scripts.log diff --git a/HISTORY.md b/HISTORY.md index d774cd3454..e39d76bd02 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,94 @@ # Keyman Version History +## 19.0.106 alpha 2025-08-27 + +* fix(windows): check if automatic updates off before prompt (#14295) +* refactor(linux): use bash testing framework for packaging tests (#14603) +* maint(resources): use correct version for PR title for history cherry-pick (#14610) +* refactor(common): fix shellcheck warnings (#14580) + +## 19.0.105 alpha 2025-08-25 + +* maint(linux): ignore generate patch directories (#14600) + +## 19.0.104 alpha 2025-08-21 + +* fix(android): Update sentry-android dependency to 8.19.1 for 16 KB page alignment (#14559) +* maint(android): Cleanup builder_describe_outputs for configure action (#14566) +* fix(windows): emit nunit report path correctly and update TeamCity links (#14564) +* maint(common): rename and move node-related script functions into node.inc.sh (#14568) + +## 19.0.103 alpha 2025-08-20 + +* fix(android): Show system OSK when physical keyboard connected on Android API 36 (#14538) +* fix(android): Add "Show On-screen keyboard" preference to display OSK when physical keyboard is connected (#14539) +* fix(android): Add FirstVoices preference to show on-screen keyboard (#14546) +* fix(linux): normalize language tags from keyboard (#14542) +* maint(common): fix running docker on Windows (#14154) +* maint(mac): use mac_ prefix for functions in mac.inc.sh (#14562) +* maint(android): publish symbols to Sentry on release buildLevel (#14490) +* maint(linux): add missing `--help.keyman.com` option (#14571) +* docs(web): improve documentation for SearchSpace and SearchNode (#14555) + +## 19.0.102 alpha 2025-08-19 + +* maint(mac): skip unnecessary network steps when buildLevel is build (#14467) +* maint(common): cleanup and reorganize ci scripts (#14459) +* refactor(linux): cleanup some code in bash completion script (#14543) +* maint(resources): handle build-bot skip correctly (#14551) +* maint(resources): don't fall back to 'build' action (#14552) +* maint(resources): handle unset build platform in trigger-build-bot (#14554) + +## 19.0.101 alpha 2025-08-18 + +* maint(android): Update Android Target API to 35 (#14395) +* fix(android): Convert Keyman app layout to use ConstraintLayout for handling edge-to-edge (#14396) +* fix(android): Update other activities for edge to edge (#14463) +* fix(android): Update Sample, Test, and FirstVoices apps for edge to edge (#14514) +* maint(common): rename and move node-related script functions into node.inc.sh (#14540) + +## 19.0.100 alpha 2025-08-14 + +* maint(resources): add space to test-bot command (#14528) +* fix(web): improve accuracy of types for suggestions & suggestion-generation (#14517) +* refactor(web): move applySuggestionCasing to standalone exportable method (#14518) +* chore(web): convert worker-thread tests to TS (#14510) + +## 19.0.99 alpha 2025-08-14 + +* maint(web): skip unnecessary steps for `build` buildLevel (#14516) + +## 19.0.98 alpha 2025-08-14 + +* maint(resources): specify `keymanapp/keyman` for gh in automerge (#14524) + +## 19.0.97 alpha 2025-08-14 + +* maint(resources): use GH_TOKEN variable for gh calls (#14522) + +## 19.0.96 alpha 2025-08-14 + +* maint(resources): add build-bot commands to increment-version auto PRs (#14504) +* maint(resources): use GH builtin automerge for auto PRs (#14519) + +## 19.0.95 alpha 2025-08-13 + +* fix(web): use actual legacy model for legacy-model support unit tests (#14460) +* chore(common): Update Crowdin strings for Spanish (#14464) +* fix(android): Get default sizes before initializing keyboard (#14472) +* docs(resources): clarify Build-bot usage (#14282) +* maint(resources): build.sh-style commands for build-bot (#14461) +* chore(android): Update keycode test app dependencies (#14474) +* maint(common): update npm modules brace-expansion to 1.1.12, form-data to 4.0.4 (#14479) +* chore(android): Specify Java language version 21 (#14491) +* maint(ios): skip unnecessary network steps when buildLevel is build (#14466) +* maint(common): rename shellHelperFunctions.sh to utils.inc.sh (#14446) +* maint(common): consolidate builder scripts (#14449) +* maint(common): rename and move node-related script functions into node.inc.sh (#14451) +* maint(common): move typescript script functions into typescript.inc.sh (#14452) +* maint(common): reorganize mac/ios build script includes (#14458) +* docs(resources): add note on builder-basic vs builder-full (#14507) + ## 19.0.94 alpha 2025-08-01 * maint(common): use `cpp_std=c++17` in meson project default_options (#14433) @@ -574,6 +663,26 @@ * refactor(windows): rename `TKeymanMutex.MutexOwned` to `TakeOwnership` and add `ReleaseOwnership` (#13168) * chore: increment to alpha 19.0 (#13187) +## 18.0.240 stable 2025-08-27 + +* maint(resources): automatically cherry-pick history updates to master (#14596) +* maint(linux): fix lintian warnings (#14591) +* maint(linux): ignore generate patch directories (#14601) + +## 18.0.239 stable 2025-08-22 + +* docs(linux): clarify requirement of patched ibus for Keyman < 18 (#14113) +* chore(linux): Update debian changelog (#14118) +* fix(windows): add values wucUpdateAvailable and wucNotChecked to TRemoteUpdateCheckResult enum (#14208) +* fix(web): deploy `web/build/publish` folder (#14238) +* fix(ios): restore keyboard scale map for iPad Air 2 (#14306) +* chore(developer): upgrade multer to 2.0.2 (#14417) +* fix(android): cherry-pick getting default sizes before initializing keyboard (#14473) +* fix(android): polyfill globalThis for API 28 devices (#14553) +* fix(android): Update sentry-android dependency to 7.22.6 for 16 KB page alignment (#14560) +* fix(android): Show system OSK when physical keyboard connected (#14547) +* fix(android): Add preference to show on-screen keyboard to Keyman and FirstVoices apps (#14561) + ## 18.0.238 stable 2025-06-04 * fix(developer): ldml: make sure .run() calls compile() for validation (#14071) diff --git a/VERSION.md b/VERSION.md index d0f6206d48..84e9e82913 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.95 \ No newline at end of file +19.0.107 \ No newline at end of file diff --git a/android/KMAPro/build.gradle b/android/KMAPro/build.gradle index c644d44fca..d02f3eeb92 100644 --- a/android/KMAPro/build.gradle +++ b/android/KMAPro/build.gradle @@ -3,19 +3,12 @@ buildscript { repositories { google() mavenCentral() - flatDir { - dirs "kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/" - } } dependencies { classpath 'com.android.tools.build:gradle:8.9.2' // sentry-android-gradle-plugin 2.1.5+ requires AGP 7.0 - classpath 'io.sentry:sentry-android-gradle-plugin:4.6.0' + classpath 'io.sentry:sentry-android-gradle-plugin:5.9.0' classpath 'name.remal:gradle-plugins:1.9.2' - - // From jcenter() which was deprecated August 2024 - // https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/ - classpath 'com.stepstone.stepper:material-stepper:4.3.1@aar' } } diff --git a/android/KMAPro/build.sh b/android/KMAPro/build.sh index fd54215d1c..74fed10588 100755 --- a/android/KMAPro/build.sh +++ b/android/KMAPro/build.sh @@ -3,11 +3,10 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../resources/build/builder.inc.sh" +. "${THIS_SCRIPT%/*}/../../resources/build/builder-full.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE -. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" -. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" +. "$KEYMAN_ROOT/resources/build/utils.inc.sh" . "$KEYMAN_ROOT/resources/build/build-help.inc.sh" . "$KEYMAN_ROOT/resources/build/build-download-resources.sh" @@ -28,8 +27,8 @@ builder_describe "Builds Keyman for Android app." \ "configure" \ "build" \ "test Runs lint and unit tests." \ - "publish Publishes symbols to Sentry and the APK to the Play Store." \ - "--upload-sentry Upload to sentry" + "publish-symbols Publishes symbols to Sentry." \ + "publish-play-store Publishes the APK to the Play Store." # parse before describe_outputs to check debug flags builder_parse "$@" @@ -41,8 +40,12 @@ if builder_is_debug_build; then TEST_FLAGS="-x assembleDebug lintDebug testDebug" fi +KEYBOARD_PACKAGE_ID="sil_euro_latin" +KEYBOARDS_TARGET="android/KMAPro/kMAPro/src/main/assets/${KEYBOARD_PACKAGE_ID}.kmp" +MODEL_PACKAGE_ID="nrc.en.mtnt" +MODELS_TARGET="android/KMAPro/kMAPro/src/main/assets/${MODEL_PACKAGE_ID}.model.kmp" builder_describe_outputs \ - configure /android/KMAPro/kMAPro/libs/keyman-engine.aar \ + configure "/${MODELS_TARGET}" \ build /android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION}.apk #### Build @@ -54,18 +57,6 @@ if builder_is_ci_build; then DAEMON_FLAG=--no-daemon fi -#### Build action definitions #### - -function makeLocalSentryRelease() { - echo "Making a Sentry release for tag $KEYMAN_VERSION_GIT_TAG" - sentry-cli upload-dif -p keyman-android --include-sources - sentry-cli releases -p keyman-android files $KEYMAN_VERSION_GIT_TAG upload-sourcemaps ./ - - echo "Finalizing release tag $KEYMAN_VERSION_GIT_TAG" - sentry-cli releases finalize "$KEYMAN_VERSION_GIT_TAG" -} - - #### Build action definitions #### # Check about cleaning artifact paths @@ -76,13 +67,8 @@ fi if builder_start_action configure; then - KEYBOARD_PACKAGE_ID="sil_euro_latin" - KEYBOARDS_TARGET="$KEYMAN_ROOT/android/KMAPro/kMAPro/src/main/assets/${KEYBOARD_PACKAGE_ID}.kmp" - MODEL_PACKAGE_ID="nrc.en.mtnt" - MODELS_TARGET="$KEYMAN_ROOT/android/KMAPro/kMAPro/src/main/assets/${MODEL_PACKAGE_ID}.model.kmp" - - downloadKeyboardPackage "$KEYBOARD_PACKAGE_ID" "$KEYBOARDS_TARGET" - downloadModelPackage "$MODEL_PACKAGE_ID" "$MODELS_TARGET" + downloadKeyboardPackage "$KEYBOARD_PACKAGE_ID" "${KEYMAN_ROOT}/$KEYBOARDS_TARGET" + downloadModelPackage "$MODEL_PACKAGE_ID" "${KEYMAN_ROOT}/$MODELS_TARGET" builder_finish_action success configure fi @@ -90,18 +76,14 @@ fi if builder_start_action build; then # Copy Keyman Engine for Android - cp "$KEYMAN_ROOT/android/KMEA/app/build/outputs/aar/keyman-engine-${CONFIG}.aar" "$KEYMAN_ROOT/android/KMAPro/kMAPro/libs/keyman-engine.aar" - + cp "${KEYMAN_ROOT}/android/KMEA/app/build/outputs/aar/keyman-engine-${CONFIG}.aar" "${KEYMAN_ROOT}/android/KMAPro/kMAPro/libs/keyman-engine.aar" + # Convert markdown to html for offline help build_help_html android KMAPro/kMAPro/src/main/assets/info echo "BUILD_FLAGS $BUILD_FLAGS" ./gradlew $DAEMON_FLAG clean $BUILD_FLAGS - if builder_has_option --upload-sentry; then - makeLocalSentryRelease - fi - builder_finish_action success build fi @@ -113,12 +95,23 @@ if builder_start_action test; then builder_finish_action success test fi -if builder_start_action publish; then - # Copy Release Notes - generateReleaseNotes +publish_symbols() { + if builder_is_ci_build && builder_is_ci_build_level_release; then + # TODO: what does publishSentry even do? + ./gradlew $DAEMON_FLAG publishSentry + builder_echo "Making a Sentry release for tag $KEYMAN_VERSION_GIT_TAG" + sentry-cli upload-dif -p keyman-android --include-sources + sentry-cli releases -p keyman-android files $KEYMAN_VERSION_GIT_TAG upload-sourcemaps ./ + fi +} - # Publish symbols and Keyman for Android to Play Store - ./gradlew $DAEMON_FLAG publishSentry publishReleaseApk +publish_play_store() { + if builder_is_ci_build && builder_is_ci_build_level_release; then + generateReleaseNotes + # Publish Keyman for Android to Play Store + ./gradlew $DAEMON_FLAG publishReleaseApk + fi +} - builder_finish_action success publish -fi +builder_run_action publish-symbols publish_symbols +builder_run_action publish-play-store publish_play_store diff --git a/android/KMAPro/kMAPro/build.gradle b/android/KMAPro/kMAPro/build.gradle index 864fb36ee9..77ab2fa736 100644 --- a/android/KMAPro/kMAPro/build.gradle +++ b/android/KMAPro/kMAPro/build.gradle @@ -11,8 +11,14 @@ apply from: "$rootPath/version.gradle" String tier = new File('../../TIER.md').getText('UTF-8').trim(); +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + android { - compileSdk 34 + compileSdk 35 namespace="com.tavultesoft.kmapro" // Don't compress kmp files so they can be copied via AssetManager @@ -24,15 +30,10 @@ android { buildConfig = true } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 - } - defaultConfig { applicationId "com.tavultesoft.kmapro" minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 //println "===DUMPING PROPERTIES===" //dumpProperties(project) // Use this to dump all external properties for debugging TeamCity integration @@ -113,6 +114,12 @@ android { disable 'MissingQuantity', 'MissingTranslation' lintConfig file("lint.xml") } + + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + } } // how to configure the sentry android gradle plugin @@ -157,19 +164,17 @@ if (env_keys_json_file != null && file(env_keys_json_file).exists()) { } repositories { - flatDir { - dirs 'libs' - } google() } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.7.0' + implementation 'androidx.constraintlayout:constraintlayout:2.2.1' implementation 'com.google.android.material:material:1.12.0' implementation 'com.stepstone.stepper:material-stepper:4.3.1' - api(name: 'keyman-engine', ext: 'aar') - implementation 'io.sentry:sentry-android:7.8.0' + implementation files('libs/keyman-engine.aar') + implementation 'io.sentry:sentry-android:8.19.1' implementation 'androidx.preference:preference:1.2.1' implementation "com.android.installreferrer:installreferrer:2.2" diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index 2d03311d50..f6acd350da 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -5,10 +5,10 @@ package com.keyman.android; import com.keyman.engine.util.DownloadFileUtils; -import com.tavultesoft.kmapro.AdjustLongpressDelayActivity; import com.tavultesoft.kmapro.BuildConfig; import com.tavultesoft.kmapro.DefaultLanguageResource; import com.tavultesoft.kmapro.KeymanSettingsActivity; +import com.tavultesoft.kmapro.PreferencesManager; import com.keyman.engine.KMManager; import com.keyman.engine.KMManager.KeyboardType; import com.keyman.engine.KMHardwareKeyboardInterpreter; @@ -30,7 +30,6 @@ import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; -import android.view.WindowManager; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -278,6 +277,21 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven // Do nothing } + @Override + public boolean onEvaluateInputViewShown() { + // On Android API 36+, the OSK defaults to not appearing when a physical keyboard is connected. + // If the default implementation returns true, recommend honoring it + // Reference: https://android.googlesource.com/platform/frameworks/base/+/7b739a8%5E%21/ + if (super.onEvaluateInputViewShown()) { + return true; + }; + + Context context = getApplicationContext(); + SharedPreferences prefs = context.getSharedPreferences(PreferencesManager.kma_prefs_name, Context.MODE_PRIVATE); + boolean showOSK = prefs.getBoolean(KeymanSettingsActivity.oskWithPhysicalKeyboardKey, false); + return showOSK; + } + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Determine if Physical keystroke should be passed off diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustKeyboardHeightActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustKeyboardHeightActivity.java index cef9ec33fc..cc23b2d2ed 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustKeyboardHeightActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustKeyboardHeightActivity.java @@ -44,6 +44,9 @@ public class AdjustKeyboardHeightActivity extends BaseActivity { setContentView(R.layout.activity_adjust_keyboard_height); + setupEdgeToEdge(R.id.adjust_keyboard_layout); + setupStatusBarColors(R.color.keyman_blue, android.R.color.white); + Toolbar toolbar = (Toolbar) findViewById(R.id.titlebar); setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/InfoActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/InfoActivity.java index 3f70750118..3cefe9fe7f 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/InfoActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/InfoActivity.java @@ -34,6 +34,7 @@ public class InfoActivity extends BaseActivity { final Context context = this; setContentView(R.layout.activity_info); + setupEdgeToEdge(R.id.info_layout); // Navigation buttons final ImageButton backButton = (ImageButton) findViewById(R.id.back_button); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KMPBrowserActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KMPBrowserActivity.java index 09a8921e7b..07ba2a7074 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KMPBrowserActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KMPBrowserActivity.java @@ -79,6 +79,9 @@ public class KMPBrowserActivity extends BaseActivity { return; } + setupEdgeToEdge(R.id.kmp_browser_layout); + setupStatusBarColors(R.color.complementary_5, android.R.color.white); + webView = (WebView) findViewById(R.id.kmpBrowserWebView); webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); webView.getSettings().setJavaScriptEnabled(true); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsActivity.java index 7113e0a982..bda56856b2 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsActivity.java @@ -5,7 +5,6 @@ import android.os.Bundle; import com.keyman.engine.BaseActivity; import com.keyman.engine.KMManager; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; public class KeymanSettingsActivity extends BaseActivity { @@ -14,6 +13,7 @@ public class KeymanSettingsActivity extends BaseActivity { protected static final String sendCrashReport = "SendCrashReport"; public static final String spacebarTextKey = "SpacebarText"; public static final String hapticFeedbackKey = "HapticFeedback"; + public static final String oskWithPhysicalKeyboardKey = "ShowOSK"; protected KeymanSettingsFragment innerFragment; @@ -22,6 +22,10 @@ public class KeymanSettingsActivity extends BaseActivity { super.onCreate(savedInstanceState); setContentView(R.layout.keyman_settings_layout); + + setupEdgeToEdge(R.id.keyman_settings_layout); + setupStatusBarColors(R.color.keyman_blue, android.R.color.white); + Toolbar toolbar = (Toolbar) findViewById(R.id.keyman_settings_toolbar); toolbar.setTitleTextColor(getResources().getColor(android.R.color.white)); toolbar.setTitle(R.string.keyman_settings); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java index 59ac59e2f8..4629336635 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java @@ -6,6 +6,7 @@ package com.tavultesoft.kmapro; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; import android.provider.Settings; import android.view.inputmethod.InputMethodManager; @@ -20,6 +21,7 @@ import androidx.preference.SwitchPreference; import com.keyman.engine.DisplayLanguages; import com.keyman.engine.KMManager; import com.keyman.engine.data.Dataset; +import com.tavultesoft.kmapro.PreferencesManager; import java.util.HashMap; @@ -157,6 +159,31 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { } }); + SwitchPreference oskWithPhysicalKeyboardPreference = new SwitchPreference(context); + oskWithPhysicalKeyboardPreference.setKey(KeymanSettingsActivity.oskWithPhysicalKeyboardKey); + oskWithPhysicalKeyboardPreference.setTitle(getString(R.string.show_osk)); + oskWithPhysicalKeyboardPreference.setSummary(getString(R.string.show_osk_hint)); + + SharedPreferences prefs = context.getSharedPreferences( + PreferencesManager.kma_prefs_name, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + boolean showOSK = prefs.getBoolean( + KeymanSettingsActivity.oskWithPhysicalKeyboardKey, false); + oskWithPhysicalKeyboardPreference.setDefaultValue(showOSK); + + oskWithPhysicalKeyboardPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (newValue == null) { + return false; + } + + editor.putBoolean(KeymanSettingsActivity.oskWithPhysicalKeyboardKey, (boolean)newValue); + editor.commit(); + return true; + } + }); + SwitchPreference hapticFeedbackPreference = new SwitchPreference(context); hapticFeedbackPreference.setKey(KeymanSettingsActivity.hapticFeedbackKey); hapticFeedbackPreference.setTitle(getString(R.string.haptic_feedback)); @@ -198,6 +225,8 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { screen.addPreference(adjustKeyboardHeight); screen.addPreference(adjustLongpressDelay); + + screen.addPreference(oskWithPhysicalKeyboardPreference); screen.addPreference(spacebarTextPreference); screen.addPreference(hapticFeedbackPreference); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsInstallActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsInstallActivity.java index 71a8f7c355..728a6b2d15 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsInstallActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsInstallActivity.java @@ -7,7 +7,6 @@ import java.util.ArrayList; import java.util.HashMap; import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import android.content.Context; @@ -24,11 +23,12 @@ import android.os.Bundle; import android.widget.SimpleAdapter; import android.widget.TextView; +import com.keyman.engine.BaseActivity; import com.keyman.engine.KMManager; import com.keyman.engine.data.KeyboardController; import com.keyman.engine.util.MapCompat; -public class KeymanSettingsInstallActivity extends AppCompatActivity { +public class KeymanSettingsInstallActivity extends BaseActivity { private static final String TAG = "SettingsInstallActivity"; private static ArrayList> installOptionList = null; private static Typeface titleFont = null; @@ -45,6 +45,8 @@ public class KeymanSettingsInstallActivity extends AppCompatActivity { context = this; setContentView(R.layout.activity_list_layout); + setupEdgeToEdge(R.id.list_toolbar); + final Toolbar toolbar = findViewById(R.id.list_toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java index 96abc83f8a..8db40bb3de 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java @@ -25,10 +25,10 @@ import android.widget.TextView; import androidx.annotation.IdRes; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.Toolbar; +import com.keyman.engine.BaseActivity; import com.keyman.engine.KeyboardPickerActivity; import com.keyman.engine.KMManager; import com.keyman.engine.ModelPickerActivity; @@ -43,7 +43,7 @@ import java.util.HashMap; * Keyman Settings --> Languages Settings --> Language Settings * Displays a list of installed keyboards and some lexical model switches. */ -public final class LanguageSettingsActivity extends AppCompatActivity { +public final class LanguageSettingsActivity extends BaseActivity { private Context context; private static Toolbar toolbar = null; private static ListView listView = null; @@ -66,6 +66,8 @@ public final class LanguageSettingsActivity extends AppCompatActivity { context = this; setContentView(R.layout.language_settings_list_layout); + setupEdgeToEdge(R.id.list_toolbar); + toolbar = (Toolbar) findViewById(R.id.list_toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguagesSettingsActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguagesSettingsActivity.java index 6e21d04f7b..79c845fa6f 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguagesSettingsActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguagesSettingsActivity.java @@ -19,9 +19,9 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import com.keyman.engine.BaseActivity; import com.keyman.engine.data.Dataset; import com.keyman.engine.data.adapters.AdapterFilter; import com.keyman.engine.data.adapters.NestedAdapter; @@ -36,7 +36,7 @@ import java.util.List; * Keyman Settings --> Languages Settings * Displays a list of installed languages and a count of their associated installed keyboards. */ -public final class LanguagesSettingsActivity extends AppCompatActivity { +public final class LanguagesSettingsActivity extends BaseActivity { private Context context; private static Toolbar toolbar = null; @@ -53,6 +53,8 @@ public final class LanguagesSettingsActivity extends AppCompatActivity { context = this; setContentView(R.layout.languages_settings_list_layout); + setupEdgeToEdge(R.id.languages_list_layout); + toolbar = (Toolbar) findViewById(R.id.list_toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index 40b41b6176..b422d7e881 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -67,6 +67,7 @@ import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.widget.Toolbar; import androidx.appcompat.app.AlertDialog; +import androidx.constraintlayout.widget.ConstraintLayout; import android.content.ClipData; import android.content.Context; import android.content.DialogInterface; @@ -85,7 +86,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; import android.provider.Settings; import android.text.Html; @@ -98,8 +98,6 @@ import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import android.view.WindowManager; -import android.webkit.WebView; import android.widget.Button; import android.widget.LinearLayout; import android.widget.SeekBar; @@ -118,6 +116,7 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene private static final String TAG = "MainActivity"; + private ConstraintLayout constraintLayout; private KMTextView textView; private final int minTextSize = 16; private final int maxTextSize = 72; @@ -170,6 +169,10 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene setContentView(R.layout.activity_main); + constraintLayout = (ConstraintLayout)findViewById(R.id.constraintLayout); + setupEdgeToEdge(R.id.constraintLayout); + setupStatusBarColors(android.R.color.white, R.color.neutral_2); + toolbar = (Toolbar) findViewById(R.id.titlebar); setSupportActionBar(toolbar); getSupportActionBar().setTitle(null); @@ -622,10 +625,18 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene if (resourceId > 0) statusBarHeight = getResources().getDimensionPixelSize(resourceId); + // Navigation bar height + int navigationBarHeight = 0; + resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); + if (resourceId > 0) { + navigationBarHeight = getResources().getDimensionPixelSize(resourceId); + } + Point size = KMManager.getWindowSize(context); int screenHeight = size.y; Log.d(TAG, "Main resizeTextView bannerHeight: " + bannerHeight); - textView.setHeight(screenHeight - statusBarHeight - actionBarHeight - bannerHeight - keyboardHeight); + textView.setHeight( + screenHeight - statusBarHeight - actionBarHeight - bannerHeight - keyboardHeight - navigationBarHeight); } private void showInfo() { diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java index ee76265a97..28517ef04a 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java @@ -4,7 +4,6 @@ package com.tavultesoft.kmapro; import android.annotation.SuppressLint; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; @@ -18,6 +17,7 @@ import android.widget.Toast; import com.stepstone.stepper.StepperLayout; import com.stepstone.stepper.VerificationError; +import com.keyman.engine.BaseActivity; import com.keyman.engine.KMManager; import com.keyman.engine.KeyboardEventHandler; import com.keyman.engine.KmpInstallMode; @@ -34,7 +34,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -public class PackageActivity extends AppCompatActivity implements +public class PackageActivity extends BaseActivity implements StepperLayout.StepperListener, WebViewFragment.OnInstallClickedListener, SelectLanguageFragment.OnLanguagesSelectedListener { private final static String TAG = "PackageActivity"; @@ -52,6 +52,7 @@ public class PackageActivity extends AppCompatActivity implements public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_package_installer); + setupEdgeToEdge(R.id.package_installer_layout); KmpInstallMode installMode = KmpInstallMode.Full; String languageID = null; diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PreferencesManager.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PreferencesManager.java new file mode 100644 index 0000000000..73abd79ecc --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PreferencesManager.java @@ -0,0 +1,11 @@ +/** + * Keyman is copyright (C) SIL Global. MIT License. + * + */ +package com.tavultesoft.kmapro; + +public class PreferencesManager { + + // TODO: Separate this from the Keyman Engine preference key name in strings.xml: #13633 + public static final String kma_prefs_name = "KMAPreferences"; +} diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectLanguageActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectLanguageActivity.java index 892ac820cf..ffaf1e28ae 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectLanguageActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectLanguageActivity.java @@ -8,11 +8,11 @@ import android.os.Bundle; import android.view.View; import android.widget.Toast; -import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import com.stepstone.stepper.StepperLayout; import com.stepstone.stepper.VerificationError; +import com.keyman.engine.BaseActivity; import com.keyman.engine.KMManager; import com.keyman.engine.data.Keyboard; import com.keyman.engine.packages.PackageProcessor; @@ -29,7 +29,7 @@ import java.util.List; * Also available during keyboard package installation that involves a language choice. * Displays a list of available language names for the user to add for a given installed packageID/keyboardID. */ -public class SelectLanguageActivity extends AppCompatActivity implements +public class SelectLanguageActivity extends BaseActivity implements StepperLayout.StepperListener, SelectLanguageFragment.OnLanguagesSelectedListener { private final static String TAG = "SelectLanguageActivity"; private File packagePath; @@ -43,6 +43,7 @@ public class SelectLanguageActivity extends AppCompatActivity implements public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_select_language); + setupEdgeToEdge(R.id.select_language_layout); Bundle bundle = getIntent().getExtras(); keyboard = (Keyboard)bundle.getSerializable("keyboard"); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java index 9b05332182..0b6a3ac9a7 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java @@ -16,9 +16,9 @@ import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.TextView; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import com.keyman.engine.BaseActivity; import com.keyman.engine.KMManager; import com.keyman.engine.data.Keyboard; import com.keyman.engine.data.KeyboardController; @@ -33,7 +33,7 @@ import java.util.List; * Keyman Settings --> KeymanInstallActivity --> SelectPackageActivity * Displays a list of installed package ID / keyboard IDs so the user can select a language from the kmp.json */ -public final class SelectPackageActivity extends AppCompatActivity { +public final class SelectPackageActivity extends BaseActivity { private static final String TAG = "SelectPackageActivity"; private static ArrayList> list = null; private static Typeface titleFont = null; @@ -49,6 +49,8 @@ public final class SelectPackageActivity extends AppCompatActivity { context = this; setContentView(R.layout.activity_list_layout); + setupEdgeToEdge(R.id.activity_list_layout); + final Toolbar toolbar = findViewById(R.id.list_toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_keyboard_height.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_keyboard_height.xml index 7a53c88321..0cb7a262d2 100644 --- a/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_keyboard_height.xml +++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_keyboard_height.xml @@ -1,9 +1,11 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> @@ -15,7 +17,7 @@ android:layout_marginStart="@dimen/activity_horizontal_margin" android:text="@string/drag_the_keyboard" android:textSize="@dimen/adjust_keyboard_height_label_textsize" - /> + app:layout_constraintTop_toBottomOf="@id/titlebar" /> + app:layout_constraintTop_toBottomOf="@id/drag_the_keyboard" /> - - - - + diff --git a/android/KMEA/app/src/main/res/layout/activity_list_layout.xml b/android/KMEA/app/src/main/res/layout/activity_list_layout.xml index 51c506fc28..cb1044524b 100644 --- a/android/KMEA/app/src/main/res/layout/activity_list_layout.xml +++ b/android/KMEA/app/src/main/res/layout/activity_list_layout.xml @@ -1,13 +1,21 @@ - - + - + - + diff --git a/android/KMEA/app/src/main/res/layout/language_settings_list_layout.xml b/android/KMEA/app/src/main/res/layout/language_settings_list_layout.xml index 42ae9b1511..84f6f189bb 100644 --- a/android/KMEA/app/src/main/res/layout/language_settings_list_layout.xml +++ b/android/KMEA/app/src/main/res/layout/language_settings_list_layout.xml @@ -1,12 +1,15 @@ - - + + android:layout_above="@+id/modeling_settings_layout" + android:layout_below="@id/list_appbar" + app:layout_constraintTop_toBottomOf="@id/list_appbar"/> - - - - - - - + android:layout_gravity="end|center_vertical" + android:contentDescription="@string/image_button" + android:src="@drawable/ic_add_white" + android:layout_marginEnd="@dimen/fab_margin" + android:layout_marginBottom="@dimen/fab_margin" + app:fabSize="normal" + app:layout_constraintBottom_toTopOf="@+id/modeling_settings_layout" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="1.0"/> + android:orientation="vertical" + app:layout_constraintVertical_bias="1.0" + app:layout_constraintBottom_toBottomOf="parent"> --> - + diff --git a/android/KMEA/app/src/main/res/layout/languages_settings_list_layout.xml b/android/KMEA/app/src/main/res/layout/languages_settings_list_layout.xml index cfd94dc922..052db1cf85 100644 --- a/android/KMEA/app/src/main/res/layout/languages_settings_list_layout.xml +++ b/android/KMEA/app/src/main/res/layout/languages_settings_list_layout.xml @@ -1,31 +1,25 @@ - - + - - - - - + android:layout_below="@+id/list_appbar" + app:layout_constraintTop_toBottomOf="@id/list_appbar" + app:layout_constraintStart_toStartOf="parent"/> + android:layout_marginEnd="@dimen/fab_margin" + android:layout_marginBottom="@dimen/fab_margin" + app:fabSize="normal" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="1.0"/> - - + diff --git a/android/KMEA/app/src/main/res/layout/list_toolbar.xml b/android/KMEA/app/src/main/res/layout/list_toolbar.xml index fe200ce6a2..cd90384196 100644 --- a/android/KMEA/app/src/main/res/layout/list_toolbar.xml +++ b/android/KMEA/app/src/main/res/layout/list_toolbar.xml @@ -7,31 +7,39 @@ android:layout_height="wrap_content" app:elevation="0dp"> - - + app:layout_constraintTop_toTopOf="parent"> - + - - + + + + + diff --git a/android/KMEA/app/src/main/res/layout/titlebar.xml b/android/KMEA/app/src/main/res/layout/titlebar.xml index 64b91a0fee..9166846600 100644 --- a/android/KMEA/app/src/main/res/layout/titlebar.xml +++ b/android/KMEA/app/src/main/res/layout/titlebar.xml @@ -6,7 +6,9 @@ android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_alignParentTop="true" - app:popupTheme="@style/ThemeOverlay.AppCompat.Light"> + app:popupTheme="@style/ThemeOverlay.AppCompat.Light" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent"> + android:scrollbars="vertical" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent"> - + diff --git a/android/Samples/KMSample1/build.sh b/android/Samples/KMSample1/build.sh index 172ef6c5e7..d1d41bc200 100755 --- a/android/Samples/KMSample1/build.sh +++ b/android/Samples/KMSample1/build.sh @@ -4,11 +4,10 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../resources/build/builder.inc.sh" +. "${THIS_SCRIPT%/*}/../../../resources/build/builder-full.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE -. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" -. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" +. "$KEYMAN_ROOT/resources/build/utils.inc.sh" ################################ Main script ################################ @@ -23,7 +22,7 @@ builder_describe "Build KMSample1 app for Android." \ "configure" \ "build" \ "test" \ - ":app KMSample1" + ":app KMSample1" # parse before describe_outputs to check debug flags builder_parse "$@" @@ -39,7 +38,6 @@ fi builder_describe_outputs \ - configure /android/Samples/KMSample1/app/libs/keyman-engine.aar \ build:app /android/Samples/KMSample1/app/build/outputs/apk/$CONFIG/$ARTIFACT diff --git a/android/Samples/KMSample2/app/build.gradle b/android/Samples/KMSample2/app/build.gradle index cd2f4d6225..a148a7ab19 100644 --- a/android/Samples/KMSample2/app/build.gradle +++ b/android/Samples/KMSample2/app/build.gradle @@ -2,8 +2,14 @@ plugins { id 'com.android.application' } +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + android { - compileSdk 34 + compileSdk 35 namespace="com.keyman.kmsample2" // Don't compress kmp files so they can be copied via AssetManager @@ -14,7 +20,7 @@ android { defaultConfig { applicationId "com.keyman.kmsample2" minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } @@ -24,19 +30,23 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + } } repositories { - flatDir { - dirs 'libs' - } google() } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.7.0' + implementation 'androidx.constraintlayout:constraintlayout:2.2.1' implementation 'com.google.android.material:material:1.12.0' - api (name:'keyman-engine', ext:'aar') + implementation files('libs/keyman-engine.aar') implementation 'androidx.preference:preference:1.2.1' } diff --git a/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/MainActivity.java b/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/MainActivity.java index 4f9fa0a45f..6099997520 100644 --- a/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/MainActivity.java +++ b/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/MainActivity.java @@ -1,6 +1,5 @@ package com.keyman.kmsample2; -import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.content.Intent; import android.provider.Settings; @@ -11,13 +10,20 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.Button; -public class MainActivity extends AppCompatActivity { +import com.keyman.engine.BaseActivity; + +public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { setTheme(R.style.AppTheme); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + setupEdgeToEdge(R.id.constraintLayout); + setupStatusBarColors( // Inset colors for Android API < 35 + android.R.color.black, // Color for status bar on top + android.R.color.white // Color for navigation bar on bottom + ); Button button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(new View.OnClickListener() { diff --git a/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/SystemKeyboard.java b/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/SystemKeyboard.java index 438ed237db..f2c947ff42 100644 --- a/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/SystemKeyboard.java +++ b/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/SystemKeyboard.java @@ -215,6 +215,20 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven // Handle Keyman keyboard dismissed event here if needed } + @Override + public boolean onEvaluateInputViewShown() { + // On Android API 36+, the OSK defaults to not appearing when a physical keyboard is connected. + // If the default implementation returns true, recommend honoring it + // Reference: https://android.googlesource.com/platform/frameworks/base/+/7b739a8%5E%21/ + if (super.onEvaluateInputViewShown()) { + return true; + }; + + // TODO: Implement IME setting similar to Gboard "Show on-screen keyboard" with physical keyboard + // (default false) + return true; + } + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { diff --git a/android/Samples/KMSample2/app/src/main/res/layout/activity_main.xml b/android/Samples/KMSample2/app/src/main/res/layout/activity_main.xml index 349c927903..f4e9e590a9 100644 --- a/android/Samples/KMSample2/app/src/main/res/layout/activity_main.xml +++ b/android/Samples/KMSample2/app/src/main/res/layout/activity_main.xml @@ -1,31 +1,50 @@ - + + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingBottom="@dimen/activity_vertical_margin" + tools:context=".MainActivity"> - + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/description" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" />