From e0c82e775dad89d3e9356502acc919bb8e1fbeb3 Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Wed, 30 Oct 2019 15:05:22 +0700 Subject: [PATCH 01/12] feat: move keyboard download to background --- .../kmea/KMKeyboardDownloaderActivity.java | 297 ++++++++---------- .../tavultesoft/kmea/data/CloudApiTypes.java | 53 ++-- .../data/CloudCatalogDownloadCallback.java | 29 +- .../kmea/data/CloudDataJsonUtil.java | 205 +++++++++++- .../kmea/data/CloudDownloadMgr.java | 3 +- .../CloudKeyboardDataDownloadCallback.java | 101 ++++++ .../data/CloudKeyboardDownloadReturns.java | 18 ++ ...CloudKeyboardMetaDataDownloadCallback.java | 265 ++++++++++++++++ .../CloudLexicalPackageDownloadCallback.java | 104 ++++++ .../kmea/data/CloudRepository.java | 13 +- .../kmea/packages/PackageProcessor.java | 2 +- 11 files changed, 857 insertions(+), 233 deletions(-) create mode 100644 android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java create mode 100644 android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDownloadReturns.java create mode 100644 android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java create mode 100644 android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index 766557ce89..120d768482 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -19,6 +19,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.tavultesoft.kmea.data.CloudApiTypes; +import com.tavultesoft.kmea.data.CloudDataJsonUtil; +import com.tavultesoft.kmea.data.CloudDownloadMgr; +import com.tavultesoft.kmea.data.CloudKeyboardDataDownloadCallback; +import com.tavultesoft.kmea.data.CloudKeyboardMetaDataDownloadCallback; +import com.tavultesoft.kmea.data.CloudLexicalPackageDownloadCallback; import com.tavultesoft.kmea.packages.LexicalModelPackageProcessor; import com.tavultesoft.kmea.packages.PackageProcessor; import com.tavultesoft.kmea.util.FileUtils; @@ -30,6 +36,8 @@ import static com.tavultesoft.kmea.KMManager.KMDefault_UndefinedPackageID; public class KMKeyboardDownloaderActivity extends AppCompatActivity { // Bundle Keys // Cloud + public static boolean USE_DOWNLOAD_MANAGER = true; + public static final String ARG_PKG_ID = "KMKeyboardActivity.pkgID"; public static final String ARG_KB_ID = "KMKeyboardActivity.kbID"; public static final String ARG_LANG_ID = "KMKeyboardActivity.langID"; @@ -89,43 +97,41 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { super.onCreate(savedInstanceState); Bundle bundle = getIntent().getExtras(); - if (bundle != null) { - pkgID = bundle.getString(ARG_PKG_ID); - if (pkgID == null || pkgID.isEmpty()) { - pkgID = KMManager.KMDefault_UndefinedPackageID; - } - langID = bundle.getString(ARG_LANG_ID); - langName = bundle.getString(ARG_LANG_NAME); - - downloadOnlyLexicalModel = bundle.containsKey(ARG_MODEL_URL) && - bundle.getString(ARG_MODEL_URL) != null && - !bundle.getString(ARG_MODEL_URL).isEmpty(); - - if (downloadOnlyLexicalModel) { - modelID = bundle.getString(ARG_MODEL_ID); - modelName = bundle.getString(ARG_MODEL_NAME); - isCustom = false; - url = bundle.getString(ARG_MODEL_URL); - } else { - - kbID = bundle.getString(ARG_KB_ID); - kbName = bundle.getString(ARG_KB_NAME); - isCustom = bundle.getBoolean(ARG_IS_CUSTOM); - - // URL parameters for custom keyboard (if they exist) - customKeyboard = bundle.getString(ARG_KEYBOARD); - customLanguage = bundle.getString(ARG_LANGUAGE); - url = bundle.getString(ARG_URL); - filename = bundle.getString(ARG_FILENAME); - if (filename == null || filename.isEmpty()) { - filename = "unknown"; - } - } - } else { + if (bundle == null) return; + + pkgID = bundle.getString(ARG_PKG_ID); + if (pkgID == null || pkgID.isEmpty()) { + pkgID = KMManager.KMDefault_UndefinedPackageID; + } + langID = bundle.getString(ARG_LANG_ID); + langName = bundle.getString(ARG_LANG_NAME); + + downloadOnlyLexicalModel = bundle.containsKey(ARG_MODEL_URL) && + bundle.getString(ARG_MODEL_URL) != null && + !bundle.getString(ARG_MODEL_URL).isEmpty(); + + if (downloadOnlyLexicalModel) { + modelID = bundle.getString(ARG_MODEL_ID); + modelName = bundle.getString(ARG_MODEL_NAME); + isCustom = false; + url = bundle.getString(ARG_MODEL_URL); + } else { + + kbID = bundle.getString(ARG_KB_ID); + kbName = bundle.getString(ARG_KB_NAME); + isCustom = bundle.getBoolean(ARG_IS_CUSTOM); + + // URL parameters for custom keyboard (if they exist) + customKeyboard = bundle.getString(ARG_KEYBOARD); + customLanguage = bundle.getString(ARG_LANGUAGE); + url = bundle.getString(ARG_URL); + filename = bundle.getString(ARG_FILENAME); + if (filename == null || filename.isEmpty()) { + filename = "unknown"; + } } - Bundle args = new Bundle(); String title = ""; if (url != null) { title = String.format("%s: %s", getString(R.string.custom_keyboard), filename); @@ -247,6 +253,8 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { String remoteUrl = "",remoteLexicalModelUrl = ""; if (isCustom) { + //TODO: Doesn't work, because this case will end up in an exception during download??? + // See downloadNonKMPKeyboard remoteUrl = url; } else { // Keyman cloud @@ -357,10 +365,9 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { } String fontBaseUri = options.optString(KMKey_FontBaseURI, ""); - JSONObject language, keyboard = null; // Keyman cloud keyboard distribution via JSON - language = kbData.optJSONObject(KMKey_Language); + JSONObject language = kbData.optJSONObject(KMKey_Language); if (language == null) { throw new Exception(exceptionStr); } @@ -368,20 +375,8 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { langName = language.optString(KMManager.KMKey_Name, ""); JSONArray keyboards = language.getJSONArray(KMKey_LanguageKeyboards); - if (keyboards == null) { - throw new Exception(exceptionStr); - } - // In case keyboards array contains multiple keyboards, get the one with matching keyboard ID - for (int index = 0; index < keyboards.length(); index++) { - keyboard = keyboards.getJSONObject(index); - if (keyboard != null && (kbID.equals(keyboard.getString(KMManager.KMKey_ID)))) { - break; - } - } - if (keyboard == null) { - throw new Exception(exceptionStr); - } + JSONObject keyboard = CloudDataJsonUtil.findMatchingKeyBoardByID(keyboards,kbID); kbID = keyboard.getString(KMManager.KMKey_ID); pkgID = keyboard.optString(KMManager.KMKey_PackageID, KMManager.KMDefault_UndefinedPackageID); @@ -400,13 +395,13 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { JSONObject jsonOskFont = keyboard.optJSONObject(KMManager.KMKey_OskFont); if (jsonFont != null) { - findTTF(jsonFont); + CloudDataJsonUtil.updateFontSourceToTTFFont(jsonFont); } if (jsonOskFont != null) { - findTTF(jsonOskFont); + CloudDataJsonUtil.updateFontSourceToTTFFont(jsonOskFont); } - ArrayList fontUrls = fontUrls(jsonFont, fontBaseUri, true); - ArrayList oskFontUrls = fontUrls(jsonOskFont, fontBaseUri, true); + ArrayList fontUrls = CloudDataJsonUtil.fontUrls(jsonFont, fontBaseUri, true); + ArrayList oskFontUrls = CloudDataJsonUtil.fontUrls(jsonOskFont, fontBaseUri, true); if (fontUrls != null) urls.addAll(fontUrls); if (oskFontUrls != null) { @@ -502,17 +497,9 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { */ protected void notifyListeners(KeyboardEventHandler.EventType eventType, int result) { if (kbDownloadEventListeners != null) { - HashMap keyboardInfo = new HashMap(); - keyboardInfo.put(KMManager.KMKey_PackageID, pkgID); - keyboardInfo.put(KMManager.KMKey_KeyboardID, kbID); - keyboardInfo.put(KMManager.KMKey_LanguageID, langID); - keyboardInfo.put(KMManager.KMKey_KeyboardName, kbName); - keyboardInfo.put(KMManager.KMKey_LanguageName, langName); - keyboardInfo.put(KMManager.KMKey_KeyboardVersion, kbVersion); - keyboardInfo.put(KMManager.KMKey_CustomKeyboard, kbIsCustom); - keyboardInfo.put(KMManager.KMKey_Font, font); - if (oskFont != null) - keyboardInfo.put(KMManager.KMKey_OskFont, oskFont); + HashMap keyboardInfo = + CloudDataJsonUtil.createKeyBoardInfoMap(pkgID,langID,langName,kbID,kbName,kbVersion,kbIsCustom,font,oskFont); + KeyboardEventHandler.notifyListeners(kbDownloadEventListeners, eventType, keyboardInfo, result); } } @@ -537,14 +524,89 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { * @param showProgressDialog */ public static void download(final Context context, final boolean showProgressDialog) { - new DownloadTask(context, showProgressDialog).execute(); + if(USE_DOWNLOAD_MANAGER) + downloadKeyboardUsingDownloadManager(context); + else + new DownloadTask(context, showProgressDialog).execute(); } public static void download(final Context context, final boolean showProgressDialog, - final boolean donwloadOnlyLexicalModel) { - new DownloadTask(context, showProgressDialog, downloadOnlyLexicalModel).execute(); + final boolean aDownloadOnlyLexicalModel) { + if(USE_DOWNLOAD_MANAGER) + downloadUsingDownloadManager(context,aDownloadOnlyLexicalModel); + else + new DownloadTask(context, showProgressDialog, aDownloadOnlyLexicalModel).execute(); } + public static void downloadUsingDownloadManager(final Context context, + final boolean aDownloadOnlyLexicalModel) + { + if(aDownloadOnlyLexicalModel) + { + downloadLexicalModelUsingDownloadManager(context); + } + else + { + downloadKeyboardUsingDownloadManager(context); + } + } + + private static void downloadKeyboardUsingDownloadManager(Context context) { + if (pkgID == null || pkgID.trim().isEmpty() || + (!isCustom && (langID == null || langID.trim().isEmpty() || kbID == null || kbID.trim().isEmpty()))) { + throw new IllegalStateException("Invalid keyboard"); + } + + String deviceType = CloudDataJsonUtil.getDeviceTypeForCloudQuery(context); + + List cloudQueries = new ArrayList<>(); + + if (isCustom) { + //TODO: will end up in an exception during download??? + cloudQueries.add(new CloudApiTypes.CloudApiParam( + CloudApiTypes.ApiTarget.KeyboardData, url)); + } + else + { + // Keyman cloud + String _remoteUrl = String.format("%s/%s/%s?version=%s&device=%s&languageidtype=bcp47", + kKeymanApiBaseURL, langID, kbID, BuildConfig.VERSION_NAME, deviceType); + cloudQueries.add( + new CloudApiTypes.CloudApiParam( + CloudApiTypes.ApiTarget.Keyboard, _remoteUrl) + .setType(CloudApiTypes.JSONType.Object) + .setAdditionalProperty(CloudKeyboardMetaDataDownloadCallback.PARAM_IS_CUSTOM,isCustom) + .setAdditionalProperty(CloudKeyboardMetaDataDownloadCallback.PARAM_LANG_ID,langID) + .setAdditionalProperty(CloudKeyboardMetaDataDownloadCallback.PARAM_KB_ID,kbID)); + + String _remoteLexicalModelUrl = String.format("%s?q=bcp47:%s", kKeymanApiModelURL, langID); + cloudQueries.add(new CloudApiTypes.CloudApiParam( + CloudApiTypes.ApiTarget.KeyBoardLexicalModels, _remoteLexicalModelUrl) + .setType(CloudApiTypes.JSONType.Array)); + } + + CloudKeyboardMetaDataDownloadCallback _callback = new CloudKeyboardMetaDataDownloadCallback(); + _callback.setDownloadEventListeners(kbDownloadEventListeners); + + CloudDownloadMgr.getInstance().executeAsDownload( + context, "metadata_" + langID + "_" + kbID, null, _callback, + cloudQueries.toArray(new CloudApiTypes.CloudApiParam[0])); + + } + + private static void downloadLexicalModelUsingDownloadManager(Context context) { + CloudLexicalPackageDownloadCallback _callback =new CloudLexicalPackageDownloadCallback(); + _callback.initializeContext(context); + _callback.setDownloadEventListeners(kbDownloadEventListeners); + + CloudApiTypes.CloudApiParam _param = new CloudApiTypes.CloudApiParam( + CloudApiTypes.ApiTarget.LexicalModelPackage, url); + + CloudDownloadMgr.getInstance().executeAsDownload( + context, "dictionary_" + modelID, null, _callback, _param); + } + + public static boolean isCustom(String u) { boolean ret = false; if (u != null && !u.contains(KMKeyboardDownloaderActivity.kKeymanApiBaseURL) && @@ -554,108 +616,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { return ret; } - // If a font JSONObject contains multiple font font files, only keep the .ttf source - private static void findTTF(JSONObject jsonFont) { - boolean updateJsonFont = false; - try { - JSONArray fontSource = jsonFont.optJSONArray(KMManager.KMKey_FontSource); - if ((fontSource != null) && hasTTFFont(fontSource)) { - for (int i = fontSource.length() - 1; i >= 0; i--) { - String s = fontSource.getString(i); - if (!FileUtils.isTTFFont(s)) { - updateJsonFont = true; - // remove() was added in API 19 - // https://developer.android.com/reference/org/json/JSONArray#remove(int) - if (Build.VERSION.SDK_INT > 19) { - fontSource.remove(i); - } else { - fontSource = removeJsonObjectAtIndex(fontSource, i); - } - } - } - if (updateJsonFont) { - JSONArray copy = fontSource; - jsonFont.remove(KMManager.KMKey_FontSource); - jsonFont.put(KMManager.KMKey_FontSource, copy); - } - } - } catch (JSONException e) { - Log.e(TAG, "findTTF exception" + e); - } - } - - // Parse the fontSource JSONArray to see if it contains a .ttf font - private static boolean hasTTFFont(JSONArray fontSource) { - try { - for (int i = 0; i < fontSource.length(); i++) { - String s = fontSource.getString(i); - if (FileUtils.isTTFFont(s)) { - return true; - } - } - return false; - } catch (JSONException e) { - Log.e(TAG, "hasTTFFont exception" + e); - return false; - } - } - - // From https://stackoverflow.com/questions/27427999/remove-jsonobeject-before-android-api-lvl-19 - private static JSONArray removeJsonObjectAtIndex(JSONArray source, int index) throws JSONException { - if (index < 0 || index > source.length() - 1) { - throw new IndexOutOfBoundsException(); - } - - final JSONArray copy = new JSONArray(); - for (int i=0, count = source.length(); i fontUrls(JSONObject jsonFont, String baseUri, boolean isOskFont) { - if (jsonFont == null) - return null; - - ArrayList urls = new ArrayList(); - JSONArray fontSource = jsonFont.optJSONArray(KMManager.KMKey_FontSource); - if (fontSource != null) { - int fcCount = fontSource.length(); - for (int i = 0; i < fcCount; i++) { - String fontSourceString; - try { - fontSourceString = fontSource.getString(i); - - if (FileUtils.hasFontExtension(fontSourceString)) { - urls.add(baseUri + fontSourceString); - } else if (isOskFont && FileUtils.hasSVGViewBox(fontSourceString)) { - String fontFilename = FileUtils.getSVGFilename(fontSourceString); - urls.add(baseUri + fontFilename); - } - } catch (JSONException e) { - return null; - } - } - } else { - String fontSourceString; - try { - fontSourceString = jsonFont.getString(KMManager.KMKey_FontSource); - if (FileUtils.hasFontExtension(fontSourceString)) { - urls.add(baseUri + fontSourceString); - } else if (isOskFont && FileUtils.hasSVGViewBox(fontSourceString)) { - String fontFilename = FileUtils.getSVGFilename(fontSourceString); - urls.add(baseUri + fontFilename); - } - } catch (JSONException e) { - return null; - } - } - - return urls; - } public static void addKeyboardDownloadEventListener(KeyboardEventHandler.OnKeyboardDownloadEventListener listener) { if (kbDownloadEventListeners == null) { diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java index 7cb8f787bf..bc908b2ddb 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java @@ -9,8 +9,10 @@ import org.json.JSONObject; import java.io.File; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; public class CloudApiTypes { protected static class CloudApiReturns { @@ -33,25 +35,44 @@ public class CloudApiTypes { } - protected enum ApiTarget { + public enum ApiTarget { Keyboards, - LexicalModels + LexicalModels, + Keyboard, + KeyBoardLexicalModels, + KeyboardData, + LexicalModelPackage, } - protected enum JSONType { + public enum JSONType { Array, Object } - protected static class CloudApiParam { + public static class CloudApiParam { public final ApiTarget target; public final String url; - public final JSONType type; + public JSONType type; + private Map additionalProperties = new HashMap<>(); - CloudApiParam(ApiTarget target, String url, JSONType type) { + public CloudApiParam(ApiTarget target, String url) { this.target = target; this.url = url; + } + + public CloudApiParam setType(JSONType type) { this.type = type; + return this; + } + public CloudApiParam setAdditionalProperty(String aProperty, Object aValue) + { + additionalProperties.put(aProperty,aValue); + return this; + } + + public T getAdditionalProperty(String aProperty,Class aType) + { + return (T)additionalProperties.get(aProperty); } } @@ -61,8 +82,7 @@ public class CloudApiTypes { private boolean downloadFinished =false; private long downloadId; private File destinationFile; - private CloudApiTypes.JSONType type; - private CloudApiTypes.ApiTarget target; + private CloudApiParam cloudParams; public SingleCloudDownload(DownloadManager.Request aRequest,File aDestinationFile) { @@ -74,13 +94,8 @@ public class CloudApiTypes { return this; } - public SingleCloudDownload setJsonType(JSONType type) { - this.type = type; - return this; - } - - public SingleCloudDownload setTarget(ApiTarget target) { - this.target = target; + public SingleCloudDownload setCloudParams(CloudApiParam params) { + this.cloudParams = params; return this; } @@ -96,12 +111,8 @@ public class CloudApiTypes { return destinationFile; } - public JSONType getType() { - return type; - } - - public ApiTarget getTarget() { - return target; + public CloudApiParam getCloudParams() { + return cloudParams; } } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudCatalogDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudCatalogDownloadCallback.java index 54de4de0ff..7a3e7b0b4b 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudCatalogDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudCatalogDownloadCallback.java @@ -245,35 +245,14 @@ public class CloudCatalogDownloadCallback implements ICloudDownloadCallback retrievedJSON = new ArrayList<>(aDownload.getSingleDownloads().size()); - for (CloudApiTypes.SingleCloudDownload _d : aDownload.getSingleDownloads()) { - JSONParser jsonParser = new JSONParser(); - JSONArray dataArray = null; - JSONObject dataObject = null; - if (_d.getDestinationFile() != null && _d.getDestinationFile().length() > 0) { - try { + CloudApiTypes.CloudApiReturns _json_result = CloudDataJsonUtil.retrieveJsonFromDownload(_d); - if (_d.getType() == CloudApiTypes.JSONType.Array) { - dataArray = jsonParser.getJSONObjectFromFile(_d.getDestinationFile(),JSONArray.class);//(JSONArray) _o; - } else { - dataObject = jsonParser.getJSONObjectFromFile(_d.getDestinationFile(),JSONObject.class);//(JSONObject) _o; - } - } catch (Exception e) { - Log.d(TAG, e.getMessage()); - } finally { - _d.getDestinationFile().delete(); - } - } else { - // Offline trouble! That said, we can't get anything, so we simply shouldn't add anything. - } - - if (_d.getType() == CloudApiTypes.JSONType.Array) { - retrievedJSON.add(new CloudApiTypes.CloudApiReturns(_d.getTarget(), dataArray)); // Null if offline. - } else { - retrievedJSON.add(new CloudApiTypes.CloudApiReturns(_d.getTarget(), dataObject)); // Null if offline. - } + if (_json_result!=null) + retrievedJSON.add(_json_result); // Null if offline. } + return new CloudCatalogDownloadReturns(retrievedJSON); } } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java index 37c31a1c19..16271c9726 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java @@ -1,8 +1,10 @@ package com.tavultesoft.kmea.data; import android.content.Context; +import android.os.Build; import android.util.Log; +import com.tavultesoft.kmea.JSONParser; import com.tavultesoft.kmea.KMKeyboardDownloaderActivity; import com.tavultesoft.kmea.KMManager; import com.tavultesoft.kmea.R; @@ -29,6 +31,27 @@ public class CloudDataJsonUtil { { //no instances } + + public static HashMap createKeyBoardInfoMap(String aPackageId,String aLanguageId, String aLanguageName, String aKeyboardId, + String aKeyboardName, String aKeyboardVersion, String anIsCustomKeyBoard, + String aFont, String aOskFont) + { + HashMap keyboardInfo = new HashMap(); + if(aPackageId!=null) + keyboardInfo.put(KMManager.KMKey_PackageID, aPackageId); + keyboardInfo.put(KMManager.KMKey_KeyboardID, aKeyboardId); + keyboardInfo.put(KMManager.KMKey_LanguageID, aLanguageId); + keyboardInfo.put(KMManager.KMKey_KeyboardName, aKeyboardName); + keyboardInfo.put(KMManager.KMKey_LanguageName, aLanguageName); + keyboardInfo.put(KMManager.KMKey_KeyboardVersion, aKeyboardVersion); + keyboardInfo.put(KMManager.KMKey_CustomKeyboard, anIsCustomKeyBoard); + keyboardInfo.put(KMManager.KMKey_Font, aFont); + if (aOskFont != null) + keyboardInfo.put(KMManager.KMKey_OskFont, aOskFont); + + return keyboardInfo; + } + static List processKeyboardJSON(JSONObject query, boolean fromKMP) { List keyboardsList = new ArrayList<>(); //keyboardModifiedDates = new HashMap(); @@ -55,14 +78,8 @@ public class CloudDataJsonUtil { String kbFont = keyboardJSON.optString(KMManager.KMKey_Font, ""); //String kbKey = String.format("%s_%s", langID, kbID); - HashMap hashMap = new HashMap(); - hashMap.put(KMManager.KMKey_KeyboardName, kbName); - hashMap.put(KMManager.KMKey_KeyboardID, kbID); - hashMap.put(KMManager.KMKey_LanguageName, langName); - hashMap.put(KMManager.KMKey_LanguageID, langID); - hashMap.put(KMManager.KMKey_KeyboardVersion, kbVersion); - hashMap.put(KMManager.KMKey_CustomKeyboard, isCustom); - hashMap.put(KMManager.KMKey_Font, kbFont); + HashMap hashMap = createKeyBoardInfoMap(null,langID,langName,kbID,kbName,kbVersion,isCustom,kbFont,null); + // if (keyboardModifiedDates.get(kbID) == null) { // keyboardModifiedDates.put(kbID, keyboardJSON.getString(KMManager.KMKey_KeyboardModified)); @@ -219,4 +236,176 @@ public class CloudDataJsonUtil { final String jsonLexicalCacheFilename = "jsonLexicalModelsCache.dat"; return new File(context.getCacheDir(), jsonLexicalCacheFilename); } + + public static CloudApiTypes.CloudApiReturns retrieveJsonFromDownload( CloudApiTypes.SingleCloudDownload aDownload) + { + JSONParser jsonParser = new JSONParser(); + JSONArray dataArray = null; + JSONObject dataObject = null; + + if (aDownload.getDestinationFile() != null && aDownload.getDestinationFile().length() > 0) { + try { + + if (aDownload.getCloudParams().type == CloudApiTypes.JSONType.Array) { + dataArray = jsonParser.getJSONObjectFromFile(aDownload.getDestinationFile(),JSONArray.class);//(JSONArray) _o; + } else { + dataObject = jsonParser.getJSONObjectFromFile(aDownload.getDestinationFile(),JSONObject.class);//(JSONObject) _o; + } + } catch (Exception e) { + Log.d(TAG, e.getMessage()); + } finally { + aDownload.getDestinationFile().delete(); + } + } else { + // Offline trouble! That said, we can't get anything, so we simply shouldn't add anything. + } + + if (aDownload.getCloudParams().type == CloudApiTypes.JSONType.Array) + { + if(dataArray!=null) + return new CloudApiTypes.CloudApiReturns(aDownload.getCloudParams().target, dataArray); // Null if offline. + return null; + } + if(dataObject!=null) + return new CloudApiTypes.CloudApiReturns(aDownload.getCloudParams().target, dataObject); // Null if offline. + + + return null; + } + + // If a font JSONObject contains multiple font font files, only keep the .ttf source + public static void updateFontSourceToTTFFont(JSONObject jsonFont) { + boolean updateJsonFont = false; + try { + JSONArray fontSource = jsonFont.optJSONArray(KMManager.KMKey_FontSource); + if ((fontSource != null) && hasTTFFont(fontSource)) { + for (int i = fontSource.length() - 1; i >= 0; i--) { + String s = fontSource.getString(i); + if (!FileUtils.isTTFFont(s)) { + updateJsonFont = true; + // remove() was added in API 19 + // https://developer.android.com/reference/org/json/JSONArray#remove(int) + if (Build.VERSION.SDK_INT > 19) { + fontSource.remove(i); + } else { + fontSource = removeJsonObjectAtIndex(fontSource, i); + } + } + } + + if (updateJsonFont) { + JSONArray copy = fontSource; + jsonFont.remove(KMManager.KMKey_FontSource); + jsonFont.put(KMManager.KMKey_FontSource, copy); + } + } + } catch (JSONException e) { + Log.e(TAG, "findTTF exception" + e); + } + } + + // Parse the fontSource JSONArray to see if it contains a .ttf font + private static boolean hasTTFFont(JSONArray fontSource) { + try { + for (int i = 0; i < fontSource.length(); i++) { + String s = fontSource.getString(i); + if (FileUtils.isTTFFont(s)) { + return true; + } + } + return false; + } catch (JSONException e) { + Log.e(TAG, "hasTTFFont exception" + e); + return false; + } + } + + // From https://stackoverflow.com/questions/27427999/remove-jsonobeject-before-android-api-lvl-19 + private static JSONArray removeJsonObjectAtIndex(JSONArray source, int index) throws JSONException { + if (index < 0 || index > source.length() - 1) { + throw new IndexOutOfBoundsException(); + } + + final JSONArray copy = new JSONArray(); + for (int i=0, count = source.length(); i fontUrls(JSONObject jsonFont, String baseUri, boolean isOskFont) { + if (jsonFont == null) + return null; + + ArrayList urls = new ArrayList(); + JSONArray fontSource = jsonFont.optJSONArray(KMManager.KMKey_FontSource); + if (fontSource != null) { + int fcCount = fontSource.length(); + for (int i = 0; i < fcCount; i++) { + String fontSourceString; + try { + fontSourceString = fontSource.getString(i); + + if (FileUtils.hasFontExtension(fontSourceString)) { + urls.add(baseUri + fontSourceString); + } else if (isOskFont && FileUtils.hasSVGViewBox(fontSourceString)) { + String fontFilename = FileUtils.getSVGFilename(fontSourceString); + urls.add(baseUri + fontFilename); + } + } catch (JSONException e) { + return null; + } + } + } else { + String fontSourceString; + try { + fontSourceString = jsonFont.getString(KMManager.KMKey_FontSource); + if (FileUtils.hasFontExtension(fontSourceString)) { + urls.add(baseUri + fontSourceString); + } else if (isOskFont && FileUtils.hasSVGViewBox(fontSourceString)) { + String fontFilename = FileUtils.getSVGFilename(fontSourceString); + urls.add(baseUri + fontFilename); + } + } catch (JSONException e) { + return null; + } + } + + return urls; + } + + public static JSONObject findMatchingKeyBoardByID(JSONArray aKeyboards, String aKbId) + throws IllegalStateException, JSONException + { + if (aKeyboards == null) { + throw new IllegalStateException("Keyboard array is empty"); + } + + JSONObject keyboard = null; + // In case keyboards array contains multiple keyboards, get the one with matching keyboard ID + for (int index = 0; index < aKeyboards.length(); index++) { + keyboard = aKeyboards.getJSONObject(index); + if (keyboard != null && (aKbId.equals(keyboard.getString(KMManager.KMKey_ID)))) { + break; + } + } + if (keyboard == null) { + throw new IllegalStateException("could not find matching keyboard"); + } + + return keyboard; + } + public static String getDeviceTypeForCloudQuery(Context aContext) + { + String deviceType = aContext.getString(R.string.device_type); + if (deviceType.equals("AndroidTablet")) { + deviceType = "androidtablet"; + } else { + deviceType = "androidphone"; + } + return deviceType; + } + } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDownloadMgr.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDownloadMgr.java index 4ddbe25994..48dd340a88 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDownloadMgr.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDownloadMgr.java @@ -232,7 +232,6 @@ public class CloudDownloadMgr{ //.setAllowedOverRoaming(true);// Set if download is allowed on roaming network return new CloudApiTypes.SingleCloudDownload(_request,_file) - .setJsonType(aParam.type) - .setTarget(aParam.target); + .setCloudParams(aParam); } } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java new file mode 100644 index 0000000000..7879268937 --- /dev/null +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java @@ -0,0 +1,101 @@ +package com.tavultesoft.kmea.data; + +import android.content.Context; +import android.util.Log; + +import com.tavultesoft.kmea.KeyboardEventHandler; +import com.tavultesoft.kmea.util.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + +import static com.tavultesoft.kmea.KMManager.KMDefault_UndefinedPackageID; + +public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback< + Void, CloudKeyboardDownloadReturns> +{ + + private static final String TAG = "CloudkbDataDldCb"; + + private File dataDir; + + private ArrayList downloadEventListeners = new ArrayList<>(); + private HashMap keyboardInfo; + + public static final String PARAM_DESTINATION_FILE_NAME = "destination_file_name"; + + + + public void setDownloadEventListeners(ArrayList aDownloadEventListeners) + { + downloadEventListeners.clear(); + downloadEventListeners.addAll(aDownloadEventListeners); + } + + public void setKeyboardInfo(HashMap aKeyboardInfo) { + this.keyboardInfo = aKeyboardInfo; + } + + public void initializeContext(Context context) + { + dataDir = context.getDir("data", Context.MODE_PRIVATE); + } + + @Override + public CloudKeyboardDownloadReturns extractCloudResultFromDownloadSet( + CloudApiTypes.CloudDownloadSet aDownload) + { + + + int _result = FileUtils.DOWNLOAD_SUCCESS; + for(CloudApiTypes.SingleCloudDownload _d:aDownload.getSingleDownloads()) + { + if (_d.getDestinationFile() != null && _d.getDestinationFile().length() > 0) + { + + try { + + String destination = dataDir.toString() + + File.separator + KMDefault_UndefinedPackageID + File.separator + File.separator; + + String _filename = _d.getCloudParams().getAdditionalProperty(PARAM_DESTINATION_FILE_NAME,String.class); + if (_filename==null) { + + _filename = FileUtils.getFilename(_d.getCloudParams().url); + } + + File _data_file = new File(destination,_filename); + FileUtils.copy(_d.getDestinationFile(), _data_file); + + } + catch (IOException _e) + { + Log.e(TAG,_e.getLocalizedMessage(),_e); + } + } + else + { + if (FileUtils.hasFontExtension(_d.getCloudParams().url)) + _result = -2; + else + _result = FileUtils.DOWNLOAD_ERROR; + } + } + return new CloudKeyboardDownloadReturns(_result); + } + + + + @Override + public void applyCloudDownloadToModel(Context aContext, Void aModel, CloudKeyboardDownloadReturns aCloudResult) + { + if(keyboardInfo!=null) + { + KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_FINISHED, + keyboardInfo, aCloudResult.kbdResult); + } + + } +} diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDownloadReturns.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDownloadReturns.java new file mode 100644 index 0000000000..967d91a5ac --- /dev/null +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDownloadReturns.java @@ -0,0 +1,18 @@ +package com.tavultesoft.kmea.data; + +import java.util.List; +import java.util.Map; + +public class CloudKeyboardDownloadReturns { + public final Integer kbdResult; + public final List> installedLexicalModels; + + public CloudKeyboardDownloadReturns(Integer i) { + this(i, null); + } + + public CloudKeyboardDownloadReturns(Integer i, List> installedLexicalModels) { + this.kbdResult = i; + this.installedLexicalModels = installedLexicalModels; + } +} diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java new file mode 100644 index 0000000000..48d54c8938 --- /dev/null +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java @@ -0,0 +1,265 @@ +package com.tavultesoft.kmea.data; + +import android.content.Context; +import android.util.Log; +import android.widget.Toast; + +import com.tavultesoft.kmea.KMKeyboardDownloaderActivity; +import com.tavultesoft.kmea.KMManager; +import com.tavultesoft.kmea.KeyboardEventHandler; +import com.tavultesoft.kmea.R; +import com.tavultesoft.kmea.util.FileUtils; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCallback> +{ + public static class MetaDataResult + { + CloudApiTypes.CloudApiReturns returnjson; + CloudApiTypes.CloudApiParam params; + HashMap keyboardInfo; + String keyboardId; + List additionalDownloads; + } + + private static final String TAG = "CloudKeyboardMetaDldCb"; + + private static ArrayList downloadEventListeners = new ArrayList<>(); + + + public static final String PARAM_IS_CUSTOM = "is_custom"; + public static final String PARAM_LANG_ID = "lang_id"; + public static final String PARAM_KB_ID = "kb_id"; + + + public void setDownloadEventListeners(ArrayList aDownloadEventListeners) { + downloadEventListeners.clear(); + downloadEventListeners.addAll(aDownloadEventListeners); + } + + @Override + public List extractCloudResultFromDownloadSet( + CloudApiTypes.CloudDownloadSet> aDownload) { + + List _result = new ArrayList<>(aDownload.getSingleDownloads().size()); + + for (CloudApiTypes.SingleCloudDownload _d : aDownload.getSingleDownloads()) { + + CloudApiTypes.CloudApiReturns _json_result = CloudDataJsonUtil.retrieveJsonFromDownload(_d); + + if (_json_result!=null) { + + CloudKeyboardMetaDataDownloadCallback.MetaDataResult _data = new CloudKeyboardMetaDataDownloadCallback.MetaDataResult(); + _data.returnjson = _json_result; + _data.params = _d.getCloudParams(); + _result.add(_data); // Null if offline. + } + } + return _result; + } + + + + @Override + public void applyCloudDownloadToModel(Context aContext, Void aModel, List aCloudResult) + { + if(aCloudResult.isEmpty()) { + String msg = aContext.getString(R.string.catalog_unavailable); + Toast.makeText(aContext, msg, Toast.LENGTH_SHORT).show(); + //throw new IllegalStateException("Could not reach server"); + return; + } + + processCloudResults(aCloudResult); + + for(MetaDataResult _r:aCloudResult) + { + if(_r.additionalDownloads!=null) + { + ; + + + + if(_r.returnjson.target== CloudApiTypes.ApiTarget.Keyboard) + { + CloudKeyboardDataDownloadCallback _callback = new CloudKeyboardDataDownloadCallback(); + _callback.setDownloadEventListeners(downloadEventListeners); + _callback.setKeyboardInfo(_r.keyboardInfo); + _callback.initializeContext(aContext); + + KeyboardEventHandler.notifyListeners(downloadEventListeners, + KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_STARTED, _r.keyboardInfo, 0); + + CloudDownloadMgr.getInstance().executeAsDownload(aContext, + "keyboarddata_" + _r.keyboardId, null, _callback, + _r.additionalDownloads.toArray(new CloudApiTypes.CloudApiParam[0])); + } + else if(_r.returnjson.target== CloudApiTypes.ApiTarget.KeyBoardLexicalModels) { + CloudLexicalPackageDownloadCallback _callback = new CloudLexicalPackageDownloadCallback(); + _callback.setDownloadEventListeners(downloadEventListeners); + _callback.initializeContext(aContext); + + CloudDownloadMgr.getInstance().executeAsDownload(aContext, + "lexicalpackage_" + _r.keyboardId, null, _callback, + _r.additionalDownloads.toArray(new CloudApiTypes.CloudApiParam[0])); + } + else + continue; + + + + } + } + } + + private void processCloudResults(List aCloudResult) { + for(MetaDataResult _r:aCloudResult) + { + if(_r.returnjson.target== CloudApiTypes.ApiTarget.Keyboard) + { + handleKeyBoardMetaData(_r); + } + if(_r.returnjson.target== CloudApiTypes.ApiTarget.KeyBoardLexicalModels) + { + JSONArray lmData = _r.returnjson.jsonArray; + if (lmData != null && lmData.length() > 0) { + try + { + JSONObject modelInfo = lmData.getJSONObject(0); + if (modelInfo.has("packageFilename")) + { + ArrayList urls = new ArrayList<>(); + urls.add(new CloudApiTypes.CloudApiParam( + CloudApiTypes.ApiTarget.KeyBoardLexicalModels, + modelInfo.getString("packageFilename"))); + _r.additionalDownloads= urls; + } + } catch (JSONException e) { + Log.e(TAG, "Error parsing lexical model from api.keyman.com. " + e); + } + } + } + } + } + + private void handleKeyBoardMetaData(MetaDataResult theKbData) + { + if (theKbData.params.getAdditionalProperty(PARAM_IS_CUSTOM,Boolean.class)) { + throw new IllegalStateException("Cannot download custom non-KMP keyboard"); + } + + String _key_id = theKbData.params.getAdditionalProperty(PARAM_KB_ID,String.class); + String _lang_id = theKbData.params.getAdditionalProperty(PARAM_LANG_ID,String.class); + + String _kbIsCustom = + theKbData.params.getAdditionalProperty(PARAM_IS_CUSTOM,Boolean.class) ? "Y" : "N"; + JSONObject _kb_data = theKbData.returnjson.jsonObject; + + try { + JSONObject options = _kb_data.optJSONObject( + KMKeyboardDownloaderActivity.KMKey_Options); + if (options == null) { + throw new IllegalStateException("JSON file does not contain a valid \"options\" object"); + } + String kbBaseUri = options.optString(KMKeyboardDownloaderActivity.KMKey_KeyboardBaseURI, ""); + if (kbBaseUri.isEmpty()) { + throw new IllegalStateException("JSON file does not contain a valid \"keyboardBaseUri\" object"); + } + + String fontBaseUri = options.optString(KMKeyboardDownloaderActivity.KMKey_FontBaseURI, ""); + + // Keyman cloud keyboard distribution via JSON + JSONObject language = _kb_data.optJSONObject( + KMKeyboardDownloaderActivity.KMKey_Language); + if (language == null) { + throw new IllegalStateException("JSON file does not contain a valid \"language\" object"); + } + + String _langName = language.optString(KMManager.KMKey_Name, ""); + + JSONArray keyboards = language.getJSONArray(KMKeyboardDownloaderActivity.KMKey_LanguageKeyboards); + + JSONObject keyboard = CloudDataJsonUtil.findMatchingKeyBoardByID(keyboards, _key_id); + + _key_id = keyboard.getString(KMManager.KMKey_ID); + String _pkgID = keyboard.optString(KMManager.KMKey_PackageID, KMManager.KMDefault_UndefinedPackageID); + + String _kbName = keyboard.optString(KMManager.KMKey_Name, ""); + String _kbVersion = keyboard.optString(KMManager.KMKey_KeyboardVersion, "1.0"); + String _kbFilename = keyboard.optString(KMKeyboardDownloaderActivity.KMKey_Filename, ""); + if (_kbName.isEmpty() || _langName.isEmpty() || _kbFilename.isEmpty()) + throw new IllegalStateException("JSON file does not contain a valid base values for keyboard object"); + + String _js_filename = _kbFilename; + if (FileUtils.hasJavaScriptExtension(_kbFilename)) { + + int start = _kbFilename.lastIndexOf("/"); + if (start < 0) { + start = 0; + } else { + start++; + } + if (!_kbFilename.contains("-")) { + _js_filename = _kbFilename.substring(start, _kbFilename.length() - 3) + "-" + _kbVersion + ".js"; + } else { + _js_filename = _kbFilename.substring(start); + } + } + String kbUrl = kbBaseUri + _kbFilename; + ArrayList urls = new ArrayList<>(); + + urls.add( + new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, kbUrl) + .setAdditionalProperty( + CloudKeyboardDataDownloadCallback.PARAM_DESTINATION_FILE_NAME, _js_filename)); + + JSONObject jsonFont = keyboard.optJSONObject(KMManager.KMKey_Font); + JSONObject jsonOskFont = keyboard.optJSONObject(KMManager.KMKey_OskFont); + + if (jsonFont != null) { + CloudDataJsonUtil.updateFontSourceToTTFFont(jsonFont); + } + if (jsonOskFont != null) { + CloudDataJsonUtil.updateFontSourceToTTFFont(jsonOskFont); + } + ArrayList fontUrls = CloudDataJsonUtil.fontUrls(jsonFont, fontBaseUri, true); + ArrayList oskFontUrls = CloudDataJsonUtil.fontUrls(jsonOskFont, fontBaseUri, true); + if (fontUrls != null) { + for (String url : fontUrls) { + urls.add(new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, url)); + } + } + if (oskFontUrls != null) { + for (String url : oskFontUrls) { + if (!urls.contains(url)) + urls.add(new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, url)); + ; + } + } + + String _font = keyboard.optString(KMManager.KMKey_Font); + String _oskFont = keyboard.optString(KMManager.KMKey_OskFont); + + theKbData.keyboardId = _key_id; + theKbData.keyboardInfo = CloudDataJsonUtil + .createKeyBoardInfoMap( + _pkgID, _lang_id, _langName, _key_id, _kbName, _kbVersion, _kbIsCustom, _font, _oskFont); + theKbData.additionalDownloads = urls; + } + catch(JSONException _e) + { + Log.e(TAG,_e.getLocalizedMessage(),_e); + } + } + + +} diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java new file mode 100644 index 0000000000..03c6696f8f --- /dev/null +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java @@ -0,0 +1,104 @@ +package com.tavultesoft.kmea.data; + +import android.content.Context; +import android.util.Log; + +import androidx.appcompat.app.AppCompatActivity; + +import com.tavultesoft.kmea.KeyboardEventHandler; +import com.tavultesoft.kmea.packages.LexicalModelPackageProcessor; +import com.tavultesoft.kmea.packages.PackageProcessor; +import com.tavultesoft.kmea.util.FileUtils; + +import org.json.JSONException; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static com.tavultesoft.kmea.KMManager.KMDefault_UndefinedPackageID; + +public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallback< + Void, CloudKeyboardDownloadReturns> +{ + + private static final String TAG = "CloudLexModelPKGDldCb"; + + private File resourceRoot; + private File cacheDir; + + private ArrayList downloadEventListeners = new ArrayList<>(); + + + public void setDownloadEventListeners(ArrayList aDownloadEventListeners) + { + downloadEventListeners.clear(); + downloadEventListeners.addAll(aDownloadEventListeners); + } + + public void initializeContext(Context context) + { + resourceRoot = new File(context.getDir("data", Context.MODE_PRIVATE).toString() + File.separator); + cacheDir = context.getCacheDir(); + } + + @Override + public CloudKeyboardDownloadReturns extractCloudResultFromDownloadSet( + CloudApiTypes.CloudDownloadSet aDownload) + { + + LexicalModelPackageProcessor kmpProcessor = new LexicalModelPackageProcessor(resourceRoot); + List> installedLexicalModels = null; + + int _result = FileUtils.DOWNLOAD_SUCCESS; + for(CloudApiTypes.SingleCloudDownload _d:aDownload.getSingleDownloads()) + { + if (_d.getDestinationFile() != null && _d.getDestinationFile().length() > 0) + { + + try { + + if (_d.getCloudParams().target== CloudApiTypes.ApiTarget.LexicalModelPackage) { + installedLexicalModels = new LinkedList<>(); + // Extract the kmp. Validate it contains only lexical models, and then process the lexical model package + File kmpFile = new File(cacheDir, FileUtils.getFilename(_d.getCloudParams().url)); + + FileUtils.copy(_d.getDestinationFile(), kmpFile); + + String pkgTarget = kmpProcessor.getPackageTarget(kmpFile); + if (pkgTarget.equals(PackageProcessor.PP_TARGET_LEXICAL_MODELS)) { + File unzipPath = kmpProcessor.unzipKMP(kmpFile); + installedLexicalModels.addAll(kmpProcessor.processKMP(kmpFile, unzipPath, PackageProcessor.PP_LEXICAL_MODELS_KEY)); + } + } + } + catch (IOException | JSONException _e) + { + Log.e(TAG,_e.getLocalizedMessage(),_e); + } + } + else + { + _result = FileUtils.DOWNLOAD_ERROR; + } + } + return new CloudKeyboardDownloadReturns(_result,installedLexicalModels); + } + + + + @Override + public void applyCloudDownloadToModel(Context aContext, Void aModel, CloudKeyboardDownloadReturns aCloudResult) + { + if(aCloudResult.installedLexicalModels != null) + { + KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED, + aCloudResult.installedLexicalModels, aCloudResult.kbdResult); + } + + } +} diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java index 3c225e43ff..025967a3e5 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java @@ -117,19 +117,15 @@ public class CloudRepository { private CloudApiTypes.CloudApiParam prepareKeyboardUpdateQuery(Context aContext) { - String deviceType = aContext.getString(R.string.device_type); - if (deviceType.equals("AndroidTablet")) { - deviceType = "androidtablet"; - } else { - deviceType = "androidphone"; - } + String deviceType = CloudDataJsonUtil.getDeviceTypeForCloudQuery(aContext); // Retrieves the cloud-based keyboard catalog in Android's preferred format. String keyboardURL = String.format("%s?version=%s&device=%s&languageidtype=bcp47", KMKeyboardDownloaderActivity.kKeymanApiBaseURL, BuildConfig.VERSION_NAME, deviceType); //cloudQueries[cloudQueryEntries++] = new CloudApiParam(ApiTarget.Keyboards, keyboardURL, JSONType.Object); - return new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.Keyboards, keyboardURL, CloudApiTypes.JSONType.Object); + return new CloudApiTypes.CloudApiParam( + CloudApiTypes.ApiTarget.Keyboards, keyboardURL).setType(CloudApiTypes.JSONType.Object); } private CloudApiTypes.CloudApiParam prepareLexicalModellUpdateQuery(Context aContext) @@ -139,7 +135,8 @@ public class CloudRepository { // query is ready! String lexicalURL = String.format("%s?q", KMKeyboardDownloaderActivity.kKeymanApiModelURL); - return new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.LexicalModels, lexicalURL, CloudApiTypes.JSONType.Array); + return new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.LexicalModels, lexicalURL) + .setType(CloudApiTypes.JSONType.Array); // TODO: We want a list of lexical models for every language with an installed resource (kbd, lex model) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java index 8cffa673a6..5db7fdae72 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java @@ -30,7 +30,7 @@ import org.json.JSONObject; * KMEA engine. This is primarily for installing keyboard packages. */ public class PackageProcessor { - protected static File resourceRoot = null; + protected File resourceRoot = null; public static final String PP_DEFAULT_VERSION = "1.0"; public static final String PP_DEFAULT_METADATA = "kmp.json"; From fb8b04fba85fdbe7e790ebbfd22238bac76a97d9 Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Wed, 30 Oct 2019 16:58:26 +0700 Subject: [PATCH 02/12] feat: keyboard download in background, add notifications --- .../kmea/KMKeyboardDownloaderActivity.java | 64 ++++++-- .../data/CloudCatalogDownloadCallback.java | 5 + .../kmea/data/CloudDownloadMgr.java | 3 + .../CloudKeyboardDataDownloadCallback.java | 22 ++- ...CloudKeyboardMetaDataDownloadCallback.java | 142 +++++++++++------- .../CloudLexicalPackageDownloadCallback.java | 14 +- .../kmea/data/ICloudDownloadCallback.java | 1 + .../KMEA/app/src/main/res/values/strings.xml | 10 +- 8 files changed, 186 insertions(+), 75 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index 120d768482..d2fe30aa72 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -8,6 +8,7 @@ import android.content.Context; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; +import android.widget.Toast; import org.json.JSONArray; import org.json.JSONException; @@ -552,6 +553,9 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { } private static void downloadKeyboardUsingDownloadManager(Context context) { + + + if (pkgID == null || pkgID.trim().isEmpty() || (!isCustom && (langID == null || langID.trim().isEmpty() || kbID == null || kbID.trim().isEmpty()))) { throw new IllegalStateException("Invalid keyboard"); @@ -585,25 +589,61 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { .setType(CloudApiTypes.JSONType.Array)); } - CloudKeyboardMetaDataDownloadCallback _callback = new CloudKeyboardMetaDataDownloadCallback(); - _callback.setDownloadEventListeners(kbDownloadEventListeners); + String _downloadid= "metadata_" + langID + "_" + kbID; - CloudDownloadMgr.getInstance().executeAsDownload( - context, "metadata_" + langID + "_" + kbID, null, _callback, - cloudQueries.toArray(new CloudApiTypes.CloudApiParam[0])); + if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_downloadid) + || CloudDownloadMgr.getInstance().alreadyDownloadingData( + CloudKeyboardDataDownloadCallback.createDownloadId(kbID))) + { + Toast.makeText(context, + context.getString(R.string.keyboard_download_is_running_in_background), + Toast.LENGTH_SHORT).show(); + } + else + { + CloudKeyboardMetaDataDownloadCallback _callback = new CloudKeyboardMetaDataDownloadCallback(); + _callback.setDownloadEventListeners(kbDownloadEventListeners); + Toast.makeText(context, + context.getString(R.string.keyboard_download_start_in_background), + Toast.LENGTH_SHORT).show(); + + CloudDownloadMgr.getInstance().executeAsDownload( + context, _downloadid, null, _callback, + cloudQueries.toArray(new CloudApiTypes.CloudApiParam[0])); + } + + ((AppCompatActivity) context).finish(); } private static void downloadLexicalModelUsingDownloadManager(Context context) { - CloudLexicalPackageDownloadCallback _callback =new CloudLexicalPackageDownloadCallback(); - _callback.initializeContext(context); - _callback.setDownloadEventListeners(kbDownloadEventListeners); - CloudApiTypes.CloudApiParam _param = new CloudApiTypes.CloudApiParam( - CloudApiTypes.ApiTarget.LexicalModelPackage, url); - CloudDownloadMgr.getInstance().executeAsDownload( - context, "dictionary_" + modelID, null, _callback, _param); + String _downloadid= CloudLexicalPackageDownloadCallback.createDownloadId(modelID); + + if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_downloadid)) + { + Toast.makeText(context, + context.getString(R.string.dictionary_download_is_running_in_background), + Toast.LENGTH_SHORT).show(); + } + else + { + CloudLexicalPackageDownloadCallback _callback = new CloudLexicalPackageDownloadCallback(); + _callback.setDownloadEventListeners(kbDownloadEventListeners); + + CloudApiTypes.CloudApiParam _param = new CloudApiTypes.CloudApiParam( + CloudApiTypes.ApiTarget.LexicalModelPackage, url); + + Toast.makeText(context, + context.getString(R.string.dictionary_download_start_in_background), + Toast.LENGTH_SHORT).show(); + + CloudDownloadMgr.getInstance().executeAsDownload( + context, _downloadid, null, _callback, _param); + } + + ((AppCompatActivity) context).finish(); } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudCatalogDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudCatalogDownloadCallback.java index 7a3e7b0b4b..cffbd79627 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudCatalogDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudCatalogDownloadCallback.java @@ -229,6 +229,11 @@ public class CloudCatalogDownloadCallback implements ICloudDownloadCallback _downloadSet = new CloudApiTypes.CloudDownloadSet( aDownloadIdentifier,aTargetModel); diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java index 7879268937..5739cc28da 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java @@ -2,8 +2,10 @@ package com.tavultesoft.kmea.data; import android.content.Context; import android.util.Log; +import android.widget.Toast; import com.tavultesoft.kmea.KeyboardEventHandler; +import com.tavultesoft.kmea.R; import com.tavultesoft.kmea.util.FileUtils; import java.io.File; @@ -26,8 +28,6 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback public static final String PARAM_DESTINATION_FILE_NAME = "destination_file_name"; - - public void setDownloadEventListeners(ArrayList aDownloadEventListeners) { downloadEventListeners.clear(); @@ -38,6 +38,7 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback this.keyboardInfo = aKeyboardInfo; } + @Override public void initializeContext(Context context) { dataDir = context.getDir("data", Context.MODE_PRIVATE); @@ -47,8 +48,6 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback public CloudKeyboardDownloadReturns extractCloudResultFromDownloadSet( CloudApiTypes.CloudDownloadSet aDownload) { - - int _result = FileUtils.DOWNLOAD_SUCCESS; for(CloudApiTypes.SingleCloudDownload _d:aDownload.getSingleDownloads()) { @@ -58,7 +57,7 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback try { String destination = dataDir.toString() + - File.separator + KMDefault_UndefinedPackageID + File.separator + File.separator; + File.separator + KMDefault_UndefinedPackageID + File.separator; String _filename = _d.getCloudParams().getAdditionalProperty(PARAM_DESTINATION_FILE_NAME,String.class); if (_filename==null) { @@ -78,7 +77,7 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback else { if (FileUtils.hasFontExtension(_d.getCloudParams().url)) - _result = -2; + _result = 2; else _result = FileUtils.DOWNLOAD_ERROR; } @@ -91,11 +90,22 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback @Override public void applyCloudDownloadToModel(Context aContext, Void aModel, CloudKeyboardDownloadReturns aCloudResult) { + Toast.makeText(aContext, + aContext.getString(R.string.keyboard_download_finished), + Toast.LENGTH_SHORT).show(); + if(keyboardInfo!=null) { KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_FINISHED, keyboardInfo, aCloudResult.kbdResult); } + + + } + + public static String createDownloadId(String aKeyboardId) + { + return "keyboarddata_" + aKeyboardId; } } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java index 48d54c8938..759c9f1da5 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java @@ -17,7 +17,6 @@ import org.json.JSONObject; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCallback> @@ -27,7 +26,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall CloudApiTypes.CloudApiReturns returnjson; CloudApiTypes.CloudApiParam params; HashMap keyboardInfo; - String keyboardId; + String additionalDownloadid; List additionalDownloads; } @@ -46,6 +45,11 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall downloadEventListeners.addAll(aDownloadEventListeners); } + @Override + public void initializeContext(Context context) { + + } + @Override public List extractCloudResultFromDownloadSet( CloudApiTypes.CloudDownloadSet> aDownload) { @@ -81,42 +85,51 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall processCloudResults(aCloudResult); + startDownloads(aContext, aCloudResult); + } + + private void startDownloads(Context aContext, List aCloudResult) { for(MetaDataResult _r:aCloudResult) { if(_r.additionalDownloads!=null) { - ; - - - if(_r.returnjson.target== CloudApiTypes.ApiTarget.Keyboard) { CloudKeyboardDataDownloadCallback _callback = new CloudKeyboardDataDownloadCallback(); _callback.setDownloadEventListeners(downloadEventListeners); _callback.setKeyboardInfo(_r.keyboardInfo); - _callback.initializeContext(aContext); + + if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_r.additionalDownloadid)) + { + continue; + } KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_STARTED, _r.keyboardInfo, 0); - CloudDownloadMgr.getInstance().executeAsDownload(aContext, - "keyboarddata_" + _r.keyboardId, null, _callback, + CloudDownloadMgr.getInstance().executeAsDownload(aContext, _r.additionalDownloadid, null, _callback, _r.additionalDownloads.toArray(new CloudApiTypes.CloudApiParam[0])); } else if(_r.returnjson.target== CloudApiTypes.ApiTarget.KeyBoardLexicalModels) { + + if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_r.additionalDownloadid)) + { + Toast.makeText(aContext, + aContext.getString(R.string.dictionary_download_is_running_in_background), + Toast.LENGTH_SHORT).show(); + continue; + } CloudLexicalPackageDownloadCallback _callback = new CloudLexicalPackageDownloadCallback(); _callback.setDownloadEventListeners(downloadEventListeners); - _callback.initializeContext(aContext); + + Toast.makeText(aContext, + aContext.getString(R.string.dictionary_download_start_in_background), + Toast.LENGTH_SHORT).show(); CloudDownloadMgr.getInstance().executeAsDownload(aContext, - "lexicalpackage_" + _r.keyboardId, null, _callback, + _r.additionalDownloadid, null, _callback, _r.additionalDownloads.toArray(new CloudApiTypes.CloudApiParam[0])); } - else - continue; - - - } } } @@ -135,12 +148,15 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall try { JSONObject modelInfo = lmData.getJSONObject(0); - if (modelInfo.has("packageFilename")) + + if (modelInfo.has("packageFilename") && modelInfo.has("id")) { + String _modelID = modelInfo.getString("id"); ArrayList urls = new ArrayList<>(); urls.add(new CloudApiTypes.CloudApiParam( CloudApiTypes.ApiTarget.KeyBoardLexicalModels, modelInfo.getString("packageFilename"))); + _r.additionalDownloadid = CloudLexicalPackageDownloadCallback.createDownloadId(_modelID); _r.additionalDownloads= urls; } } catch (JSONException e) { @@ -170,14 +186,9 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall if (options == null) { throw new IllegalStateException("JSON file does not contain a valid \"options\" object"); } - String kbBaseUri = options.optString(KMKeyboardDownloaderActivity.KMKey_KeyboardBaseURI, ""); - if (kbBaseUri.isEmpty()) { - throw new IllegalStateException("JSON file does not contain a valid \"keyboardBaseUri\" object"); - } - String fontBaseUri = options.optString(KMKeyboardDownloaderActivity.KMKey_FontBaseURI, ""); - // Keyman cloud keyboard distribution via JSON + // Keyman cloud _keyboard distribution via JSON JSONObject language = _kb_data.optJSONObject( KMKeyboardDownloaderActivity.KMKey_Language); if (language == null) { @@ -188,42 +199,23 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall JSONArray keyboards = language.getJSONArray(KMKeyboardDownloaderActivity.KMKey_LanguageKeyboards); - JSONObject keyboard = CloudDataJsonUtil.findMatchingKeyBoardByID(keyboards, _key_id); + JSONObject _keyboard = CloudDataJsonUtil.findMatchingKeyBoardByID(keyboards, _key_id); - _key_id = keyboard.getString(KMManager.KMKey_ID); - String _pkgID = keyboard.optString(KMManager.KMKey_PackageID, KMManager.KMDefault_UndefinedPackageID); + _key_id = _keyboard.getString(KMManager.KMKey_ID); + String _pkgID = _keyboard.optString(KMManager.KMKey_PackageID, KMManager.KMDefault_UndefinedPackageID); - String _kbName = keyboard.optString(KMManager.KMKey_Name, ""); - String _kbVersion = keyboard.optString(KMManager.KMKey_KeyboardVersion, "1.0"); - String _kbFilename = keyboard.optString(KMKeyboardDownloaderActivity.KMKey_Filename, ""); - if (_kbName.isEmpty() || _langName.isEmpty() || _kbFilename.isEmpty()) - throw new IllegalStateException("JSON file does not contain a valid base values for keyboard object"); + String _kbName = _keyboard.optString(KMManager.KMKey_Name, ""); + String _kbVersion = _keyboard.optString(KMManager.KMKey_KeyboardVersion, "1.0"); - String _js_filename = _kbFilename; - if (FileUtils.hasJavaScriptExtension(_kbFilename)) { + if (_kbName.isEmpty() || _langName.isEmpty()) + throw new IllegalStateException("JSON file does not contain a valid base values for _keyboard object"); - int start = _kbFilename.lastIndexOf("/"); - if (start < 0) { - start = 0; - } else { - start++; - } - if (!_kbFilename.contains("-")) { - _js_filename = _kbFilename.substring(start, _kbFilename.length() - 3) + "-" + _kbVersion + ".js"; - } else { - _js_filename = _kbFilename.substring(start); - } - } - String kbUrl = kbBaseUri + _kbFilename; ArrayList urls = new ArrayList<>(); - urls.add( - new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, kbUrl) - .setAdditionalProperty( - CloudKeyboardDataDownloadCallback.PARAM_DESTINATION_FILE_NAME, _js_filename)); + urls.add(prepareKeyboardPackageDownload(options, _keyboard)); - JSONObject jsonFont = keyboard.optJSONObject(KMManager.KMKey_Font); - JSONObject jsonOskFont = keyboard.optJSONObject(KMManager.KMKey_OskFont); + JSONObject jsonFont = _keyboard.optJSONObject(KMManager.KMKey_Font); + JSONObject jsonOskFont = _keyboard.optJSONObject(KMManager.KMKey_OskFont); if (jsonFont != null) { CloudDataJsonUtil.updateFontSourceToTTFFont(jsonFont); @@ -231,6 +223,8 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall if (jsonOskFont != null) { CloudDataJsonUtil.updateFontSourceToTTFFont(jsonOskFont); } + String fontBaseUri = options.optString(KMKeyboardDownloaderActivity.KMKey_FontBaseURI, ""); + ArrayList fontUrls = CloudDataJsonUtil.fontUrls(jsonFont, fontBaseUri, true); ArrayList oskFontUrls = CloudDataJsonUtil.fontUrls(jsonOskFont, fontBaseUri, true); if (fontUrls != null) { @@ -246,10 +240,11 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall } } - String _font = keyboard.optString(KMManager.KMKey_Font); - String _oskFont = keyboard.optString(KMManager.KMKey_OskFont); + String _font = _keyboard.optString(KMManager.KMKey_Font); + String _oskFont = _keyboard.optString(KMManager.KMKey_OskFont); - theKbData.keyboardId = _key_id; + + theKbData.additionalDownloadid = CloudKeyboardDataDownloadCallback.createDownloadId(_key_id); theKbData.keyboardInfo = CloudDataJsonUtil .createKeyBoardInfoMap( _pkgID, _lang_id, _langName, _key_id, _kbName, _kbVersion, _kbIsCustom, _font, _oskFont); @@ -261,5 +256,42 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall } } + private CloudApiTypes.CloudApiParam prepareKeyboardPackageDownload(JSONObject aOptions, JSONObject aKeyboard) { + + + String kbBaseUri = aOptions.optString(KMKeyboardDownloaderActivity.KMKey_KeyboardBaseURI, ""); + if (kbBaseUri.isEmpty()) { + throw new IllegalStateException("JSON file does not contain a valid \"keyboardBaseUri\" object"); + } + + String _kbVersion = aKeyboard.optString(KMManager.KMKey_KeyboardVersion, "1.0"); + String _kbFilename = aKeyboard.optString(KMKeyboardDownloaderActivity.KMKey_Filename, ""); + + if (_kbFilename.isEmpty()) + throw new IllegalStateException("JSON file does not contain a valid \"filename\" object"); + + String _js_filename = _kbFilename; + if (FileUtils.hasJavaScriptExtension(_kbFilename)) { + + int start = _kbFilename.lastIndexOf("/"); + if (start < 0) { + start = 0; + } else { + start++; + } + if (!_kbFilename.contains("-")) { + _js_filename = _kbFilename.substring(start, _kbFilename.length() - 3) + "-" + _kbVersion + ".js"; + } else { + _js_filename = _kbFilename.substring(start); + } + } + String kbUrl = kbBaseUri + _kbFilename; + + return new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, kbUrl) + .setAdditionalProperty( + CloudKeyboardDataDownloadCallback.PARAM_DESTINATION_FILE_NAME, _js_filename); + } + + } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java index 03c6696f8f..080a52dd8f 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java @@ -2,10 +2,12 @@ package com.tavultesoft.kmea.data; import android.content.Context; import android.util.Log; +import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.tavultesoft.kmea.KeyboardEventHandler; +import com.tavultesoft.kmea.R; import com.tavultesoft.kmea.packages.LexicalModelPackageProcessor; import com.tavultesoft.kmea.packages.PackageProcessor; import com.tavultesoft.kmea.util.FileUtils; @@ -33,13 +35,13 @@ public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallba private ArrayList downloadEventListeners = new ArrayList<>(); - public void setDownloadEventListeners(ArrayList aDownloadEventListeners) { downloadEventListeners.clear(); downloadEventListeners.addAll(aDownloadEventListeners); } + @Override public void initializeContext(Context context) { resourceRoot = new File(context.getDir("data", Context.MODE_PRIVATE).toString() + File.separator); @@ -94,11 +96,21 @@ public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallba @Override public void applyCloudDownloadToModel(Context aContext, Void aModel, CloudKeyboardDownloadReturns aCloudResult) { + Toast.makeText(aContext, + aContext.getString(R.string.dictionary_download_finished), + Toast.LENGTH_SHORT).show(); + if(aCloudResult.installedLexicalModels != null) { KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED, aCloudResult.installedLexicalModels, aCloudResult.kbdResult); } + + } + + public static String createDownloadId(String aModelID) + { + return "dictionary_" + aModelID; } } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/ICloudDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/ICloudDownloadCallback.java index 4fe402c732..5d63d09ecf 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/ICloudDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/ICloudDownloadCallback.java @@ -9,6 +9,7 @@ import android.content.Context; */ public interface ICloudDownloadCallback { + void initializeContext(Context context); /** * extract download result object from download set diff --git a/android/KMEA/app/src/main/res/values/strings.xml b/android/KMEA/app/src/main/res/values/strings.xml index df77ff5223..a76d35dd36 100644 --- a/android/KMEA/app/src/main/res/values/strings.xml +++ b/android/KMEA/app/src/main/res/values/strings.xml @@ -58,10 +58,18 @@ Checking to download dictionary… Downloading dictionary… The resource catalog is unavailable\n + + Catalog update started in background.\n The catalog is still downloading; please try again in a moment!\n + Downloading keyboard started in Background + The selected keyboard is already downloading; please try again in a moment! + Keyboard download is finished! + Downloading dictionary started in Background + The selected dictionary is already downloading; please try again in a moment! + Dictionary download is finished. - + Failed to access server!\n "All resources are up to date!" From 72bf48977489fccb7b23fe05b8b8f0b072ea93a1 Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Thu, 31 Oct 2019 11:55:26 +0700 Subject: [PATCH 03/12] docs: comments for better understanding --- .../kmea/KMKeyboardDownloaderActivity.java | 89 ++++++++++++------- .../kmea/data/CloudDataJsonUtil.java | 11 +++ .../CloudKeyboardDataDownloadCallback.java | 35 +++++++- .../data/CloudKeyboardDownloadReturns.java | 3 + ...CloudKeyboardMetaDataDownloadCallback.java | 63 ++++++++++--- .../CloudLexicalPackageDownloadCallback.java | 19 ++-- .../kmea/data/ICloudDownloadCallback.java | 4 + 7 files changed, 173 insertions(+), 51 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index d2fe30aa72..ce42006102 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -169,6 +169,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { * Used by the download method to handle asynchronous downloading and evaluation of * packages and keyboards. */ + @Deprecated static class DownloadTask extends AsyncTask { static class Result { public final Integer kbdResult; @@ -539,7 +540,12 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { new DownloadTask(context, showProgressDialog, aDownloadOnlyLexicalModel).execute(); } - public static void downloadUsingDownloadManager(final Context context, + /** + * Download in keyboards and lexical model using download manager. + * @param context the context + * @param aDownloadOnlyLexicalModel is lexical model download + */ + private static void downloadUsingDownloadManager(final Context context, final boolean aDownloadOnlyLexicalModel) { if(aDownloadOnlyLexicalModel) @@ -552,19 +558,59 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { } } - private static void downloadKeyboardUsingDownloadManager(Context context) { - - - + /** + * prepare and execute keyboard download using downloadmanager. + * @param context the context + */ + private static void downloadKeyboardUsingDownloadManager(Context context) + { if (pkgID == null || pkgID.trim().isEmpty() || (!isCustom && (langID == null || langID.trim().isEmpty() || kbID == null || kbID.trim().isEmpty()))) { throw new IllegalStateException("Invalid keyboard"); } - String deviceType = CloudDataJsonUtil.getDeviceTypeForCloudQuery(context); + + List cloudQueries = getPrepareCloudQueriesForKeyboardDownload(context); + + String _downloadid= CloudKeyboardMetaDataDownloadCallback.createDownloadId(langID , kbID); + + if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_downloadid) + || CloudDownloadMgr.getInstance().alreadyDownloadingData( + CloudKeyboardDataDownloadCallback.createDownloadId(kbID))) + { + Toast.makeText(context, + context.getString(R.string.keyboard_download_is_running_in_background), + Toast.LENGTH_SHORT).show(); + } + else + { + CloudKeyboardMetaDataDownloadCallback _callback = new CloudKeyboardMetaDataDownloadCallback(); + _callback.setDownloadEventListeners(kbDownloadEventListeners); + + Toast.makeText(context, + context.getString(R.string.keyboard_download_start_in_background), + Toast.LENGTH_SHORT).show(); + + CloudDownloadMgr.getInstance().executeAsDownload( + context, _downloadid, null, _callback, + cloudQueries.toArray(new CloudApiTypes.CloudApiParam[0])); + } + + ((AppCompatActivity) context).finish(); + } + + /** + * Prepare the cloud queries for keyboard metadata download. + * @param context the context + * @return the result + */ + private static List getPrepareCloudQueriesForKeyboardDownload(Context context) + { List cloudQueries = new ArrayList<>(); + String deviceType = CloudDataJsonUtil.getDeviceTypeForCloudQuery(context); + if (isCustom) { //TODO: will end up in an exception during download??? cloudQueries.add(new CloudApiTypes.CloudApiParam( @@ -588,34 +634,13 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { CloudApiTypes.ApiTarget.KeyBoardLexicalModels, _remoteLexicalModelUrl) .setType(CloudApiTypes.JSONType.Array)); } - - String _downloadid= "metadata_" + langID + "_" + kbID; - - if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_downloadid) - || CloudDownloadMgr.getInstance().alreadyDownloadingData( - CloudKeyboardDataDownloadCallback.createDownloadId(kbID))) - { - Toast.makeText(context, - context.getString(R.string.keyboard_download_is_running_in_background), - Toast.LENGTH_SHORT).show(); - } - else - { - CloudKeyboardMetaDataDownloadCallback _callback = new CloudKeyboardMetaDataDownloadCallback(); - _callback.setDownloadEventListeners(kbDownloadEventListeners); - - Toast.makeText(context, - context.getString(R.string.keyboard_download_start_in_background), - Toast.LENGTH_SHORT).show(); - - CloudDownloadMgr.getInstance().executeAsDownload( - context, _downloadid, null, _callback, - cloudQueries.toArray(new CloudApiTypes.CloudApiParam[0])); - } - - ((AppCompatActivity) context).finish(); + return cloudQueries; } + /** + * prepare and execute lexical model download using downloadmanager. + * @param context the context + */ private static void downloadLexicalModelUsingDownloadManager(Context context) { diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java index 684f58aa1c..274c130aa4 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java @@ -237,6 +237,11 @@ public class CloudDataJsonUtil { return new File(context.getCacheDir(), jsonLexicalCacheFilename); } + /** + * retrieve a json object from a downloaded file. + * @param aDownload the download + * @return the result + */ public static CloudApiTypes.CloudApiReturns retrieveJsonFromDownload( CloudApiTypes.SingleCloudDownload aDownload) { JSONParser jsonParser = new JSONParser(); @@ -397,6 +402,12 @@ public class CloudDataJsonUtil { return keyboard; } + + /** + * select device type for api queries. + * @param aContext a context + * @return the result + */ public static String getDeviceTypeForCloudQuery(Context aContext) { String deviceType = aContext.getString(R.string.device_type); diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java index 5739cc28da..36b144d26a 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDataDownloadCallback.java @@ -15,6 +15,10 @@ import java.util.HashMap; import static com.tavultesoft.kmea.KMManager.KMDefault_UndefinedPackageID; +/** + * Install keyboard data, when download is finished. + * Could be keyboard packages or fonts. + */ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback< Void, CloudKeyboardDownloadReturns> { @@ -26,14 +30,34 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback private ArrayList downloadEventListeners = new ArrayList<>(); private HashMap keyboardInfo; + /** + * Additional Cloud API parameter: + * Parameter to force a special destination file name during installation. + * Default name is the file name of the url. + */ public static final String PARAM_DESTINATION_FILE_NAME = "destination_file_name"; + /** + * Additional Cloud API parameter: + * Parameter to force a special destination file name during installation. + * Default name is the file name of the url. + */ + public static final String PARAM_PACKAGE = "package"; + + /** + * listeners to inform after installation is completed. + * @param aDownloadEventListeners the listeners + */ public void setDownloadEventListeners(ArrayList aDownloadEventListeners) { downloadEventListeners.clear(); downloadEventListeners.addAll(aDownloadEventListeners); } + /** + * Keyboard meta data. + * @param aKeyboardInfo the keyboard + */ public void setKeyboardInfo(HashMap aKeyboardInfo) { this.keyboardInfo = aKeyboardInfo; } @@ -56,8 +80,9 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback try { + String _pkg = _d.getCloudParams().getAdditionalProperty(PARAM_PACKAGE,String.class); String destination = dataDir.toString() + - File.separator + KMDefault_UndefinedPackageID + File.separator; + File.separator + _pkg + File.separator; String _filename = _d.getCloudParams().getAdditionalProperty(PARAM_DESTINATION_FILE_NAME,String.class); if (_filename==null) { @@ -99,11 +124,13 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_FINISHED, keyboardInfo, aCloudResult.kbdResult); } - - - } + /** + * create a download id for the keyboard data. + * @param aKeyboardId the keyboard id + * @return the result + */ public static String createDownloadId(String aKeyboardId) { return "keyboarddata_" + aKeyboardId; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDownloadReturns.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDownloadReturns.java index 967d91a5ac..8aaaa21d84 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDownloadReturns.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardDownloadReturns.java @@ -3,6 +3,9 @@ package com.tavultesoft.kmea.data; import java.util.List; import java.util.Map; +/** + * key board and lexical model download result. + */ public class CloudKeyboardDownloadReturns { public final Integer kbdResult; public final List> installedLexicalModels; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java index 759c9f1da5..2afa320cbc 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java @@ -18,9 +18,15 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +/** + * Start the keyboard download when keyboard metadata is downloaded. + */ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCallback> { + /** + * the metadata result and all necessary downloads which should be started. + */ public static class MetaDataResult { CloudApiTypes.CloudApiReturns returnjson; @@ -32,14 +38,25 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall private static final String TAG = "CloudKeyboardMetaDldCb"; - private static ArrayList downloadEventListeners = new ArrayList<>(); - + private ArrayList downloadEventListeners = new ArrayList<>(); + /** + * Additional Cloud API parameter: Is custom keyboard. + */ public static final String PARAM_IS_CUSTOM = "is_custom"; + /** + * Additional Cloud API parameter: language id. + */ public static final String PARAM_LANG_ID = "lang_id"; + /** + * Additional Cloud API parameter: keyboard id. + */ public static final String PARAM_KB_ID = "kb_id"; - + /** + * Listeners to notify about starting the data download. + * @param aDownloadEventListeners + */ public void setDownloadEventListeners(ArrayList aDownloadEventListeners) { downloadEventListeners.clear(); downloadEventListeners.addAll(aDownloadEventListeners); @@ -88,8 +105,13 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall startDownloads(aContext, aCloudResult); } - private void startDownloads(Context aContext, List aCloudResult) { - for(MetaDataResult _r:aCloudResult) + /** + * Start the keyboard data and lexical model download. + * @param aContext the context + * @param aMetaDataResult the meta data result + */ + private void startDownloads(Context aContext, List aMetaDataResult) { + for(MetaDataResult _r:aMetaDataResult) { if(_r.additionalDownloads!=null) { @@ -134,8 +156,12 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall } } - private void processCloudResults(List aCloudResult) { - for(MetaDataResult _r:aCloudResult) + /** + * process the meta data result and prepare the additional downloads. + * @param aMetaDataResult the meta data results + */ + private void processCloudResults(List aMetaDataResult) { + for(MetaDataResult _r:aMetaDataResult) { if(_r.returnjson.target== CloudApiTypes.ApiTarget.Keyboard) { @@ -229,13 +255,17 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall ArrayList oskFontUrls = CloudDataJsonUtil.fontUrls(jsonOskFont, fontBaseUri, true); if (fontUrls != null) { for (String url : fontUrls) { - urls.add(new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, url)); + urls.add(new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, url) + .setAdditionalProperty( + CloudKeyboardDataDownloadCallback.PARAM_PACKAGE, _pkgID)); } } if (oskFontUrls != null) { for (String url : oskFontUrls) { if (!urls.contains(url)) - urls.add(new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, url)); + urls.add(new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, url) + .setAdditionalProperty( + CloudKeyboardDataDownloadCallback.PARAM_PACKAGE, _pkgID)); ; } } @@ -285,13 +315,26 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall _js_filename = _kbFilename.substring(start); } } + + String _pkgID = aKeyboard.optString(KMManager.KMKey_PackageID, KMManager.KMDefault_UndefinedPackageID); String kbUrl = kbBaseUri + _kbFilename; return new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, kbUrl) + .setAdditionalProperty( + CloudKeyboardDataDownloadCallback.PARAM_PACKAGE, _pkgID) .setAdditionalProperty( CloudKeyboardDataDownloadCallback.PARAM_DESTINATION_FILE_NAME, _js_filename); } - + /** + * create a download id for the keyboard metadata. + * @param aLanguageId the language id + * @param aKeyboardId the keyboard id + * @return the result + */ + public static String createDownloadId(String aLanguageId, String aKeyboardId) + { + return "metadata_" + aLanguageId + "_" + aKeyboardId; + } } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java index 080a52dd8f..91106ad61a 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudLexicalPackageDownloadCallback.java @@ -24,6 +24,9 @@ import java.util.Map; import static com.tavultesoft.kmea.KMManager.KMDefault_UndefinedPackageID; +/** + * Install lexical model. + */ public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallback< Void, CloudKeyboardDownloadReturns> { @@ -35,6 +38,10 @@ public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallba private ArrayList downloadEventListeners = new ArrayList<>(); + /** + * listeners to inform after installation is completed. + * @param aDownloadEventListeners the listeners + */ public void setDownloadEventListeners(ArrayList aDownloadEventListeners) { downloadEventListeners.clear(); @@ -52,7 +59,6 @@ public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallba public CloudKeyboardDownloadReturns extractCloudResultFromDownloadSet( CloudApiTypes.CloudDownloadSet aDownload) { - LexicalModelPackageProcessor kmpProcessor = new LexicalModelPackageProcessor(resourceRoot); List> installedLexicalModels = null; @@ -105,12 +111,15 @@ public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallba KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED, aCloudResult.installedLexicalModels, aCloudResult.kbdResult); } - - } - public static String createDownloadId(String aModelID) + /** + * create a download id for the model. + * @param aModelId the lexical model id + * @return the result + */ + public static String createDownloadId(String aModelId) { - return "dictionary_" + aModelID; + return "dictionary_" + aModelId; } } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/ICloudDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/ICloudDownloadCallback.java index 5d63d09ecf..5fe73b75c6 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/ICloudDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/ICloudDownloadCallback.java @@ -9,6 +9,10 @@ import android.content.Context; */ public interface ICloudDownloadCallback { + /** + * Initialize callback using context. + * @param context the context + */ void initializeContext(Context context); /** From bba8c51af9309653ecccc4c728864cff02ff7ba9 Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Thu, 31 Oct 2019 13:24:31 +0700 Subject: [PATCH 04/12] docs: comments for better understanding --- .../CloudKeyboardMetaDataDownloadCallback.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java index 2afa320cbc..6e6ec50087 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java @@ -193,6 +193,10 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall } } + /** + * handle meta data result. + * @param theKbData the data + */ private void handleKeyBoardMetaData(MetaDataResult theKbData) { if (theKbData.params.getAdditionalProperty(PARAM_IS_CUSTOM,Boolean.class)) { @@ -286,9 +290,14 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall } } - private CloudApiTypes.CloudApiParam prepareKeyboardPackageDownload(JSONObject aOptions, JSONObject aKeyboard) { - - + /** + * prepare keyboard package download. + * @param aOptions the options from json + * @param aKeyboard the keyboard + * @return the result + */ + private CloudApiTypes.CloudApiParam prepareKeyboardPackageDownload(JSONObject aOptions, JSONObject aKeyboard) + { String kbBaseUri = aOptions.optString(KMKeyboardDownloaderActivity.KMKey_KeyboardBaseURI, ""); if (kbBaseUri.isEmpty()) { throw new IllegalStateException("JSON file does not contain a valid \"keyboardBaseUri\" object"); From 8b65f6bd5c88787ad46d4f85b11d36c9c5fb4282 Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Thu, 31 Oct 2019 14:12:00 +0700 Subject: [PATCH 05/12] fix: small changes --- .../com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java | 2 +- .../kmea/data/CloudKeyboardMetaDataDownloadCallback.java | 2 +- .../java/com/tavultesoft/kmea/data/CloudRepository.java | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index ce42006102..7ba23e54d5 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -402,7 +402,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { if (jsonOskFont != null) { CloudDataJsonUtil.updateFontSourceToTTFFont(jsonOskFont); } - ArrayList fontUrls = CloudDataJsonUtil.fontUrls(jsonFont, fontBaseUri, true); + ArrayList fontUrls = CloudDataJsonUtil.fontUrls(jsonFont, fontBaseUri, false); ArrayList oskFontUrls = CloudDataJsonUtil.fontUrls(jsonOskFont, fontBaseUri, true); if (fontUrls != null) urls.addAll(fontUrls); diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java index 6e6ec50087..a09dee7481 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java @@ -255,7 +255,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall } String fontBaseUri = options.optString(KMKeyboardDownloaderActivity.KMKey_FontBaseURI, ""); - ArrayList fontUrls = CloudDataJsonUtil.fontUrls(jsonFont, fontBaseUri, true); + ArrayList fontUrls = CloudDataJsonUtil.fontUrls(jsonFont, fontBaseUri, false); ArrayList oskFontUrls = CloudDataJsonUtil.fontUrls(jsonOskFont, fontBaseUri, true); if (fontUrls != null) { for (String url : fontUrls) { diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java index 025967a3e5..5120c7ad08 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java @@ -164,7 +164,7 @@ public class CloudRepository { preCacheDataSet(context,updateHandler,onSuccess,onFailure); if(USE_DOWNLOAD_MANAGER) - downloadCatalogFromServer(context,updateHandler,onSuccess,onFailure); + downloadMetaDataFromServer(context,updateHandler,onSuccess,onFailure); } /** @@ -188,7 +188,7 @@ public class CloudRepository { preCacheDataSet(context,updateHandler,onSuccess,onFailure); - downloadCatalogFromServer(context,updateHandler,onSuccess,onFailure); + downloadMetaDataFromServer(context,updateHandler,onSuccess,onFailure); } @@ -307,7 +307,7 @@ public class CloudRepository { * @param onFailure A callback to be triggered upon failure of a query. * @return A Dataset object implementing the Adapter interface to be asynchronously filled. */ - private void downloadCatalogFromServer(@NonNull Context context, UpdateHandler updateHandler, Runnable onSuccess, Runnable onFailure) { + private void downloadMetaDataFromServer(@NonNull Context context, UpdateHandler updateHandler, Runnable onSuccess, Runnable onFailure) { boolean loadKeyboardsFromCache = this.shouldUseCache(context, CloudDataJsonUtil.getKeyboardCacheFile(context)); boolean loadLexicalModelsFromCache = this.shouldUseCache(context, CloudDataJsonUtil.getLexicalModelCacheFile(context)); From d6de9e3afd57c87e5a82b5dfd986cd8dcd7eff85 Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Mon, 4 Nov 2019 17:08:21 +0700 Subject: [PATCH 06/12] feat[android]: new keyboard marker --- .../com/tavultesoft/kmapro/MainActivity.java | 6 +- .../kmea/KMKeyboardPickerAdapter.java | 8 +- .../kmea/KeyboardListActivity.java | 3 +- .../kmea/KeyboardPickerActivity.java | 95 +++++++++++++------ .../kmea/LanguageListActivity.java | 7 +- .../com/tavultesoft/kmea/data/Keyboard.java | 7 ++ .../KMEA/app/src/main/res/values/strings.xml | 1 + 7 files changed, 91 insertions(+), 36 deletions(-) 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 6cae94598d..33aeb3795e 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 @@ -854,7 +854,8 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi kbInfo.put(KMManager.KMKey_OskFont, kOskFont); if (i == 0) { if (KMManager.addKeyboard(this, kbInfo)) { - KMManager.setKeyboard(packageID, keyboardID, langId, keyboardName, langName, kFont, kOskFont); + if (!KMKeyboardDownloaderActivity.USE_DOWNLOAD_MANAGER) + KMManager.setKeyboard(packageID, keyboardID, langId, keyboardName, langName, kFont, kOskFont); } } else { KMManager.addKeyboard(this, kbInfo); @@ -862,7 +863,8 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi } } else { if (KMManager.addKeyboard(this, keyboardInfo)) { - KMManager.setKeyboard(packageID, keyboardID, languageID, keyboardName, languageName, kFont, kOskFont); + if (!KMKeyboardDownloaderActivity.USE_DOWNLOAD_MANAGER) + KMManager.setKeyboard(packageID, keyboardID, languageID, keyboardName, languageName, kFont, kOskFont); } } } else { diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java index 628e4ef966..18251633e6 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java @@ -74,8 +74,12 @@ final class KMKeyboardPickerAdapter extends NestedAdapter> keyboardsList = null; private static ArrayList> lexicalModelsList = null; @@ -176,6 +177,39 @@ public final class KeyboardPickerActivity extends AppCompatActivity { int curKbPos = getCurrentKeyboardIndex(); setSelection(curKbPos); + + KMKeyboard.addOnKeyboardEventListener(new KeyboardEventHandler.OnKeyboardEventListener() { + @Override + public void onKeyboardLoaded(KMManager.KeyboardType keyboardType) { + + } + + @Override + public void onKeyboardChanged(String newKeyboard) { + int _index = getKeyboardIndex(context,newKeyboard); + if(_index>=0) + { + Map _keyboard = keyboardsList.get(_index); + if(_keyboard==null) + return; + if(_keyboard.get(KMKEY_INTERNAL_NEW_KEYBOARD)==null) + return; + _keyboard.remove(KMKEY_INTERNAL_NEW_KEYBOARD); + saveList(context, KMManager.KMFilename_KeyboardsList); + notifyKeyboardsUpdate(context); + } + } + + @Override + public void onKeyboardShown() { + + } + + @Override + public void onKeyboardDismissed() { + + } + }); } @Override @@ -343,9 +377,12 @@ public final class KeyboardPickerActivity extends AppCompatActivity { if (kbKey.length() >= 3) { int x = getKeyboardIndex(context, kbKey); if (x >= 0) { + if(keyboardsList.get(x).get(KMKEY_INTERNAL_NEW_KEYBOARD)!=null) + keyboardInfo.put(KMKEY_INTERNAL_NEW_KEYBOARD,KMKEY_INTERNAL_NEW_KEYBOARD); keyboardsList.set(x, keyboardInfo); result = saveList(context, KMManager.KMFilename_KeyboardsList); } else { + keyboardInfo.put(KMKEY_INTERNAL_NEW_KEYBOARD,KMKEY_INTERNAL_NEW_KEYBOARD); keyboardsList.add(keyboardInfo); result = saveList(context, KMManager.KMFilename_KeyboardsList); if (!result) { diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguageListActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguageListActivity.java index 7d77337573..8e1622ac62 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguageListActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguageListActivity.java @@ -137,7 +137,9 @@ public final class LanguageListActivity extends AppCompatActivity implements OnK if (!pkgID.equals(KMManager.KMDefault_UndefinedPackageID)) { // Custom keyboard already exists in packages/ so just add the language association KeyboardPickerActivity.addKeyboard(context, kbInfo); - KMManager.setKeyboard(pkgID, kbID, langID, kbName, language.name, kFont, kOskFont); + + if (!KMKeyboardDownloaderActivity.USE_DOWNLOAD_MANAGER) + KMManager.setKeyboard(pkgID, kbID, langID, kbName, language.name, kFont, kOskFont); Toast.makeText(context, "Keyboard installed", Toast.LENGTH_SHORT).show(); setResult(RESULT_OK); ((AppCompatActivity) context).finish(); @@ -214,7 +216,8 @@ public final class LanguageListActivity extends AppCompatActivity implements OnK String kOskFont = keyboardInfo.get(KMManager.KMKey_OskFont); KeyboardPickerActivity.addKeyboard(this, keyboardInfo); - KMManager.setKeyboard(packageID, keyboardID, languageID, keyboardName, languageName, kFont, kOskFont); + if (!KMKeyboardDownloaderActivity.USE_DOWNLOAD_MANAGER) + KMManager.setKeyboard(packageID, keyboardID, languageID, keyboardName, languageName, kFont, kOskFont); if (result == 2) { Toast.makeText(context, context.getString(R.string.font_failed_to_download), Toast.LENGTH_LONG).show(); diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/Keyboard.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/Keyboard.java index 567d9e0a59..fa088416a8 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/Keyboard.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/Keyboard.java @@ -4,6 +4,7 @@ import android.os.Bundle; import com.tavultesoft.kmea.KMKeyboardDownloaderActivity; import com.tavultesoft.kmea.KMManager; +import com.tavultesoft.kmea.KeyboardPickerActivity; import java.io.Serializable; import java.util.Map; @@ -26,6 +27,12 @@ public class Keyboard implements Serializable, LanguageResource { this.map = kbdData; } + + + public boolean isNewKeyboard() { + return map.get(KeyboardPickerActivity.KMKEY_INTERNAL_NEW_KEYBOARD)!=null; + } + public String getResourceId() { return this.map.get(KMManager.KMKey_KeyboardID); } diff --git a/android/KMEA/app/src/main/res/values/strings.xml b/android/KMEA/app/src/main/res/values/strings.xml index a76d35dd36..aa8b6bf840 100644 --- a/android/KMEA/app/src/main/res/values/strings.xml +++ b/android/KMEA/app/src/main/res/values/strings.xml @@ -51,6 +51,7 @@ Keyboard version Help link Uninstall keyboard + [new] Getting dictionary catalog.\nThis may take a while… From bc30c183780ccddae575991e718a4bfa1c2a0637 Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Mon, 4 Nov 2019 17:09:59 +0700 Subject: [PATCH 07/12] fix[android]: fix text --- .../main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java index 18251633e6..848af2b8b0 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardPickerAdapter.java @@ -76,7 +76,7 @@ final class KMKeyboardPickerAdapter extends NestedAdapter Date: Tue, 5 Nov 2019 09:45:42 +0700 Subject: [PATCH 08/12] docs[android]: add todos/refactoring suggestions --- .../com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java | 3 +++ .../main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java | 2 ++ .../java/com/tavultesoft/kmea/LanguagesSettingsActivity.java | 1 + .../main/java/com/tavultesoft/kmea/data/CloudRepository.java | 2 ++ 4 files changed, 8 insertions(+) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index 7ba23e54d5..95718cac28 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -36,7 +36,9 @@ import static com.tavultesoft.kmea.KMManager.KMDefault_UndefinedPackageID; public class KMKeyboardDownloaderActivity extends AppCompatActivity { // Bundle Keys + // Cloud + //TODO: Should be removed with the old implementation when downloadmanager impl works public static boolean USE_DOWNLOAD_MANAGER = true; public static final String ARG_PKG_ID = "KMKeyboardActivity.pkgID"; @@ -75,6 +77,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { public static final String KMKey_KeyboardBaseURI = "keyboardBaseUri"; public static final String KMKey_FontBaseURI = "fontBaseUri"; + //TODO: use keyboard model class, should not be static private static String pkgID; private static String kbID; private static String langID; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java index 30fef0bf2e..10ed3da015 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java @@ -44,6 +44,7 @@ import java.util.Map; public final class KeyboardPickerActivity extends AppCompatActivity { + //TODO: view instances should not be static private static Toolbar toolbar = null; private static ListView listView = null; private static Button closeButton = null; @@ -51,6 +52,7 @@ public final class KeyboardPickerActivity extends AppCompatActivity { public static final String KMKEY_INTERNAL_NEW_KEYBOARD = "_internal_new_keyboard_"; + // TODO: Refactoring to remove keyboard selection into own keyboard manager class (MVC) // Lists of installed keyboards and installed lexical models private static ArrayList> keyboardsList = null; private static ArrayList> lexicalModelsList = null; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguagesSettingsActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguagesSettingsActivity.java index ef757c6e8e..ad9aca38b4 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguagesSettingsActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguagesSettingsActivity.java @@ -53,6 +53,7 @@ public final class LanguagesSettingsActivity extends AppCompatActivity // ********* ONLY USED BY UPDATE CODE *********** + //TODO: Refactoring to separate update logic from view private static boolean updateCheckFailed = false; private static boolean updateFailed = false; private static Calendar lastUpdateCheck = null; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java index 5120c7ad08..dc843a7281 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudRepository.java @@ -28,7 +28,9 @@ public class CloudRepository { static public final CloudRepository shared = new CloudRepository(); private static final String TAG = "CloudRepository"; + //TODO: Should be removed with the old implementation when downloadmanager impl works public static final boolean USE_DOWNLOAD_MANAGER = true; + public static final String DOWNLOAD_IDENTIFIER_CATALOGUE = "catalogue"; private Dataset memCachedDataset; From b9765970750fbe8461adcd7279298dfca01257a2 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 5 Nov 2019 13:07:33 +0700 Subject: [PATCH 09/12] fix(android): Fix the API target type to download lexical model package --- .../kmea/data/CloudKeyboardMetaDataDownloadCallback.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java index a09dee7481..32eff13dd6 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java @@ -180,7 +180,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall String _modelID = modelInfo.getString("id"); ArrayList urls = new ArrayList<>(); urls.add(new CloudApiTypes.CloudApiParam( - CloudApiTypes.ApiTarget.KeyBoardLexicalModels, + CloudApiTypes.ApiTarget.LexicalModelPackage, modelInfo.getString("packageFilename"))); _r.additionalDownloadid = CloudLexicalPackageDownloadCallback.createDownloadId(_modelID); _r.additionalDownloads= urls; From 7055b5816c01ec521e6df93ee2211264d0de641c Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Wed, 6 Nov 2019 11:17:59 +0700 Subject: [PATCH 10/12] fix[android]: review base changes (renames, comments) --- .../kmea/KMKeyboardDownloaderActivity.java | 4 ++-- .../tavultesoft/kmea/data/CloudApiTypes.java | 20 +++++++++++++++++++ .../kmea/data/CloudDataJsonUtil.java | 6 +++--- ...CloudKeyboardMetaDataDownloadCallback.java | 4 ++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index 95718cac28..13bde5e388 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -381,7 +381,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { JSONArray keyboards = language.getJSONArray(KMKey_LanguageKeyboards); - JSONObject keyboard = CloudDataJsonUtil.findMatchingKeyBoardByID(keyboards,kbID); + JSONObject keyboard = CloudDataJsonUtil.findMatchingKeyboardByID(keyboards,kbID); kbID = keyboard.getString(KMManager.KMKey_ID); pkgID = keyboard.optString(KMManager.KMKey_PackageID, KMManager.KMDefault_UndefinedPackageID); @@ -503,7 +503,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { protected void notifyListeners(KeyboardEventHandler.EventType eventType, int result) { if (kbDownloadEventListeners != null) { HashMap keyboardInfo = - CloudDataJsonUtil.createKeyBoardInfoMap(pkgID,langID,langName,kbID,kbName,kbVersion,kbIsCustom,font,oskFont); + CloudDataJsonUtil.createKeyboardInfoMap(pkgID,langID,langName,kbID,kbName,kbVersion,kbIsCustom,font,oskFont); KeyboardEventHandler.notifyListeners(kbDownloadEventListeners, eventType, keyboardInfo, result); } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java index bc908b2ddb..17f24b1a67 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java @@ -36,11 +36,31 @@ public class CloudApiTypes { } public enum ApiTarget { + /** + * Catalog download: available keyboards including meta data. + */ Keyboards, + /** + * Catalog download: available lexical models including meta data. + */ LexicalModels, + /** + * Keyboard download: keyboard meta data for the selected keyboard. + */ Keyboard, + /** + * Keyboard download: lexical models meta data for the language of the selected keyboard. + */ KeyBoardLexicalModels, + /** + * Keyboard download: download keyboard data package and fonts. + */ KeyboardData, + /** + * Lexical download: download lexical model package + * Used for single lexical model download and + * automatic lexical model download during keyboard download + */ LexicalModelPackage, } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java index 79f1e26dde..15c27a6946 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java @@ -32,7 +32,7 @@ public class CloudDataJsonUtil { //no instances } - public static HashMap createKeyBoardInfoMap(String aPackageId,String aLanguageId, String aLanguageName, String aKeyboardId, + public static HashMap createKeyboardInfoMap(String aPackageId,String aLanguageId, String aLanguageName, String aKeyboardId, String aKeyboardName, String aKeyboardVersion, String anIsCustomKeyBoard, String aFont, String aOskFont) { @@ -78,7 +78,7 @@ public class CloudDataJsonUtil { String kbFont = keyboardJSON.optString(KMManager.KMKey_Font, ""); //String kbKey = String.format("%s_%s", langID, kbID); - HashMap hashMap = createKeyBoardInfoMap(null,langID,langName,kbID,kbName,kbVersion,isCustom,kbFont,null); + HashMap hashMap = createKeyboardInfoMap(null,langID,langName,kbID,kbName,kbVersion,isCustom,kbFont,null); // if (keyboardModifiedDates.get(kbID) == null) { @@ -382,7 +382,7 @@ public class CloudDataJsonUtil { return urls; } - public static JSONObject findMatchingKeyBoardByID(JSONArray aKeyboards, String aKbId) + public static JSONObject findMatchingKeyboardByID(JSONArray aKeyboards, String aKbId) throws IllegalStateException, JSONException { if (aKeyboards == null) { diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java index 32eff13dd6..2113ca9bec 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java @@ -229,7 +229,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall JSONArray keyboards = language.getJSONArray(KMKeyboardDownloaderActivity.KMKey_LanguageKeyboards); - JSONObject _keyboard = CloudDataJsonUtil.findMatchingKeyBoardByID(keyboards, _key_id); + JSONObject _keyboard = CloudDataJsonUtil.findMatchingKeyboardByID(keyboards, _key_id); _key_id = _keyboard.getString(KMManager.KMKey_ID); String _pkgID = _keyboard.optString(KMManager.KMKey_PackageID, KMManager.KMDefault_UndefinedPackageID); @@ -280,7 +280,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall theKbData.additionalDownloadid = CloudKeyboardDataDownloadCallback.createDownloadId(_key_id); theKbData.keyboardInfo = CloudDataJsonUtil - .createKeyBoardInfoMap( + .createKeyboardInfoMap( _pkgID, _lang_id, _langName, _key_id, _kbName, _kbVersion, _kbIsCustom, _font, _oskFont); theKbData.additionalDownloads = urls; } From 3aad415144322297efd74db510265be2bb97782e Mon Sep 17 00:00:00 2001 From: Sandra Forberger Date: Wed, 6 Nov 2019 13:36:08 +0700 Subject: [PATCH 11/12] fix[android]: variable names --- .../tavultesoft/kmea/KMKeyboardDownloaderActivity.java | 2 +- .../java/com/tavultesoft/kmea/data/CloudApiTypes.java | 2 +- .../java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java | 4 ++-- .../kmea/data/CloudKeyboardMetaDataDownloadCallback.java | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index 13bde5e388..d4c2b036ab 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -634,7 +634,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { String _remoteLexicalModelUrl = String.format("%s?q=bcp47:%s", kKeymanApiModelURL, langID); cloudQueries.add(new CloudApiTypes.CloudApiParam( - CloudApiTypes.ApiTarget.KeyBoardLexicalModels, _remoteLexicalModelUrl) + CloudApiTypes.ApiTarget.KeyboardLexicalModels, _remoteLexicalModelUrl) .setType(CloudApiTypes.JSONType.Array)); } return cloudQueries; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java index 17f24b1a67..ecc758e2eb 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudApiTypes.java @@ -51,7 +51,7 @@ public class CloudApiTypes { /** * Keyboard download: lexical models meta data for the language of the selected keyboard. */ - KeyBoardLexicalModels, + KeyboardLexicalModels, /** * Keyboard download: download keyboard data package and fonts. */ diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java index 15c27a6946..3072627d0d 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudDataJsonUtil.java @@ -33,7 +33,7 @@ public class CloudDataJsonUtil { } public static HashMap createKeyboardInfoMap(String aPackageId,String aLanguageId, String aLanguageName, String aKeyboardId, - String aKeyboardName, String aKeyboardVersion, String anIsCustomKeyBoard, + String aKeyboardName, String aKeyboardVersion, String anIsCustomKeyboard, String aFont, String aOskFont) { HashMap keyboardInfo = new HashMap(); @@ -44,7 +44,7 @@ public class CloudDataJsonUtil { keyboardInfo.put(KMManager.KMKey_KeyboardName, aKeyboardName); keyboardInfo.put(KMManager.KMKey_LanguageName, aLanguageName); keyboardInfo.put(KMManager.KMKey_KeyboardVersion, aKeyboardVersion); - keyboardInfo.put(KMManager.KMKey_CustomKeyboard, anIsCustomKeyBoard); + keyboardInfo.put(KMManager.KMKey_CustomKeyboard, anIsCustomKeyboard); keyboardInfo.put(KMManager.KMKey_Font, aFont); if (aOskFont != null) keyboardInfo.put(KMManager.KMKey_OskFont, aOskFont); diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java index 2113ca9bec..6971be7bb3 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/CloudKeyboardMetaDataDownloadCallback.java @@ -132,7 +132,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall CloudDownloadMgr.getInstance().executeAsDownload(aContext, _r.additionalDownloadid, null, _callback, _r.additionalDownloads.toArray(new CloudApiTypes.CloudApiParam[0])); } - else if(_r.returnjson.target== CloudApiTypes.ApiTarget.KeyBoardLexicalModels) { + else if(_r.returnjson.target== CloudApiTypes.ApiTarget.KeyboardLexicalModels) { if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_r.additionalDownloadid)) { @@ -165,9 +165,9 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall { if(_r.returnjson.target== CloudApiTypes.ApiTarget.Keyboard) { - handleKeyBoardMetaData(_r); + handleKeyboardMetaData(_r); } - if(_r.returnjson.target== CloudApiTypes.ApiTarget.KeyBoardLexicalModels) + if(_r.returnjson.target== CloudApiTypes.ApiTarget.KeyboardLexicalModels) { JSONArray lmData = _r.returnjson.jsonArray; if (lmData != null && lmData.length() > 0) { @@ -197,7 +197,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall * handle meta data result. * @param theKbData the data */ - private void handleKeyBoardMetaData(MetaDataResult theKbData) + private void handleKeyboardMetaData(MetaDataResult theKbData) { if (theKbData.params.getAdditionalProperty(PARAM_IS_CUSTOM,Boolean.class)) { throw new IllegalStateException("Cannot download custom non-KMP keyboard"); From 6f5b8af2b9f7a186f8fde042668a6a7e147db987 Mon Sep 17 00:00:00 2001 From: safolit <52272980+safolit@users.noreply.github.com> Date: Wed, 6 Nov 2019 13:39:45 +0700 Subject: [PATCH 12/12] Update history.md --- android/history.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/history.md b/android/history.md index 114b1ae24d..c711f3e959 100644 --- a/android/history.md +++ b/android/history.md @@ -3,7 +3,7 @@ ## 13.0 alpha * Start version 13.0 * New Features: - * Adding a download manager to execute downloads in background (#2247) + * Adding a download manager to execute downloads in background (#2247,#2275) * Improve custom package installation: Show readme.htm before starting installation process (#2286) ## 2019-10-30 12.0.4206 stable