diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index a1bb728f64..269031b13e 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -18,6 +18,9 @@ body:
You may also wish to discuss your bug report with the Keyman community at:
https://community.software.sil.org/c/keyman
+ Are you using Linux and fcitx5? If so, please create issues at:
+ https://github.com/fcitx/fcitx5-keyman/issues/new/choose
+
- type: textarea
id: description
attributes:
diff --git a/HISTORY.md b/HISTORY.md
index 9de791f041..402bffa7e3 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,5 +1,22 @@
# Keyman Version History
+## 19.0.13 alpha 2025-03-12
+
+* feat(windows): hard code key cap colour (#13444)
+
+## 19.0.12 alpha 2025-03-04
+
+* chore: remove legacy IIS setup notes (#13403)
+
+## 19.0.11 alpha 2025-03-03
+
+* chore(linux): Update debian changelog (#13347)
+* fix(common): improve resilience of build script trigger (#13402)
+
+## 19.0.10 alpha 2025-03-01
+
+* chore: merge beta into master B18S2 (#13391)
+
## 19.0.9 alpha 2025-02-27
* docs: move node.js before Emscripten (#13366)
@@ -42,6 +59,166 @@
* refactor(windows): rename `TKeymanMutex.MutexOwned` to `TakeOwnership` and add `ReleaseOwnership` (#13168)
* chore: increment to alpha 19.0 (#13187)
+## 18.0.214 beta 2025-03-13
+
+* fix(mac): change text in privacy alert for macOS 13.0 and later (#13480)
+* docs(mac): update troubleshooting page for macOS security (#13476)
+* fix(core): unalign `usetCount` and `rangeCount` (#13450)
+* fix(developer): strip markers when generating KVK from LDML (#13479)
+
+## 18.0.213 beta 2025-03-12
+
+* docs(developer): fix typos in readme and add link (#13414)
+* fix(developer): add folder text to Error_FileDoesNotExist message (#13457)
+* fix(developer): load Keyman Developer options in Server before use (#13459)
+* chore(core): add `clean` actions for `:mac` and `:win` targets (#13460)
+* chore(common): update langtags.json to 2025-02-18 release (#13461)
+* fix(developer): use '-' as placeholder for temp project name in cmdline (#13462)
+* chore: handle failure to retrieve GitHub PR status in build triggers (#13474)
+
+## 18.0.212 beta 2025-03-11
+
+* fix(oem/fv/android): Avoid resetting keyboard index (#13449)
+* fix(android/engine): Ignore key errors if user switched to another IME (#13466)
+* fix(android): Cache inputType to determine external keyboard handling (#13475)
+
+## 18.0.211 beta 2025-03-10
+
+* feat(windows): hide update header if no updates are available (#13442)
+* fix(ios): suppress Get Started dialog when closing help page (#13422)
+* docs(ios): update minimum supported ios version (#13452)
+
+## 18.0.210 beta 2025-03-07
+
+* chore(common): Add crowdin localization for Vietnamese (#13322)
+* chore(linux): add link to fcitx5 issues to bug issue template (#13451)
+
+## 18.0.209 beta 2025-03-06
+
+* fix(common): fail builds with low test coverage for all typescript projects (#13418)
+* fix(windows): Check for updates registry value stored under the one Key (#13413)
+* fix(windows): remove online update deadcode (#13421)
+
+## 18.0.208 beta 2025-03-05
+
+* fix(windows): Check registry report usage value in setup process (#13215)
+* fix(android): Don't report missing kmp.json (#13411)
+
+## 18.0.207 beta 2025-03-04
+
+* fix(common): improve resilience of build script trigger (#13407)
+* fix(mac): improve compliance checking (#13337)
+* chore(common): add unit test for nul and context() in context part of rule (#13412)
+
+## 18.0.206 beta 2025-03-03
+
+* fix(android): Control when system keyboard Keyboard Picker clears activity stack (#13313)
+* docs(android): document control flag for system keyboard picker and task (#13373)
+
+## 18.0.205 beta 2025-03-02
+
+* chore(linux): Update debian changelog (#13346)
+
+## 18.0.204 beta 2025-03-01
+
+* chore(windows): ensure dependencies for keyman32 exclude core:wasm (#13379)
+
+## 18.0.203 beta 2025-02-28
+
+* feat(windows): keyman configuration icon refresh (#13294)
+* fix(windows): if kmshell is "silent" don't start a Keyman update (#13330)
+* chore(windows): Update crowdin strings for Khmer (#13364)
+* docs: clean up links in builder.md (#13328)
+* chore: add build.sh edit action for Delphi projects (#13327)
+* fix(developer): handle line breaks in debugger correctly (#13334)
+* fix(developer): use U+0001 for deadkey markers in the debugger (#13336)
+* feat(developer): use .kps folder as initial dir for Add Files (#13324)
+* fix(developer): verify `context(n)` offsets are valid in kmcmplib (#13308)
+* chore(core): add unit tests to validate `nul` with `index` and `context` (#13311)
+* fix(core): include `nul` in context offset calculations in kmx processor (#13314)
+* fix(developer): include `nul` in offset calculations for kmw v10 compiler (#13326)
+
+## 18.0.202 beta 2025-02-27
+
+* fix(android): Direct user to switch system IME when WebView fails (#13352)
+* fix(android): Filter out SocketTimeoutExceptions (#13353)
+* refactor(linux): extract method for setting up mocks in tests (#13355)
+* chore(linux): update to current Debian policy version (#13362)
+* fix(developer): prevent double action of editor hotkeys in debugger (#13345)
+* fix(linux): ignore DBusException during install and uninstall (#13356)
+* fix(linux): ignore exception when fcitx5-configtool is not found (#13363)
+* fix(developer): prevent simultaneous opening of the same project by two processes (#13341)
+* chore: add a workflow to automatically close linked issues (#13369)
+
+## 18.0.201 beta 2025-02-26
+
+* fix(web): prevent cookie-default behavior from mangling engine init (#13331)
+* chore(linux): adjust to renamed xdg module (#13354)
+
+## 18.0.200 beta 2025-02-25
+
+* fix(web): properly support workerless use of Web engine (#13290)
+* fix(web): reconnect, patch up engine/main headless unit tests (#13291)
+* change(ios): re-order host page script load so Sentry can report script load failures (#13332)
+* chore(linux): Update to new Debian policy version (#13325)
+
+## 18.0.199 beta 2025-02-24
+
+* fix(windows): Update Greek Polytonic for keyboard help (#13323)
+
+## 18.0.198 beta 2025-02-21
+
+* fix(android): Update system keyboard height consistently (#13273)
+
+## 18.0.197 beta 2025-02-20
+
+* fix(linux): address compiling with ICU 76 (#13285)
+
+## 18.0.196 beta 2025-02-19
+
+* fix(windows): remove sentry report on firstrun in idle state (#13266)
+* fix(android): Correct the scope of `tier` in build.gradle (#13268)
+* chore(common): Update crowdin strings for Polytonic Greek (#13277)
+* fix(web): provide informative error + message when loading UI without the engine (#13269)
+* fix(developer): Use 'desktop' for target in OSK fill temp keyboard (#13271)
+* fix(linux): add missing dependency for uploading to llso (#13279)
+* refactor(linux): re-enable integration tests (#13234)
+
+## 18.0.195 beta 2025-02-18
+
+* docs(web): use promise-chaining in manual-control example (#13272)
+
+## 18.0.194 beta 2025-02-17
+
+* fix(android): Use TIER.md to determine Play Store tier (#13259)
+* fix(android): prevent update-checks from crashing system keyboard and app if `DownloadManager` is disabled (#13218)
+* feat(linux): add `--remote-debug` flag to `run-tests.sh` script (#13233)
+* chore(linux): improve output when running tests (#13247)
+* refactor(linux): cleanup code of test fixture (#13248)
+
+## 18.0.193 beta 2025-02-14
+
+* chore(developer): add INFO messages for `kmc copy` and `kmc generate` (#13200)
+* fix(android): Remove sendOptionsToKeyboard function from Engine API (#13219)
+* docs(android): Document removing sendOptionsToKeyboard API (#13220)
+* chore(ios): increase minimum ios version to 15 (#13201)
+* fix(android): Catch WebView exceptions and prompt user to install WebView (#13140)
+* chore(common): Update crowdin strings for Mon (#13241)
+* chore(ios,windows): Update Crowdin strings for Czech (#13242)
+* change(web): drop 'dom' unit test concurrency when run in CI mode (#13141)
+* chore(web): ensure /web/build.sh clean triggers all predictive-text child actions (#13158)
+* chore(web): fix coverage-reporting artifact (#13196)
+
+## 18.0.192 beta 2025-02-14
+
+* chore(common): Fix 17.0.335 tier in HISTORY.md (#13213)
+* docs(linux): update what's new for 18.0 (#13207)
+* chore(linux): additional code cleanup after Focal removal (#13206)
+* docs(windows): update keyman for windows 18.0 whats-new (#13211)
+* chore: undo master merge (#13238)
+* change(ios): prevent memory leaks from keyboard-related notification observers (#13129)
+* change(ios): mitigate keyboard input-view memory leak by force-discarding WebView (#13169)
+
## 18.0.191 beta 2025-02-12
* feat(windows): handle a hard windows reset occurring while downloading updated keyman files (#13128)
diff --git a/VERSION.md b/VERSION.md
index 0394531a29..431adb7b69 100644
--- a/VERSION.md
+++ b/VERSION.md
@@ -1 +1 @@
-19.0.10
\ No newline at end of file
+19.0.14
diff --git a/android/KMAPro/kMAPro/build.gradle b/android/KMAPro/kMAPro/build.gradle
index 11ec4efd2d..768d98d933 100644
--- a/android/KMAPro/kMAPro/build.gradle
+++ b/android/KMAPro/kMAPro/build.gradle
@@ -9,6 +9,8 @@ plugins {
ext.rootPath = '../../'
apply from: "$rootPath/version.gradle"
+String tier = new File('../../TIER.md').getText('UTF-8').trim();
+
android {
compileSdk 34
namespace="com.tavultesoft.kmapro"
@@ -75,7 +77,7 @@ android {
// - PR builds also have "-test-1234" suffix (where 1234 is PR#)
// Gradle sync will nullify these values, so have a fallback
String appSuffix = ''
- String tag = VERSION_TAG ? VERSION_TAG : '-' + new File('../../TIER.md').getText('UTF-8');
+ String tag = VERSION_TAG ? VERSION_TAG : '-' + tier;
if (tag.startsWithAny("-beta", "beta")) {
appSuffix = ' Beta';
} else if (tag.startsWithAny("-alpha", "alpha")) {
@@ -127,7 +129,7 @@ if (env_keys_json_file != null && file(env_keys_json_file).exists()) {
// Deactivate lower conflicting version APKs
resolutionStrategy.set(com.github.triplet.gradle.androidpublisher.ResolutionStrategy.IGNORE)
- switch (System.env.TIER) {
+ switch (tier) {
case 'beta':
track.set("beta")
println "TIER set to beta"
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 5ca3de5807..d1965f41b4 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
@@ -4,6 +4,7 @@
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;
@@ -44,6 +45,7 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
private static View inputView = null;
private static ExtractedText exText = null;
private KMHardwareKeyboardInterpreter interpreter = null;
+ private int inputType = InputType.TYPE_NULL;
private int lastOrientation = Configuration.ORIENTATION_UNDEFINED;
private static final String TAG = "SystemKeyboard";
@@ -84,7 +86,12 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
boolean mayHaveHapticFeedback = prefs.getBoolean(KeymanSettingsActivity.hapticFeedbackKey, false);
KMManager.setHapticFeedback(mayHaveHapticFeedback);
- KMManager.executeResourceUpdate(this);
+ // Checking for updates should never be allowed to crash the keyboard.
+ // Just silently fail if this occurs.
+ if(DownloadFileUtils.getDownloadManager(this) != null) {
+ // Will try to emit a toast if it fails - i.e., is not silent.
+ KMManager.executeResourceUpdate(this);
+ }
}
@Override
@@ -149,18 +156,9 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
KMManager.onStartInput(attribute, restarting);
KMManager.resetContext(KeyboardType.KEYBOARD_TYPE_SYSTEM);
- // This method (likely) includes the IME equivalent to `onResume` for `Activity`-based classes,
- // making it an important time to detect orientation changes.
Context appContext = getApplicationContext();
- int newOrientation = KMManager.getOrientation(appContext);
- if(newOrientation != lastOrientation) {
- lastOrientation = newOrientation;
- Configuration newConfig = this.getResources().getConfiguration();
- KMManager.onConfigurationChanged(newConfig);
- }
-
// Temporarily disable predictions on certain fields (e.g. hidden password field or numeric)
- int inputType = attribute.inputType;
+ inputType = attribute.inputType;
KMManager.setMayPredictOverride(inputType);
if (KMManager.getMayPredictOverride()) {
KMManager.setBannerOptions(false);
@@ -207,6 +205,9 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
public void onStartInputView(EditorInfo attribute, boolean restarting) {
super.onStartInputView(attribute, restarting);
setInputView(onCreateInputView());
+
+ // Update the input type
+ inputType = attribute.inputType;
}
@Override
@@ -228,6 +229,16 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
public void onComputeInsets(InputMethodService.Insets outInsets) {
super.onComputeInsets(outInsets);
+ // This method (likely) includes the IME equivalent to `onResume` for `Activity`-based classes,
+ // making it an important time to detect orientation changes.
+ Context appContext = getApplicationContext();
+ int newOrientation = KMManager.getOrientation(appContext);
+ if(newOrientation != lastOrientation) {
+ lastOrientation = newOrientation;
+ Configuration newConfig = this.getResources().getConfiguration();
+ KMManager.onConfigurationChanged(newConfig);
+ }
+
// We should extend the touchable region so that Keyman sub keys menu can receive touch events outside the keyboard frame
Point size = KMManager.getWindowSize(getApplicationContext());
@@ -250,8 +261,6 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
if (exText != null)
exText = null;
}
- // Initialize keyboard options
- KMManager.sendOptionsToKeyboard();
}
@Override
@@ -271,6 +280,11 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
+ // Determine if Physical keystroke should be passed off
+ if (inputType == InputType.TYPE_NULL) {
+ return false; // Revert to default handling
+ }
+
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java
index e79cb917ff..596c247d09 100644
--- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java
+++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java
@@ -133,7 +133,6 @@ public class AdjustLongpressDelayActivity extends BaseActivity {
// Store the longpress delay as a reference
// and then update KeymanWeb with the longpress delay
KMManager.setLongpressDelay(currentDelayTimeMS);
- KMManager.sendOptionsToKeyboard();
super.onBackPressed();
}
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 4410761e6d..e66d5e9ebc 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
@@ -11,6 +11,7 @@ import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.util.AndroidRuntimeException;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -70,7 +71,13 @@ public class KMPBrowserActivity extends BaseActivity {
}
}
- setContentView(R.layout.activity_kmp_browser);
+ try {
+ setContentView(R.layout.activity_kmp_browser);
+ } catch (AndroidRuntimeException e) {
+ // WebView not enabled
+ finish();
+ return;
+ }
webView = (WebView) findViewById(R.id.kmpBrowserWebView);
webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
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 7e6dcbe5b1..7113e0a982 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
@@ -3,6 +3,7 @@ package com.tavultesoft.kmapro;
import android.os.Bundle;
import com.keyman.engine.BaseActivity;
+import com.keyman.engine.KMManager;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
@@ -32,6 +33,9 @@ public class KeymanSettingsActivity extends BaseActivity {
}
innerFragment = (KeymanSettingsFragment) getSupportFragmentManager().findFragmentById(R.id.keyman_settings_fragment);
+
+ // For Keyman sites, disable keyboard picker task flag so keyboard picker doesn't dismiss Keyman app
+ KMManager.dontCloseParentAppOnShowKeyboardPicker();
}
@Override
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 908d2f4538..f5a3c63cb9 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
@@ -43,7 +43,9 @@ import com.keyman.android.DownloadIntentService;
import com.keyman.engine.util.KMLog;
import com.keyman.engine.util.KMPLink;
import com.keyman.engine.util.KMString;
+import com.keyman.engine.util.WebViewUtils;
import com.keyman.engine.util.WebViewUtils.EngineWebViewVersionStatus;
+import com.keyman.engine.util.WebViewUtils.SystemWebViewStatus;
import android.Manifest;
import android.app.ProgressDialog;
@@ -153,7 +155,9 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
KMManager.setDebugMode(true);
}
+ // Verify WebView installed and enabled before attempting to initialize KMManager
KMManager.initialize(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_INAPP);
+
KMManager.executeResourceUpdate(this);
DefaultLanguageResource.install(context);
@@ -181,8 +185,11 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
textView.setTextSize((float) textSize);
textView.setSelection(textView.getText().length());
- // Use in-app keyboard WebView to check the Chrome version
- checkChromeVersion(KMManager.getKMKeyboard(KeyboardType.KEYBOARD_TYPE_INAPP));
+ // Check WebView enabled and Chrome version
+ SystemWebViewStatus webViewStatus = WebViewUtils.getSystemWebViewStatus(context);
+ EngineWebViewVersionStatus chromeStatus = KMManager.getEngineWebViewVersionStatus();
+ updateWebViewIfNeeded(chromeStatus, webViewStatus);
+
CheckInstallReferrer.checkGooglePlayInstallReferrer(this, context);
checkGetStarted();
}
@@ -240,6 +247,9 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
KMManager.onResume();
KMManager.hideSystemKeyboard();
+ // Reset keyboard picker Activity Task flag
+ KMManager.closeParentAppOnShowKeyboardPicker();
+
// onConfigurationChanged() only triggers when device is rotated while app is in foreground
// This handles when device is rotated while app is in background
// using KMManager.getOrientation() since getConfiguration().orientation is unreliable #10241
@@ -475,8 +485,7 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
@Override
public void onKeyboardLoaded(KeyboardType keyboardType) {
- // Initialize keyboard options
- KMManager.sendOptionsToKeyboard();
+ // Do nothing
}
@Override
@@ -770,39 +779,114 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
KMManager.setHapticFeedback(mayHaveHapticFeedback);
}
- private void checkChromeVersion(WebView webView) {
- if (KMManager.getEngineWebViewVersionStatus() != EngineWebViewVersionStatus.FULL) {
- LinearLayout updateChromeLayout = (LinearLayout) findViewById(R.id.updateChromeLayout);
- updateChromeLayout.setVisibility(View.VISIBLE);
-
- Button updateChromeButton = (Button)findViewById(R.id.updateChromeButton);
- updateChromeButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- // Launch PlayStore to update Chrome
- try {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.android.chrome"));
- if (intent.resolveActivity(getPackageManager()) != null) {
- startActivity(intent);
- } else {
- intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.android.chrome"));
- if (intent.resolveActivity(getPackageManager()) != null) {
- startActivity(intent);
- } else {
- Toast.makeText(getApplicationContext(), getString(R.string.unable_to_open_browser), Toast.LENGTH_SHORT).show();
- }
- }
- } catch (android.content.ActivityNotFoundException e) {
- // Link to Chrome if user is not signed in to Play Store
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.android.chrome"));
- if (intent.resolveActivity(getPackageManager()) != null) {
- startActivity(intent);
- } else {
- Toast.makeText(getApplicationContext(), getString(R.string.unable_to_open_browser), Toast.LENGTH_SHORT).show();
- }
- }
- }
- });
+ /**
+ * Based on whether Chrome and WebView are installed & enabled,
+ * display the corresponding update panel
+ * @param chromeStatus
+ * @param webViewStatus
+ */
+ private void updateWebViewIfNeeded(EngineWebViewVersionStatus chromeStatus, SystemWebViewStatus webViewStatus) {
+ if (chromeStatus == EngineWebViewVersionStatus.FULL && webViewStatus == SystemWebViewStatus.FULL) {
+ return;
}
+
+ if (webViewStatus == SystemWebViewStatus.NOT_INSTALLED) {
+ displayInstallWebView();
+ } else if (webViewStatus == SystemWebViewStatus.DISABLED) {
+ displayEnableWebView();
+ } else {
+ // Otherwise, display update Chrome
+ displayUpdateChrome();
+ }
+ }
+
+ private void displayInstallWebView() {
+ TextView textView = (TextView)findViewById((R.id.kmWebViewChromeTextView));
+ textView.setText(getString(R.string.body_install_webview));
+
+ Button button = (Button)findViewById(R.id.webViewChromeButton);
+ button.setText(getString(R.string.label_install_webview));
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ // Play Store link to install WebView
+ Intent intent = new Intent(Intent.ACTION_VIEW,
+ Uri.parse("https://play.google.com/store/apps/details?id=com.google.android.webview"));
+
+ // Launch intent
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ if (intent.resolveActivity(packageManager) != null) {
+ startActivity(intent);
+ }
+ } catch (android.content.ActivityNotFoundException e) {
+ Toast.makeText(getApplicationContext(), getString(R.string.unable_to_open_browser), Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+ LinearLayout webViewChromeLayout = (LinearLayout) findViewById(R.id.checkWebViewChromeLayout);
+ webViewChromeLayout.setVisibility(View.VISIBLE);
+ }
+
+ private void displayEnableWebView() {
+ TextView textView = (TextView)findViewById((R.id.kmWebViewChromeTextView));
+ textView.setText(getString(R.string.body_enable_webview));
+
+ Button button = (Button)findViewById(R.id.webViewChromeButton);
+ button.setText(getString(R.string.label_enable_webview));
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ // Application settings to enable WebView
+ Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS",
+ Uri.parse("package:com.google.android.webview"));
+
+ // Launch intent
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ if (intent.resolveActivity(packageManager) != null) {
+ startActivity(intent);
+ }
+ } catch (android.content.ActivityNotFoundException e) {
+ Toast.makeText(getApplicationContext(), getString(R.string.unable_to_open_browser), Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+ LinearLayout webViewChromeLayout = (LinearLayout) findViewById(R.id.checkWebViewChromeLayout);
+ webViewChromeLayout.setVisibility(View.VISIBLE);
+ }
+
+ private void displayUpdateChrome() {
+ // TextView's default string is to update Chrome
+
+ Button button = (Button)findViewById(R.id.webViewChromeButton);
+ button.setText(getString(R.string.button_update_chrome));
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ // Primary Play Store link to install/update Chrome
+ Intent intent = new Intent(Intent.ACTION_VIEW,
+ Uri.parse("market://details?id=com.android.chrome"));
+
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ if (intent.resolveActivity(packageManager) != null) {
+ startActivity(intent);
+ } else {
+ // (alternate Play Store link to install/update Chrome)
+ intent = new Intent(Intent.ACTION_VIEW,
+ Uri.parse("https://play.google.com/store/apps/details?id=com.android.chrome"));
+
+ intent.resolveActivity(packageManager);
+ startActivity(intent);
+ }
+ } catch (android.content.ActivityNotFoundException e) {
+ Toast.makeText(getApplicationContext(), getString(R.string.unable_to_open_browser), Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+ LinearLayout webViewChromeLayout = (LinearLayout) findViewById(R.id.checkWebViewChromeLayout);
+ webViewChromeLayout.setVisibility(View.VISIBLE);
}
private Uri requestPermissionIntentUri;
diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_main.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_main.xml
index 87c7fe16f9..c2911272d1 100644
--- a/android/KMAPro/kMAPro/src/main/res/layout/activity_main.xml
+++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_main.xml
@@ -11,7 +11,7 @@
-
-
+