mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-13 11:07:42 +00:00
Merge pull request #2308 from keymanapp/android-cleanup-downloadtasks
Android cleanup downloadtasks
This commit is contained in:
commit
f2192c2bfa
24 changed files with 243 additions and 816 deletions
|
|
@ -854,20 +854,12 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi
|
|||
kbInfo.put(KMManager.KMKey_KeyboardVersion, kbVersion);
|
||||
kbInfo.put(KMManager.KMKey_Font, kFont);
|
||||
kbInfo.put(KMManager.KMKey_OskFont, kOskFont);
|
||||
if (i == 0) {
|
||||
if (KMManager.addKeyboard(this, kbInfo)) {
|
||||
if (!KMKeyboardDownloaderActivity.USE_DOWNLOAD_MANAGER)
|
||||
KMManager.setKeyboard(packageID, keyboardID, langId, keyboardName, langName, kFont, kOskFont);
|
||||
}
|
||||
} else {
|
||||
KMManager.addKeyboard(this, kbInfo);
|
||||
}
|
||||
|
||||
KMManager.addKeyboard(this, kbInfo);
|
||||
|
||||
}
|
||||
} else {
|
||||
if (KMManager.addKeyboard(this, keyboardInfo)) {
|
||||
if (!KMKeyboardDownloaderActivity.USE_DOWNLOAD_MANAGER)
|
||||
KMManager.setKeyboard(packageID, keyboardID, languageID, keyboardName, languageName, kFont, kOskFont);
|
||||
}
|
||||
KMManager.addKeyboard(this, keyboardInfo);
|
||||
}
|
||||
} else {
|
||||
// Error notifications handled in LanguageListActivity
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tavultesoft.kmea;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
|
|
@ -8,14 +7,23 @@ import android.content.DialogInterface;
|
|||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* Confirmation dialog for downloading or deleting a Keyman keyboard/model
|
||||
*/
|
||||
public class ConfirmDialogFragment extends DialogFragment {
|
||||
public static final String ARG_DIALOG_TYPE = "ConfirmDialogFragment.dialogType";
|
||||
public static final String ARG_TITLE = "ConfirmDialogFragment.title";
|
||||
public static final String ARG_MESSAGE = "ConfirmDialogFragment.message";
|
||||
public static final String ARG_ITEM_KEY = "confirmDialogFragment.itemKey";
|
||||
private static final String ARG_DIALOG_TYPE = "ConfirmDialogFragment.dialogType";
|
||||
private static final String ARG_TITLE = "ConfirmDialogFragment.title";
|
||||
private static final String ARG_MESSAGE = "ConfirmDialogFragment.message";
|
||||
private static final String ARG_ITEM_KEY = "confirmDialogFragment.itemKey";
|
||||
private static final String ARG_DOWNLOAD_QUERIES_KEY = "confirmDialogFragment.downloadQueries";
|
||||
private static final String ARG_MODEL_ID_KEY = "confirmDialogFragment.modelId";
|
||||
private static final String ARG_LANG_ID_KEY = "confirmDialogFragment.langId";
|
||||
private static final String ARG_KB_ID_KEY = "confirmDialogFragment.kbId";
|
||||
private boolean dismissOnSelect = false;
|
||||
|
||||
public enum DialogType {
|
||||
|
|
@ -25,17 +33,36 @@ public class ConfirmDialogFragment extends DialogFragment {
|
|||
DIALOG_TYPE_DELETE_MODEL
|
||||
}
|
||||
|
||||
public static ConfirmDialogFragment newInstance(DialogType dialogType, String title, String message) {
|
||||
public static ConfirmDialogFragment newInstanceForKeyboard(DialogType dialogType, String title, String message,
|
||||
String aLangId, String aKbId,
|
||||
ArrayList<CloudApiTypes.CloudApiParam> aQueries) {
|
||||
ConfirmDialogFragment frag = new ConfirmDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_DIALOG_TYPE, dialogType);
|
||||
args.putString(ARG_TITLE, title);
|
||||
args.putString(ARG_MESSAGE, message);
|
||||
args.putString(ARG_LANG_ID_KEY, aLangId);
|
||||
args.putString(ARG_KB_ID_KEY, aKbId);
|
||||
args.putSerializable(ARG_DOWNLOAD_QUERIES_KEY,aQueries);
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
|
||||
public static ConfirmDialogFragment newInstance(DialogType dialogType, String title, String message, String itemKey) {
|
||||
public static ConfirmDialogFragment newInstanceForLexicalModel(DialogType dialogType, String title, String message,
|
||||
String aModelId,
|
||||
ArrayList<CloudApiTypes.CloudApiParam> aQueries) {
|
||||
ConfirmDialogFragment frag = new ConfirmDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_DIALOG_TYPE, dialogType);
|
||||
args.putString(ARG_TITLE, title);
|
||||
args.putString(ARG_MESSAGE, message);
|
||||
args.putString(ARG_MODEL_ID_KEY, aModelId);
|
||||
args.putSerializable(ARG_DOWNLOAD_QUERIES_KEY,aQueries);
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
|
||||
public static ConfirmDialogFragment newInstanceForItemKeyBasedAction(DialogType dialogType, String title, String message, String itemKey) {
|
||||
ConfirmDialogFragment frag = new ConfirmDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_DIALOG_TYPE, dialogType);
|
||||
|
|
@ -48,12 +75,17 @@ public class ConfirmDialogFragment extends DialogFragment {
|
|||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
super.onCreateDialog(savedInstanceState);
|
||||
|
||||
final DialogType dialogType = (DialogType)getArguments().getSerializable(ARG_DIALOG_TYPE);
|
||||
final String title = getArguments().getString(ARG_TITLE);
|
||||
final String message = getArguments().getString(ARG_MESSAGE);
|
||||
final String itemKey = getArguments().getString(ARG_ITEM_KEY);
|
||||
final String _langId = getArguments().getString(ARG_LANG_ID_KEY);
|
||||
final String _kbId = getArguments().getString(ARG_KB_ID_KEY);
|
||||
final String _modelId = getArguments().getString(ARG_MODEL_ID_KEY);
|
||||
final ArrayList<CloudApiTypes.CloudApiParam> _preparedCloudApiParams =
|
||||
(ArrayList)getArguments().getSerializable(ARG_DOWNLOAD_QUERIES_KEY);
|
||||
String positiveLabel = (dialogType == DialogType.DIALOG_TYPE_DOWNLOAD_KEYBOARD ||
|
||||
dialogType == DialogType.DIALOG_TYPE_DOWNLOAD_MODEL) ?
|
||||
getString(R.string.label_download) : getString(R.string.label_delete);
|
||||
|
|
@ -66,9 +98,11 @@ public class ConfirmDialogFragment extends DialogFragment {
|
|||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (dialogType) {
|
||||
case DIALOG_TYPE_DOWNLOAD_KEYBOARD :
|
||||
|
||||
// Confirmation to download keyboard
|
||||
if (KMManager.hasConnection(getActivity())) {
|
||||
KMKeyboardDownloaderActivity.download(getActivity(), true);
|
||||
KMKeyboardDownloaderActivity.downloadKeyboard(
|
||||
getActivity(), _langId, _kbId,_preparedCloudApiParams);
|
||||
} else {
|
||||
Toast.makeText(getActivity(), "No internet connection", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
|
@ -82,7 +116,8 @@ public class ConfirmDialogFragment extends DialogFragment {
|
|||
case DIALOG_TYPE_DOWNLOAD_MODEL :
|
||||
// Confirmation to download lexical model
|
||||
if (KMManager.hasConnection(getActivity())) {
|
||||
KMKeyboardDownloaderActivity.download(getActivity(), true, true);
|
||||
KMKeyboardDownloaderActivity.downloadLexicalModel(getActivity(),
|
||||
_modelId, _preparedCloudApiParams);
|
||||
} else {
|
||||
Toast.makeText(getActivity(), "No internet connection", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +1,29 @@
|
|||
package com.tavultesoft.kmea;
|
||||
|
||||
import android.os.Build;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.ProgressDialog;
|
||||
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;
|
||||
import org.json.JSONObject;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
import com.tavultesoft.kmea.cloud.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.cloud.CloudDownloadMgr;
|
||||
import com.tavultesoft.kmea.cloud.impl.CloudKeyboardDataDownloadCallback;
|
||||
import com.tavultesoft.kmea.cloud.impl.CloudKeyboardMetaDataDownloadCallback;
|
||||
import com.tavultesoft.kmea.cloud.impl.CloudLexicalPackageDownloadCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
|
||||
import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_DOWNLOAD_KEYBOARD;
|
||||
import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_DOWNLOAD_MODEL;
|
||||
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";
|
||||
public static final String ARG_KB_ID = "KMKeyboardActivity.kbID";
|
||||
public static final String ARG_LANG_ID = "KMKeyboardActivity.langID";
|
||||
|
|
@ -77,23 +60,24 @@ 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;
|
||||
private static String modelID;
|
||||
private static String modelName;
|
||||
private static String kbName;
|
||||
private static String langName;
|
||||
private static Boolean isCustom;
|
||||
private static Boolean downloadOnlyLexicalModel;
|
||||
//TODO: use keyboard model class
|
||||
private String pkgID;
|
||||
private String kbID;
|
||||
private String langID;
|
||||
private String modelID;
|
||||
private String modelName;
|
||||
private String kbName;
|
||||
private String langName;
|
||||
private Boolean isCustom;
|
||||
private Boolean downloadOnlyLexicalModel;
|
||||
|
||||
private static String customKeyboard;
|
||||
private static String customLanguage;
|
||||
private static Boolean isDirect;
|
||||
private static String url;
|
||||
private static String filename;
|
||||
private String customKeyboard;
|
||||
private String customLanguage;
|
||||
private Boolean isDirect;
|
||||
private String url;
|
||||
private String filename;
|
||||
|
||||
//TODO: move to keyboard manager class
|
||||
private static ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener> kbDownloadEventListeners = null;
|
||||
|
||||
@Override
|
||||
|
|
@ -136,7 +120,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
|
||||
String title = "";
|
||||
String title;
|
||||
if (url != null) {
|
||||
title = String.format("%s: %s", getString(R.string.custom_keyboard), filename);
|
||||
} else if (customKeyboard != null && customLanguage != null &&
|
||||
|
|
@ -158,429 +142,47 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
DialogFragment dialog;
|
||||
if (downloadOnlyLexicalModel) {
|
||||
title = String.format("%s: %s", langName, modelName);
|
||||
dialog = ConfirmDialogFragment.newInstance(
|
||||
DIALOG_TYPE_DOWNLOAD_MODEL, title, getString(R.string.confirm_download_model));
|
||||
dialog = ConfirmDialogFragment.newInstanceForLexicalModel(
|
||||
DIALOG_TYPE_DOWNLOAD_MODEL, title, getString(R.string.confirm_download_model),
|
||||
modelID,
|
||||
prepareCloudApiParamsForLexicalModelDownload());
|
||||
} else {
|
||||
dialog = ConfirmDialogFragment.newInstance(
|
||||
DIALOG_TYPE_DOWNLOAD_KEYBOARD, title, getString(R.string.confirm_download_keyboard));
|
||||
dialog = ConfirmDialogFragment.newInstanceForKeyboard(
|
||||
DIALOG_TYPE_DOWNLOAD_KEYBOARD, title, getString(R.string.confirm_download_keyboard),
|
||||
langID, kbID,
|
||||
prepareCloudApiParamsForKeyboardDownload());
|
||||
}
|
||||
|
||||
dialog.show(getFragmentManager(), "dialog");
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the <code>download</code> method to handle asynchronous downloading and evaluation of
|
||||
* packages and keyboards.
|
||||
* prepare cloud api params for lexical models download.
|
||||
* @return the result
|
||||
*/
|
||||
@Deprecated
|
||||
static class DownloadTask extends AsyncTask<Void, Integer, DownloadTask.Result> {
|
||||
static class Result {
|
||||
public final Integer kbdResult;
|
||||
public final List<Map<String, String>> installedLexicalModels;
|
||||
|
||||
public Result(Integer i) {
|
||||
this(i, null);
|
||||
}
|
||||
|
||||
public Result(Integer i, List<Map<String, String>> installedLexicalModels) {
|
||||
this.kbdResult = i;
|
||||
this.installedLexicalModels = installedLexicalModels;
|
||||
}
|
||||
}
|
||||
|
||||
private ProgressDialog progressDialog;
|
||||
private String kbVersion = "1.0";
|
||||
private String kbIsCustom = isCustom ? "Y" : "N";
|
||||
private String font = "";
|
||||
private String oskFont = "";
|
||||
|
||||
private Context context;
|
||||
private boolean showProgressDialog;
|
||||
private boolean downloadOnlyLexicalModel;
|
||||
|
||||
public DownloadTask(Context context, boolean showProgressDialog) {
|
||||
this.context = context;
|
||||
this.showProgressDialog = showProgressDialog;
|
||||
this.downloadOnlyLexicalModel = false;
|
||||
}
|
||||
|
||||
public DownloadTask(Context context, boolean showProgressDialog, boolean downloadOnlyLexicalModel) {
|
||||
this.context = context;
|
||||
this.showProgressDialog = showProgressDialog;
|
||||
this.downloadOnlyLexicalModel = downloadOnlyLexicalModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
if (showProgressDialog) {
|
||||
progressDialog = new ProgressDialog(context);
|
||||
if (!downloadOnlyLexicalModel) {
|
||||
progressDialog.setMessage(context.getString(R.string.downloading_keyboard));
|
||||
} else {
|
||||
progressDialog.setMessage(context.getString(R.string.downloading_model));
|
||||
}
|
||||
progressDialog.setCancelable(false);
|
||||
if (!((AppCompatActivity) context).isFinishing()) {
|
||||
progressDialog.show();
|
||||
} else {
|
||||
cancel(true);
|
||||
progressDialog = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result doInBackground(Void... voids) {
|
||||
int ret = -1;
|
||||
|
||||
if (isCancelled())
|
||||
return new Result(-1);
|
||||
|
||||
try {
|
||||
|
||||
if (downloadOnlyLexicalModel) {
|
||||
return downloadKMPLexicalModel();
|
||||
}
|
||||
|
||||
String exceptionStr = "Invalid keyboard";
|
||||
if (pkgID == null || pkgID.trim().isEmpty() ||
|
||||
(!isCustom && (langID == null || langID.trim().isEmpty() || kbID == null || kbID.trim().isEmpty()))) {
|
||||
throw new Exception(exceptionStr);
|
||||
}
|
||||
|
||||
String deviceType = context.getString(R.string.device_type);
|
||||
if (deviceType.equals("AndroidTablet")) {
|
||||
deviceType = "androidtablet";
|
||||
} else {
|
||||
deviceType = "androidphone";
|
||||
}
|
||||
|
||||
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
|
||||
remoteUrl = String.format("%s/%s/%s?version=%s&device=%s&languageidtype=bcp47",
|
||||
kKeymanApiBaseURL, langID, kbID, BuildConfig.VERSION_NAME, deviceType);
|
||||
remoteLexicalModelUrl = String.format("%s?q=bcp47:%s", kKeymanApiModelURL, langID);
|
||||
|
||||
}
|
||||
|
||||
return downloadNonKMPKeyboard(remoteUrl, remoteLexicalModelUrl);
|
||||
} catch (Exception e) {
|
||||
ret = -1;
|
||||
Log.e(TAG, "Error: " + e, e);
|
||||
}
|
||||
|
||||
return new Result(ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Integer... progress) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Result result) {
|
||||
try {
|
||||
if (progressDialog != null && progressDialog.isShowing()) {
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
progressDialog = null;
|
||||
}
|
||||
|
||||
((AppCompatActivity) context).finish();
|
||||
|
||||
if (!downloadOnlyLexicalModel) {
|
||||
notifyListeners(KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_FINISHED, result.kbdResult);
|
||||
}
|
||||
|
||||
if(result.installedLexicalModels != null) {
|
||||
notifyLexicalModelInstallListeners(KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED,
|
||||
result.installedLexicalModels, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a KMP Keyman lexical model from Keyman cloud
|
||||
* @return A Result object with a success code and any successfully downloaded lexical models.
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Result downloadKMPLexicalModel() throws Exception {
|
||||
int result = -1;
|
||||
File resourceRoot = new File(context.getDir("data", Context.MODE_PRIVATE).toString() + File.separator);
|
||||
LexicalModelPackageProcessor kmpProcessor = new LexicalModelPackageProcessor(resourceRoot);
|
||||
List<Map<String, String>> installedLexicalModels = null;
|
||||
|
||||
if (downloadOnlyLexicalModel) {
|
||||
String destination = (context.getCacheDir() + File.separator).toString();
|
||||
filename = FileUtils.getFilename(url);
|
||||
|
||||
result = FileUtils.download(context, url, destination, filename);
|
||||
if (result > 0 && FileUtils.hasKeymanPackageExtension(url)) {
|
||||
// Extract the kmp. Validate it contains only lexical models, and then process the lexical model package
|
||||
File kmpFile = new File(context.getCacheDir(), filename);
|
||||
String pkgTarget = kmpProcessor.getPackageTarget(kmpFile);
|
||||
if (pkgTarget.equals(PackageProcessor.PP_TARGET_LEXICAL_MODELS)) {
|
||||
File unzipPath = kmpProcessor.unzipKMP(kmpFile);
|
||||
installedLexicalModels = kmpProcessor.processKMP(kmpFile, unzipPath, PackageProcessor.PP_LEXICAL_MODELS_KEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We'll notify any listeners of the successful download in onPostExecute.
|
||||
return new Result(result, installedLexicalModels);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a non-KMP Keyman keyboard from Keyman cloud via JSON.
|
||||
* If an associated lexical model keyboard package is available, download the first one.
|
||||
* @param remoteUrl String
|
||||
* @param remoteLexicalModelUrl String API query for lexical model associated with the language ID
|
||||
* @return ret int -1 for fail; >0 for success; 2 for keyboard downloading but not font
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Result downloadNonKMPKeyboard(String remoteUrl, String remoteLexicalModelUrl) throws Exception {
|
||||
int ret = -1;
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
JSONObject kbData = jsonParser.getJSONObjectFromUrl(remoteUrl);
|
||||
String exceptionStr = "Could not reach server";
|
||||
if (kbData == null) {
|
||||
throw new Exception(exceptionStr);
|
||||
}
|
||||
|
||||
if (isCustom) {
|
||||
exceptionStr = "Cannot download custom non-KMP keyboard";
|
||||
throw new Exception(exceptionStr);
|
||||
}
|
||||
|
||||
exceptionStr = "JSON file does not contain a valid \"options\" object";
|
||||
JSONObject options = kbData.optJSONObject(KMKey_Options);
|
||||
if (options == null) {
|
||||
throw new Exception(exceptionStr);
|
||||
}
|
||||
String kbBaseUri = options.optString(KMKey_KeyboardBaseURI, "");
|
||||
if (kbBaseUri.isEmpty()) {
|
||||
throw new Exception(exceptionStr);
|
||||
}
|
||||
|
||||
String fontBaseUri = options.optString(KMKey_FontBaseURI, "");
|
||||
|
||||
// Keyman cloud keyboard distribution via JSON
|
||||
JSONObject language = kbData.optJSONObject(KMKey_Language);
|
||||
if (language == null) {
|
||||
throw new Exception(exceptionStr);
|
||||
}
|
||||
|
||||
langName = language.optString(KMManager.KMKey_Name, "");
|
||||
|
||||
JSONArray keyboards = language.getJSONArray(KMKey_LanguageKeyboards);
|
||||
|
||||
JSONObject keyboard = CloudDataJsonUtil.findMatchingKeyboardByID(keyboards,kbID);
|
||||
|
||||
kbID = keyboard.getString(KMManager.KMKey_ID);
|
||||
pkgID = keyboard.optString(KMManager.KMKey_PackageID, KMManager.KMDefault_UndefinedPackageID);
|
||||
|
||||
kbName = keyboard.optString(KMManager.KMKey_Name, "");
|
||||
kbVersion = keyboard.optString(KMManager.KMKey_KeyboardVersion, "1.0");
|
||||
String kbFilename = keyboard.optString(KMKey_Filename, "");
|
||||
if (kbName.isEmpty() || langName.isEmpty() || kbFilename.isEmpty())
|
||||
throw new Exception(exceptionStr);
|
||||
|
||||
String kbUrl = kbBaseUri + kbFilename;
|
||||
ArrayList<String> urls = new ArrayList<String>();
|
||||
urls.add(kbUrl);
|
||||
|
||||
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<String> fontUrls = CloudDataJsonUtil.fontUrls(jsonFont, fontBaseUri, false);
|
||||
ArrayList<String> oskFontUrls = CloudDataJsonUtil.fontUrls(jsonOskFont, fontBaseUri, true);
|
||||
if (fontUrls != null)
|
||||
urls.addAll(fontUrls);
|
||||
if (oskFontUrls != null) {
|
||||
for (String url : oskFontUrls) {
|
||||
if (!urls.contains(url))
|
||||
urls.add(url);
|
||||
}
|
||||
}
|
||||
|
||||
font = keyboard.optString(KMManager.KMKey_Font);
|
||||
oskFont = keyboard.optString(KMManager.KMKey_OskFont);
|
||||
|
||||
// Also download first associated lexical model if it exists
|
||||
JSONArray lmData = jsonParser.getJSONObjectFromUrl(remoteLexicalModelUrl, JSONArray.class);
|
||||
if (lmData != null && lmData.length() > 0) {
|
||||
try {
|
||||
JSONObject modelInfo = lmData.getJSONObject(0);
|
||||
if (modelInfo.has("packageFilename")) {
|
||||
// TODO: Confirm if user wants to overwrite exisiting model version
|
||||
urls.add(modelInfo.getString("packageFilename"));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error parsing lexical model from api.keyman.com. " + e);
|
||||
}
|
||||
}
|
||||
|
||||
notifyListeners(KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_STARTED, 0);
|
||||
|
||||
String destination = context.getDir("data", Context.MODE_PRIVATE).toString() +
|
||||
File.separator + KMDefault_UndefinedPackageID + File.separator + File.separator;
|
||||
|
||||
ret = 1;
|
||||
int result = 0;
|
||||
File resourceRoot = new File(context.getDir("data", Context.MODE_PRIVATE).toString() + File.separator);
|
||||
LexicalModelPackageProcessor kmpProcessor = new LexicalModelPackageProcessor(resourceRoot);
|
||||
List<Map<String, String>> installedLexicalModels = new ArrayList<>();
|
||||
for (String url : urls) {
|
||||
String filename = "";
|
||||
if (FileUtils.hasJavaScriptExtension(url)) {
|
||||
|
||||
int start = kbFilename.lastIndexOf("/");
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
} else {
|
||||
start++;
|
||||
}
|
||||
if (!kbFilename.contains("-")) {
|
||||
filename = kbFilename.substring(start, kbFilename.length() - 3) + "-" + kbVersion + ".js";
|
||||
} else {
|
||||
filename = kbFilename.substring(start);
|
||||
}
|
||||
} else if (FileUtils.hasKeymanPackageExtension(url)) {
|
||||
// Save the kmp file in the app cache
|
||||
destination = (context.getCacheDir() + File.separator).toString();
|
||||
filename = FileUtils.getFilename(url);
|
||||
}
|
||||
|
||||
result = FileUtils.download(context, url, destination, filename);
|
||||
if (result > 0 && FileUtils.hasKeymanPackageExtension(url)) {
|
||||
// Extract the kmp. Validate it contains only lexical models, and then process the lexical model package
|
||||
File kmpFile = new File(context.getCacheDir(), filename);
|
||||
String pkgTarget = kmpProcessor.getPackageTarget(kmpFile);
|
||||
if (pkgTarget.equals(PackageProcessor.PP_TARGET_LEXICAL_MODELS)) {
|
||||
File unzipPath = kmpProcessor.unzipKMP(kmpFile);
|
||||
// Assumption: only one lexical model KMP will occur per download.
|
||||
installedLexicalModels = kmpProcessor.processKMP(kmpFile, unzipPath, PackageProcessor.PP_LEXICAL_MODELS_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
if (FileUtils.hasFontExtension(url)) {
|
||||
// Propagate warning about font failing to download
|
||||
ret = 2;
|
||||
} else {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (installedLexicalModels.size() != 0) {
|
||||
// Let the postExecute method signal the listeners - it's triggered on the main thread.
|
||||
return new Result(ret, installedLexicalModels);
|
||||
}
|
||||
|
||||
return new Result(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify listeners when an event happens
|
||||
* @param eventType
|
||||
* @param result
|
||||
*/
|
||||
protected void notifyListeners(KeyboardEventHandler.EventType eventType, int result) {
|
||||
if (kbDownloadEventListeners != null) {
|
||||
HashMap<String, String> keyboardInfo =
|
||||
CloudDataJsonUtil.createKeyboardInfoMap(pkgID,langID,langName,kbID,kbName,kbVersion,kbIsCustom,font,oskFont);
|
||||
|
||||
KeyboardEventHandler.notifyListeners(kbDownloadEventListeners, eventType, keyboardInfo, result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify listeners when a lexical model is installed
|
||||
* @param eventType
|
||||
* @param models
|
||||
* @param result
|
||||
*/
|
||||
protected void notifyLexicalModelInstallListeners(KeyboardEventHandler.EventType eventType,
|
||||
List<Map<String, String>> models, int result) {
|
||||
if (kbDownloadEventListeners != null) {
|
||||
KeyboardEventHandler.notifyListeners(kbDownloadEventListeners, eventType, models, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async task to download a Keyman keyboard from either Keyman cloud server or custom url
|
||||
* @param context
|
||||
* @param showProgressDialog
|
||||
*/
|
||||
public static void download(final Context context, final boolean showProgressDialog) {
|
||||
if(USE_DOWNLOAD_MANAGER)
|
||||
downloadKeyboardUsingDownloadManager(context);
|
||||
else
|
||||
new DownloadTask(context, showProgressDialog).execute();
|
||||
}
|
||||
|
||||
public static void download(final Context context, final boolean showProgressDialog,
|
||||
final boolean aDownloadOnlyLexicalModel) {
|
||||
if(USE_DOWNLOAD_MANAGER)
|
||||
downloadUsingDownloadManager(context,aDownloadOnlyLexicalModel);
|
||||
else
|
||||
new DownloadTask(context, showProgressDialog, aDownloadOnlyLexicalModel).execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
downloadLexicalModelUsingDownloadManager(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
downloadKeyboardUsingDownloadManager(context);
|
||||
}
|
||||
private ArrayList<CloudApiTypes.CloudApiParam> prepareCloudApiParamsForLexicalModelDownload() {
|
||||
ArrayList<CloudApiTypes.CloudApiParam> _params = new ArrayList<>();
|
||||
_params.add(new CloudApiTypes.CloudApiParam(
|
||||
CloudApiTypes.ApiTarget.LexicalModelPackage, url));
|
||||
return _params;
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare and execute keyboard download using downloadmanager.
|
||||
* @param context the context
|
||||
* @param aLangId the language id
|
||||
* @param aKbId the keyman keyboard id
|
||||
* @param aPreparedCloudApiParams the prepared api params
|
||||
*/
|
||||
private static void downloadKeyboardUsingDownloadManager(Context context)
|
||||
public static void downloadKeyboard(Context context,
|
||||
String aLangId, String aKbId,
|
||||
List<CloudApiTypes.CloudApiParam> aPreparedCloudApiParams)
|
||||
{
|
||||
if (pkgID == null || pkgID.trim().isEmpty() ||
|
||||
(!isCustom && (langID == null || langID.trim().isEmpty() || kbID == null || kbID.trim().isEmpty()))) {
|
||||
throw new IllegalStateException("Invalid keyboard");
|
||||
}
|
||||
|
||||
|
||||
|
||||
List<CloudApiTypes.CloudApiParam> cloudQueries = getPrepareCloudQueriesForKeyboardDownload(context);
|
||||
|
||||
String _downloadid= CloudKeyboardMetaDataDownloadCallback.createDownloadId(langID , kbID);
|
||||
String _downloadid= CloudKeyboardMetaDataDownloadCallback.createDownloadId(aLangId , aKbId);
|
||||
|
||||
if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_downloadid)
|
||||
|| CloudDownloadMgr.getInstance().alreadyDownloadingData(
|
||||
CloudKeyboardDataDownloadCallback.createDownloadId(kbID)))
|
||||
CloudKeyboardDataDownloadCallback.createDownloadId(aKbId)))
|
||||
{
|
||||
Toast.makeText(context,
|
||||
context.getString(R.string.keyboard_download_is_running_in_background),
|
||||
|
|
@ -589,7 +191,6 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
else
|
||||
{
|
||||
CloudKeyboardMetaDataDownloadCallback _callback = new CloudKeyboardMetaDataDownloadCallback();
|
||||
_callback.setDownloadEventListeners(kbDownloadEventListeners);
|
||||
|
||||
Toast.makeText(context,
|
||||
context.getString(R.string.keyboard_download_start_in_background),
|
||||
|
|
@ -597,22 +198,26 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
|
||||
CloudDownloadMgr.getInstance().executeAsDownload(
|
||||
context, _downloadid, null, _callback,
|
||||
cloudQueries.toArray(new CloudApiTypes.CloudApiParam[0]));
|
||||
aPreparedCloudApiParams.toArray(new CloudApiTypes.CloudApiParam[0]));
|
||||
}
|
||||
|
||||
((AppCompatActivity) context).finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the cloud queries for keyboard metadata download.
|
||||
* @param context the context
|
||||
* Prepare the cloud api params for keyboard metadata download.
|
||||
* @return the result
|
||||
*/
|
||||
private static List<CloudApiTypes.CloudApiParam> getPrepareCloudQueriesForKeyboardDownload(Context context)
|
||||
private ArrayList<CloudApiTypes.CloudApiParam> prepareCloudApiParamsForKeyboardDownload()
|
||||
{
|
||||
List<CloudApiTypes.CloudApiParam> cloudQueries = new ArrayList<>();
|
||||
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);
|
||||
ArrayList<CloudApiTypes.CloudApiParam> cloudQueries = new ArrayList<>();
|
||||
|
||||
String deviceType = CloudDataJsonUtil.getDeviceTypeForCloudQuery(this);
|
||||
|
||||
if (isCustom) {
|
||||
//TODO: will end up in an exception during download???
|
||||
|
|
@ -643,11 +248,15 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
/**
|
||||
* prepare and execute lexical model download using downloadmanager.
|
||||
* @param context the context
|
||||
* @param aModelId the lexical model id
|
||||
* @param aPreparedCloudApiParams the prepared api params
|
||||
*/
|
||||
private static void downloadLexicalModelUsingDownloadManager(Context context) {
|
||||
public static void downloadLexicalModel(Context context,
|
||||
String aModelId,
|
||||
List<CloudApiTypes.CloudApiParam> aPreparedCloudApiParams) {
|
||||
|
||||
|
||||
String _downloadid= CloudLexicalPackageDownloadCallback.createDownloadId(modelID);
|
||||
String _downloadid= CloudLexicalPackageDownloadCallback.createDownloadId(aModelId);
|
||||
|
||||
if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_downloadid))
|
||||
{
|
||||
|
|
@ -658,17 +267,14 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
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);
|
||||
context, _downloadid, null, _callback,
|
||||
aPreparedCloudApiParams.toArray(new CloudApiTypes.CloudApiParam[0]));
|
||||
}
|
||||
|
||||
((AppCompatActivity) context).finish();
|
||||
|
|
@ -688,7 +294,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
|
||||
public static void addKeyboardDownloadEventListener(KeyboardEventHandler.OnKeyboardDownloadEventListener listener) {
|
||||
if (kbDownloadEventListeners == null) {
|
||||
kbDownloadEventListeners = new ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener>();
|
||||
kbDownloadEventListeners = new ArrayList<>();
|
||||
}
|
||||
|
||||
if (listener != null && !kbDownloadEventListeners.contains(listener)) {
|
||||
|
|
@ -701,4 +307,8 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
kbDownloadEventListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener> getKbDownloadEventListeners() {
|
||||
return kbDownloadEventListeners;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ import com.google.firebase.analytics.FirebaseAnalytics;
|
|||
import com.tavultesoft.kmea.KeyboardEventHandler.EventType;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler.OnKeyboardDownloadEventListener;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler.OnKeyboardEventListener;
|
||||
import com.tavultesoft.kmea.data.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.data.CloudDownloadMgr;
|
||||
import com.tavultesoft.kmea.cloud.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.cloud.CloudDownloadMgr;
|
||||
import com.tavultesoft.kmea.data.Dataset;
|
||||
import com.tavultesoft.kmea.packages.JSONUtils;
|
||||
import com.tavultesoft.kmea.packages.PackageProcessor;
|
||||
|
|
|
|||
|
|
@ -145,8 +145,6 @@ public final class KeyboardListActivity extends AppCompatActivity implements OnK
|
|||
String kOskFont = keyboardInfo.get(KMManager.KMKey_OskFont);
|
||||
|
||||
KeyboardPickerActivity.addKeyboard(this, keyboardInfo);
|
||||
if (!KMKeyboardDownloaderActivity.USE_DOWNLOAD_MANAGER)
|
||||
KMManager.setKeyboard(packageID, keyboardID, languageID, keyboardName, languageName, kFont, kOskFont);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.tavultesoft.kmea.data.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.cloud.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.data.CloudRepository;
|
||||
import com.tavultesoft.kmea.data.Dataset;
|
||||
import com.tavultesoft.kmea.data.Keyboard;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
/**
|
||||
/*
|
||||
* Copyright (C) 2019 SIL International. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.tavultesoft.kmea;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import android.app.DialogFragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.net.Uri;
|
||||
|
|
@ -39,15 +36,11 @@ import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_
|
|||
// Public access is necessary to avoid IllegalAccessException
|
||||
public final class KeyboardSettingsActivity extends AppCompatActivity {
|
||||
private static final String TAG = "KbSettingsActivity";
|
||||
|
||||
private static Toolbar toolbar = null;
|
||||
private static ListView listView = null;
|
||||
private DialogFragment dialog;
|
||||
private static ArrayList<HashMap<String, String>> infoList = null;
|
||||
protected static Typeface titleFont = null;
|
||||
private final String titleKey = "title";
|
||||
private final String subtitleKey = "subtitle";
|
||||
private final String iconKey = "icon";
|
||||
private static Typeface titleFont = null;
|
||||
private static final String titleKey = "title";
|
||||
private static final String subtitleKey = "subtitle";
|
||||
private static final String iconKey = "icon";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
|
@ -57,13 +50,13 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
final String authority = FileProviderUtils.getAuthority(context);
|
||||
|
||||
setContentView(R.layout.activity_list_layout);
|
||||
toolbar = (Toolbar) findViewById(R.id.list_toolbar);
|
||||
final Toolbar toolbar = findViewById(R.id.list_toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||
|
||||
listView = (ListView) findViewById(R.id.listView);
|
||||
final ListView listView = findViewById(R.id.listView);
|
||||
|
||||
final String packageID = getIntent().getStringExtra(KMManager.KMKey_PackageID);
|
||||
final String languageID = getIntent().getStringExtra(KMManager.KMKey_LanguageID);
|
||||
|
|
@ -72,22 +65,22 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
final String kbName = getIntent().getStringExtra(KMManager.KMKey_KeyboardName);
|
||||
final String kbVersion = getIntent().getStringExtra(KMManager.KMKey_KeyboardVersion);
|
||||
|
||||
final TextView textView = (TextView) findViewById(R.id.bar_title);
|
||||
final TextView textView = findViewById(R.id.bar_title);
|
||||
textView.setText(kbName);
|
||||
if (titleFont != null)
|
||||
textView.setTypeface(titleFont, Typeface.BOLD);
|
||||
|
||||
infoList = new ArrayList<HashMap<String, String>>();
|
||||
infoList = new ArrayList<>();
|
||||
// Display keyboard version title
|
||||
final String noIcon = "0";
|
||||
HashMap<String, String> hashMap = new HashMap<String, String>();
|
||||
HashMap<String, String> hashMap = new HashMap<>();
|
||||
hashMap.put(titleKey, getString(R.string.keyboard_version));
|
||||
hashMap.put(subtitleKey, kbVersion);
|
||||
hashMap.put(iconKey, noIcon);
|
||||
infoList.add(hashMap);
|
||||
|
||||
// Display keyboard help link
|
||||
hashMap = new HashMap<String, String>();
|
||||
hashMap = new HashMap<>();
|
||||
final String helpUrlStr = getIntent().getStringExtra(KMManager.KMKey_HelpLink);
|
||||
final String customHelpLink = getIntent().getStringExtra(KMManager.KMKey_CustomHelpLink);
|
||||
// Check if app declared FileProvider
|
||||
|
|
@ -105,7 +98,7 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
// Display uninstall keyboard
|
||||
if (!packageID.equalsIgnoreCase(KMManager.KMDefault_UndefinedPackageID) ||
|
||||
!kbID.equalsIgnoreCase(KMManager.KMDefault_KeyboardID)) {
|
||||
hashMap = new HashMap<String, String>();
|
||||
hashMap = new HashMap<>();
|
||||
hashMap.put(titleKey, getString(R.string.uninstall_keyboard));
|
||||
hashMap.put(subtitleKey, "");
|
||||
hashMap.put(iconKey, noIcon);
|
||||
|
|
@ -118,7 +111,7 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
ListAdapter adapter = new SimpleAdapter(context, infoList, R.layout.list_row_layout2, from, to) {
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
HashMap<String, String> hashMap = (HashMap<String, String>)infoList.get(position);
|
||||
HashMap<String, String> hashMap = infoList.get(position);
|
||||
String itemTitle = MapCompat.getOrDefault(hashMap, titleKey, "");
|
||||
String icon = MapCompat.getOrDefault(hashMap, iconKey, noIcon);
|
||||
if (itemTitle.equals(getString(R.string.keyboard_version))) {
|
||||
|
|
@ -174,7 +167,7 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
// Uninstall selected keyboard
|
||||
String title = String.format("%s: %s", languageName, kbName);
|
||||
String keyboardKey = String.format("%s_%s", languageID, kbID);
|
||||
DialogFragment dialog = ConfirmDialogFragment.newInstance(
|
||||
DialogFragment dialog = ConfirmDialogFragment.newInstanceForItemKeyBasedAction(
|
||||
DIALOG_TYPE_DELETE_KEYBOARD, title, getString(R.string.confirm_delete_keyboard), keyboardKey);
|
||||
dialog.show(getFragmentManager(), "dialog");
|
||||
}
|
||||
|
|
@ -191,9 +184,7 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
@Override
|
||||
public void onDestroy(){
|
||||
super.onDestroy();
|
||||
if ( dialog !=null ){
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@
|
|||
|
||||
package com.tavultesoft.kmea;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -15,7 +12,7 @@ import org.json.JSONArray;
|
|||
import org.json.JSONObject;
|
||||
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler.OnKeyboardDownloadEventListener;
|
||||
import com.tavultesoft.kmea.data.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.cloud.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.data.CloudRepository;
|
||||
import com.tavultesoft.kmea.data.Dataset;
|
||||
import com.tavultesoft.kmea.data.Keyboard;
|
||||
|
|
@ -138,8 +135,6 @@ public final class LanguageListActivity extends AppCompatActivity implements OnK
|
|||
// Custom keyboard already exists in packages/ so just add the language association
|
||||
KeyboardPickerActivity.addKeyboard(context, kbInfo);
|
||||
|
||||
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();
|
||||
|
|
@ -209,8 +204,6 @@ public final class LanguageListActivity extends AppCompatActivity implements OnK
|
|||
String kOskFont = keyboardInfo.get(KMManager.KMKey_OskFont);
|
||||
|
||||
KeyboardPickerActivity.addKeyboard(this, keyboardInfo);
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import androidx.appcompat.app.AlertDialog;
|
|||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.tavultesoft.kmea.data.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.cloud.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.data.CloudRepository;
|
||||
import com.tavultesoft.kmea.data.Dataset;
|
||||
import com.tavultesoft.kmea.data.adapters.AdapterFilter;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
/**
|
||||
/*
|
||||
* Copyright (C) 2017 SIL International. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.tavultesoft.kmea;
|
||||
|
||||
import java.io.File;
|
||||
|
|
@ -18,14 +17,11 @@ import android.net.Uri;
|
|||
import android.os.Bundle;
|
||||
import androidx.core.content.FileProvider;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.SimpleAdapter;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
|
@ -39,10 +35,7 @@ import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_
|
|||
// Public access is necessary to avoid IllegalAccessException
|
||||
public final class ModelInfoActivity extends AppCompatActivity {
|
||||
|
||||
private static Toolbar toolbar = null;
|
||||
private static ListView listView = null;
|
||||
private static ArrayList<HashMap<String, String>> infoList = null;
|
||||
protected static Typeface titleFont = null;
|
||||
private final String titleKey = "title";
|
||||
private final String subtitleKey = "subtitle";
|
||||
private final String iconKey = "icon";
|
||||
|
|
@ -55,13 +48,13 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
final String authority = FileProviderUtils.getAuthority(context);
|
||||
|
||||
setContentView(R.layout.activity_list_layout);
|
||||
toolbar = (Toolbar) findViewById(R.id.list_toolbar);
|
||||
final Toolbar toolbar = findViewById(R.id.list_toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||
|
||||
listView = (ListView) findViewById(R.id.listView);
|
||||
final ListView listView = findViewById(R.id.listView);
|
||||
|
||||
final String packageID = getIntent().getStringExtra(KMManager.KMKey_PackageID);
|
||||
final String languageID = getIntent().getStringExtra(KMManager.KMKey_LanguageID);
|
||||
|
|
@ -69,23 +62,20 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
final String modelName = getIntent().getStringExtra(KMManager.KMKey_LexicalModelName);
|
||||
final String modelVersion = getIntent().getStringExtra(KMManager.KMKey_LexicalModelVersion);
|
||||
|
||||
final TextView textView = (TextView) findViewById(R.id.bar_title);
|
||||
final TextView textView = findViewById(R.id.bar_title);
|
||||
textView.setText(String.format(getString(R.string.model_info_header), modelName));
|
||||
if (titleFont != null)
|
||||
textView.setTypeface(titleFont, Typeface.BOLD);
|
||||
|
||||
|
||||
infoList = new ArrayList<HashMap<String, String>>();
|
||||
infoList = new ArrayList<>();
|
||||
// Display model version title
|
||||
final String noIcon = "0";
|
||||
HashMap<String, String> hashMap = new HashMap<String, String>();
|
||||
HashMap<String, String> hashMap = new HashMap<>();
|
||||
hashMap.put(titleKey, getString(R.string.model_version));
|
||||
hashMap.put(subtitleKey, modelVersion);
|
||||
hashMap.put(iconKey, noIcon);
|
||||
infoList.add(hashMap);
|
||||
|
||||
// Display model help link
|
||||
hashMap = new HashMap<String, String>();
|
||||
hashMap = new HashMap<>();
|
||||
final String customHelpLink = getIntent().getStringExtra(KMManager.KMKey_CustomHelpLink);
|
||||
// Check if app declared FileProvider
|
||||
// Currently, model help only available if custom link exists
|
||||
|
|
@ -102,7 +92,7 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
infoList.add(hashMap);
|
||||
|
||||
// Display link to uninstall model
|
||||
hashMap = new HashMap<String, String>();
|
||||
hashMap = new HashMap<>();
|
||||
hashMap.put(titleKey, getString(R.string.uninstall_model));
|
||||
hashMap.put(subtitleKey, "");
|
||||
hashMap.put(iconKey, noIcon);
|
||||
|
|
@ -114,7 +104,7 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
ListAdapter adapter = new SimpleAdapter(context, infoList, R.layout.list_row_layout2, from, to) {
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
HashMap<String, String> hashMap = (HashMap<String, String>)infoList.get(position);
|
||||
HashMap<String, String> hashMap = infoList.get(position);
|
||||
String itemTitle = MapCompat.getOrDefault(hashMap, titleKey, "");
|
||||
String icon = MapCompat.getOrDefault(hashMap, iconKey, noIcon);
|
||||
if (itemTitle.equals(getString(R.string.model_version))) {
|
||||
|
|
@ -168,7 +158,7 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
} else if (itemTitle.equals(getString(R.string.uninstall_model))) {
|
||||
// Uninstall selected model
|
||||
String lexicalModelKey = String.format("%s_%s_%s", packageID, languageID, modelID);
|
||||
DialogFragment dialog = ConfirmDialogFragment.newInstance(
|
||||
DialogFragment dialog = ConfirmDialogFragment.newInstanceForItemKeyBasedAction(
|
||||
DIALOG_TYPE_DELETE_MODEL, modelName, getString(R.string.confirm_delete_model), lexicalModelKey);
|
||||
dialog.show(getFragmentManager(), "dialog");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
|
||||
|
|
@ -8,14 +8,14 @@ import org.json.JSONArray;
|
|||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
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 {
|
||||
public static class CloudApiReturns {
|
||||
|
||||
public final ApiTarget target;
|
||||
public final JSONArray jsonArray;
|
||||
|
|
@ -69,11 +69,14 @@ public class CloudApiTypes {
|
|||
Object
|
||||
}
|
||||
|
||||
public static class CloudApiParam {
|
||||
public static class CloudApiParam implements Serializable {
|
||||
|
||||
static final long serialVersionUID = 1L;
|
||||
|
||||
public final ApiTarget target;
|
||||
public final String url;
|
||||
public JSONType type;
|
||||
private Map<String,Object> additionalProperties = new HashMap<>();
|
||||
private final HashMap<String,Serializable> additionalProperties = new HashMap<>();
|
||||
|
||||
public CloudApiParam(ApiTarget target, String url) {
|
||||
this.target = target;
|
||||
|
|
@ -84,24 +87,24 @@ public class CloudApiTypes {
|
|||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
public CloudApiParam setAdditionalProperty(String aProperty, Object aValue)
|
||||
public CloudApiParam setAdditionalProperty(String aProperty, Serializable aValue)
|
||||
{
|
||||
additionalProperties.put(aProperty,aValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> T getAdditionalProperty(String aProperty,Class<T> aType)
|
||||
public <T extends Serializable> T getAdditionalProperty(String aProperty,Class<T> aType)
|
||||
{
|
||||
return (T)additionalProperties.get(aProperty);
|
||||
return aType.cast(additionalProperties.get(aProperty));
|
||||
}
|
||||
}
|
||||
|
||||
public static class SingleCloudDownload
|
||||
{
|
||||
private DownloadManager.Request request;
|
||||
private final DownloadManager.Request request;
|
||||
private boolean downloadFinished =false;
|
||||
private long downloadId;
|
||||
private File destinationFile;
|
||||
private final File destinationFile;
|
||||
private CloudApiParam cloudParams;
|
||||
|
||||
public SingleCloudDownload(DownloadManager.Request aRequest,File aDestinationFile)
|
||||
|
|
@ -142,9 +145,9 @@ public class CloudApiTypes {
|
|||
* @param <ResultType> the result type of the download
|
||||
*/
|
||||
public static class CloudDownloadSet<ModelType,ResultType> {
|
||||
private String downloadIdentifier;
|
||||
private ModelType targetModel;
|
||||
private LinkedList<SingleCloudDownload> downloads = new LinkedList<>();
|
||||
private final String downloadIdentifier;
|
||||
private final ModelType targetModel;
|
||||
private final LinkedList<SingleCloudDownload> downloads = new LinkedList<>();
|
||||
|
||||
private ICloudDownloadCallback<ModelType,ResultType> callback;
|
||||
|
||||
|
|
@ -213,7 +216,6 @@ public class CloudApiTypes {
|
|||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
|
@ -8,6 +8,9 @@ import com.tavultesoft.kmea.JSONParser;
|
|||
import com.tavultesoft.kmea.KMKeyboardDownloaderActivity;
|
||||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.R;
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
import com.tavultesoft.kmea.data.Keyboard;
|
||||
import com.tavultesoft.kmea.data.LexicalModel;
|
||||
import com.tavultesoft.kmea.util.FileUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
|
@ -52,7 +55,7 @@ public class CloudDataJsonUtil {
|
|||
return keyboardInfo;
|
||||
}
|
||||
|
||||
static List<Keyboard> processKeyboardJSON(JSONObject query, boolean fromKMP) {
|
||||
public static List<Keyboard> processKeyboardJSON(JSONObject query, boolean fromKMP) {
|
||||
List<Keyboard> keyboardsList = new ArrayList<>();
|
||||
//keyboardModifiedDates = new HashMap<String, String>();
|
||||
|
||||
|
|
@ -96,7 +99,7 @@ public class CloudDataJsonUtil {
|
|||
return keyboardsList;
|
||||
}
|
||||
|
||||
static List<LexicalModel> processLexicalModelJSON(JSONArray models) {
|
||||
public static List<LexicalModel> processLexicalModelJSON(JSONArray models) {
|
||||
List<LexicalModel> modelList = new ArrayList<>(models.length());
|
||||
|
||||
try {
|
||||
|
|
@ -158,7 +161,7 @@ public class CloudDataJsonUtil {
|
|||
return modelList;
|
||||
}
|
||||
|
||||
static JSONArray getCachedJSONArray(File file) {
|
||||
public static JSONArray getCachedJSONArray(File file) {
|
||||
JSONArray lmData = null;
|
||||
try {
|
||||
// Read from cache file
|
||||
|
|
@ -198,7 +201,7 @@ public class CloudDataJsonUtil {
|
|||
* be used for each API call, such as for keyboards vs lexical models.
|
||||
* @param json - Array of JSON objects containing API return info
|
||||
*/
|
||||
protected static void saveJSONArrayToCache(File file, JSONArray json) {
|
||||
public static void saveJSONArrayToCache(File file, JSONArray json) {
|
||||
ObjectOutput objOutput;
|
||||
try {
|
||||
// Save to cache file
|
||||
|
|
@ -216,7 +219,7 @@ public class CloudDataJsonUtil {
|
|||
* be used for each API call, such as for keyboards vs lexical models.
|
||||
* @param json - JSON object containing API return info
|
||||
*/
|
||||
protected static void saveJSONObjectToCache(File file, JSONObject json) {
|
||||
public static void saveJSONObjectToCache(File file, JSONObject json) {
|
||||
ObjectOutput objOutput;
|
||||
try {
|
||||
// Save to cache file
|
||||
|
|
@ -243,7 +246,7 @@ public class CloudDataJsonUtil {
|
|||
* @param aDownload the download
|
||||
* @return the result
|
||||
*/
|
||||
public static CloudApiTypes.CloudApiReturns retrieveJsonFromDownload( CloudApiTypes.SingleCloudDownload aDownload)
|
||||
public static CloudApiTypes.CloudApiReturns retrieveJsonFromDownload(CloudApiTypes.SingleCloudDownload aDownload)
|
||||
{
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
JSONArray dataArray = null;
|
||||
|
|
@ -258,7 +261,7 @@ public class CloudDataJsonUtil {
|
|||
dataObject = jsonParser.getJSONObjectFromFile(aDownload.getDestinationFile(),JSONObject.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, e.getMessage());
|
||||
Log.d(TAG, e.getMessage(),e);
|
||||
} finally {
|
||||
aDownload.getDestinationFile().delete();
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
|
|
@ -126,6 +126,8 @@ public class CloudDownloadMgr{
|
|||
synchronized (downloadSetByDownloadIdentifier) {
|
||||
|
||||
CloudApiTypes.CloudDownloadSet _parentSet = getDownloadSetForInternalDownloadId(anInternalDownloadId);
|
||||
if(_parentSet==null)
|
||||
throw new IllegalStateException("Download with ID " + anInternalDownloadId + " is not available");
|
||||
_parentSet.setDone(anInternalDownloadId);
|
||||
if(!_parentSet.hasOpenDownloads())
|
||||
{
|
||||
|
|
@ -188,7 +190,8 @@ public class CloudDownloadMgr{
|
|||
return;
|
||||
|
||||
DownloadManager downloadManager = (DownloadManager) aContext.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
|
||||
if(downloadManager==null)
|
||||
throw new IllegalStateException("Downloadmanager is not available");
|
||||
|
||||
aCallback.initializeContext(aContext);
|
||||
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
import com.tavultesoft.kmea.cloud.CloudDownloadMgr;
|
||||
|
||||
/**
|
||||
* Interface for {@link CloudDownloadMgr} as callback to do use case specific task.
|
||||
* @param <ModelType> the model objects type
|
||||
|
|
@ -1,13 +1,20 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud.impl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tavultesoft.kmea.JSONParser;
|
||||
import com.tavultesoft.kmea.KeyboardPickerActivity;
|
||||
import com.tavultesoft.kmea.R;
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
import com.tavultesoft.kmea.cloud.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.cloud.ICloudDownloadCallback;
|
||||
import com.tavultesoft.kmea.data.CloudRepository;
|
||||
import com.tavultesoft.kmea.data.Dataset;
|
||||
import com.tavultesoft.kmea.data.Keyboard;
|
||||
import com.tavultesoft.kmea.data.LanguageResource;
|
||||
import com.tavultesoft.kmea.data.LexicalModel;
|
||||
import com.tavultesoft.kmea.util.FileUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
|
@ -20,7 +27,7 @@ import java.util.List;
|
|||
* Callback for cloud catalogue download.
|
||||
* Is used for download with progress and download with Clientdownloadmanager.
|
||||
*/
|
||||
public class CloudCatalogDownloadCallback implements ICloudDownloadCallback<Dataset, CloudCatalogDownloadReturns>{
|
||||
public class CloudCatalogDownloadCallback implements ICloudDownloadCallback<Dataset, CloudCatalogDownloadReturns> {
|
||||
|
||||
private static final String TAG = "CloudCatalogDownloadCb";
|
||||
private static final boolean DEBUG_SIMULATE_UPDATES = false;
|
||||
|
|
@ -127,10 +134,6 @@ public class CloudCatalogDownloadCallback implements ICloudDownloadCallback<Data
|
|||
public void processCloudReturns(Dataset aDataSet, CloudCatalogDownloadReturns jsonTuple, boolean executeCallbacks) {
|
||||
// Only empty if no queries returned data - we're offline.
|
||||
if (jsonTuple.isEmpty()) {
|
||||
if (this.updateHandler == null) {
|
||||
String msg = context.getString(R.string.catalog_unavailable);
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
this.failure.run(); // Signal failure to download to our failure callback.
|
||||
return;
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud.impl;
|
||||
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
|
@ -8,7 +10,7 @@ import java.util.List;
|
|||
/**
|
||||
* Result type for catalogue download.
|
||||
*/
|
||||
class CloudCatalogDownloadReturns {
|
||||
public class CloudCatalogDownloadReturns {
|
||||
public JSONObject keyboardJSON;
|
||||
public JSONArray lexicalModelJSON;
|
||||
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud.impl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tavultesoft.kmea.KMKeyboardDownloaderActivity;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler;
|
||||
import com.tavultesoft.kmea.R;
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
import com.tavultesoft.kmea.cloud.ICloudDownloadCallback;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Install keyboard data, when download is finished.
|
||||
* Could be keyboard packages or fonts.
|
||||
|
|
@ -27,7 +27,6 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback
|
|||
|
||||
private File dataDir;
|
||||
|
||||
private ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener> downloadEventListeners = new ArrayList<>();
|
||||
private HashMap<String,String> keyboardInfo;
|
||||
|
||||
/**
|
||||
|
|
@ -44,16 +43,6 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback
|
|||
*/
|
||||
public static final String PARAM_PACKAGE = "package";
|
||||
|
||||
/**
|
||||
* listeners to inform after installation is completed.
|
||||
* @param aDownloadEventListeners the listeners
|
||||
*/
|
||||
public void setDownloadEventListeners(ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener> aDownloadEventListeners)
|
||||
{
|
||||
downloadEventListeners.clear();
|
||||
downloadEventListeners.addAll(aDownloadEventListeners);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keyboard meta data.
|
||||
* @param aKeyboardInfo the keyboard
|
||||
|
|
@ -121,7 +110,8 @@ public class CloudKeyboardDataDownloadCallback implements ICloudDownloadCallback
|
|||
|
||||
if(keyboardInfo!=null)
|
||||
{
|
||||
KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_FINISHED,
|
||||
KeyboardEventHandler.notifyListeners(KMKeyboardDownloaderActivity.getKbDownloadEventListeners(),
|
||||
KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_FINISHED,
|
||||
keyboardInfo, aCloudResult.kbdResult);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud.impl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
|
@ -8,6 +8,10 @@ import com.tavultesoft.kmea.KMKeyboardDownloaderActivity;
|
|||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler;
|
||||
import com.tavultesoft.kmea.R;
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
import com.tavultesoft.kmea.cloud.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.cloud.CloudDownloadMgr;
|
||||
import com.tavultesoft.kmea.cloud.ICloudDownloadCallback;
|
||||
import com.tavultesoft.kmea.util.FileUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
|
@ -27,7 +31,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall
|
|||
/**
|
||||
* the metadata result and all necessary downloads which should be started.
|
||||
*/
|
||||
public static class MetaDataResult
|
||||
static class MetaDataResult
|
||||
{
|
||||
CloudApiTypes.CloudApiReturns returnjson;
|
||||
CloudApiTypes.CloudApiParam params;
|
||||
|
|
@ -38,8 +42,6 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall
|
|||
|
||||
private static final String TAG = "CloudKeyboardMetaDldCb";
|
||||
|
||||
private ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener> downloadEventListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Additional Cloud API parameter: Is custom keyboard.
|
||||
*/
|
||||
|
|
@ -53,14 +55,7 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall
|
|||
*/
|
||||
public static final String PARAM_KB_ID = "kb_id";
|
||||
|
||||
/**
|
||||
* Listeners to notify about starting the data download.
|
||||
* @param aDownloadEventListeners
|
||||
*/
|
||||
public void setDownloadEventListeners(ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener> aDownloadEventListeners) {
|
||||
downloadEventListeners.clear();
|
||||
downloadEventListeners.addAll(aDownloadEventListeners);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initializeContext(Context context) {
|
||||
|
|
@ -118,7 +113,6 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall
|
|||
if(_r.returnjson.target== CloudApiTypes.ApiTarget.Keyboard)
|
||||
{
|
||||
CloudKeyboardDataDownloadCallback _callback = new CloudKeyboardDataDownloadCallback();
|
||||
_callback.setDownloadEventListeners(downloadEventListeners);
|
||||
_callback.setKeyboardInfo(_r.keyboardInfo);
|
||||
|
||||
if( CloudDownloadMgr.getInstance().alreadyDownloadingData(_r.additionalDownloadid))
|
||||
|
|
@ -126,7 +120,8 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall
|
|||
continue;
|
||||
}
|
||||
|
||||
KeyboardEventHandler.notifyListeners(downloadEventListeners,
|
||||
KeyboardEventHandler.notifyListeners(
|
||||
KMKeyboardDownloaderActivity.getKbDownloadEventListeners(),
|
||||
KeyboardEventHandler.EventType.KEYBOARD_DOWNLOAD_STARTED, _r.keyboardInfo, 0);
|
||||
|
||||
CloudDownloadMgr.getInstance().executeAsDownload(aContext, _r.additionalDownloadid, null, _callback,
|
||||
|
|
@ -142,7 +137,6 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall
|
|||
continue;
|
||||
}
|
||||
CloudLexicalPackageDownloadCallback _callback = new CloudLexicalPackageDownloadCallback();
|
||||
_callback.setDownloadEventListeners(downloadEventListeners);
|
||||
|
||||
Toast.makeText(aContext,
|
||||
aContext.getString(R.string.dictionary_download_start_in_background),
|
||||
|
|
@ -266,11 +260,12 @@ public class CloudKeyboardMetaDataDownloadCallback implements ICloudDownloadCall
|
|||
}
|
||||
if (oskFontUrls != null) {
|
||||
for (String url : oskFontUrls) {
|
||||
if (!urls.contains(url))
|
||||
if (fontUrls==null || ! fontUrls.contains(url)) {
|
||||
urls.add(new CloudApiTypes.CloudApiParam(CloudApiTypes.ApiTarget.KeyboardData, url)
|
||||
.setAdditionalProperty(
|
||||
CloudKeyboardDataDownloadCallback.PARAM_PACKAGE, _pkgID));
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
package com.tavultesoft.kmea.cloud.impl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.tavultesoft.kmea.KMKeyboardDownloaderActivity;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler;
|
||||
import com.tavultesoft.kmea.R;
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
import com.tavultesoft.kmea.cloud.ICloudDownloadCallback;
|
||||
import com.tavultesoft.kmea.packages.LexicalModelPackageProcessor;
|
||||
import com.tavultesoft.kmea.packages.PackageProcessor;
|
||||
import com.tavultesoft.kmea.util.FileUtils;
|
||||
|
|
@ -16,14 +17,10 @@ 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;
|
||||
|
||||
/**
|
||||
* Install lexical model.
|
||||
*/
|
||||
|
|
@ -36,18 +33,6 @@ public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallba
|
|||
private File resourceRoot;
|
||||
private File cacheDir;
|
||||
|
||||
private ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener> downloadEventListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* listeners to inform after installation is completed.
|
||||
* @param aDownloadEventListeners the listeners
|
||||
*/
|
||||
public void setDownloadEventListeners(ArrayList<KeyboardEventHandler.OnKeyboardDownloadEventListener> aDownloadEventListeners)
|
||||
{
|
||||
downloadEventListeners.clear();
|
||||
downloadEventListeners.addAll(aDownloadEventListeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeContext(Context context)
|
||||
{
|
||||
|
|
@ -108,7 +93,8 @@ public class CloudLexicalPackageDownloadCallback implements ICloudDownloadCallba
|
|||
|
||||
if(aCloudResult.installedLexicalModels != null)
|
||||
{
|
||||
KeyboardEventHandler.notifyListeners(downloadEventListeners, KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED,
|
||||
KeyboardEventHandler.notifyListeners(KMKeyboardDownloaderActivity.getKbDownloadEventListeners(),
|
||||
KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED,
|
||||
aCloudResult.installedLexicalModels, aCloudResult.kbdResult);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
package com.tavultesoft.kmea.data;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.tavultesoft.kmea.JSONParser;
|
||||
import com.tavultesoft.kmea.KMManager;
|
||||
|
||||
import com.tavultesoft.kmea.R;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class CloudCatalogDownloadTask extends AsyncTask<CloudApiTypes.CloudApiParam, Integer, CloudCatalogDownloadReturns> {
|
||||
|
||||
private static final String TAG = "CloudCatDownloadTask";
|
||||
|
||||
private final boolean hasConnection;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
private final Context context;
|
||||
|
||||
private final Dataset dataset;
|
||||
|
||||
private final CloudCatalogDownloadCallback callback;
|
||||
|
||||
|
||||
|
||||
public CloudCatalogDownloadTask(Context context, Dataset dataset, CloudCatalogDownloadCallback aCallback) {
|
||||
this.context = context;
|
||||
this.dataset = dataset;
|
||||
|
||||
this.hasConnection = KMManager.hasConnection(context);
|
||||
|
||||
|
||||
callback = aCallback;
|
||||
}
|
||||
|
||||
protected void showProgressDialog(final Runnable finishCallback) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
progressDialog = new ProgressDialog(context, R.style.AppTheme_Dialog_Progress);
|
||||
} else {
|
||||
progressDialog = new ProgressDialog(context);
|
||||
}
|
||||
progressDialog.setMessage(context.getString(R.string.getting_cloud_catalog));
|
||||
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.label_cancel),
|
||||
new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int which) {
|
||||
cancel(true);
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
if (finishCallback != null) {
|
||||
finishCallback.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
progressDialog.setCancelable(true);
|
||||
if (!((AppCompatActivity) context).isFinishing()) {
|
||||
progressDialog.show();
|
||||
} else {
|
||||
cancel(true);
|
||||
progressDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
|
||||
if (hasConnection) {
|
||||
showProgressDialog(new Runnable() {
|
||||
@Override
|
||||
public void run() { // runs on 'cancel' selection.
|
||||
callback.handleDownloadError();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CloudCatalogDownloadReturns doInBackground(CloudApiTypes.CloudApiParam... params) {
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<CloudApiTypes.CloudApiReturns> retrievedJSON = new ArrayList<>(params.length);
|
||||
if (progressDialog != null) {
|
||||
progressDialog.setMax(params.length);
|
||||
}
|
||||
|
||||
for (CloudApiTypes.CloudApiParam param : params) {
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
JSONArray dataArray = null;
|
||||
JSONObject dataObject = null;
|
||||
|
||||
if (hasConnection) {
|
||||
try {
|
||||
String remoteUrl = param.url;
|
||||
|
||||
if (param.type == CloudApiTypes.JSONType.Array) {
|
||||
dataArray = jsonParser.getJSONObjectFromUrl(remoteUrl, JSONArray.class);
|
||||
} else {
|
||||
dataObject = jsonParser.getJSONObjectFromUrl(remoteUrl, JSONObject.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
// Offline trouble! That said, we can't get anything, so we simply shouldn't add anything.
|
||||
}
|
||||
|
||||
if (param.type == CloudApiTypes.JSONType.Array) {
|
||||
retrievedJSON.add(new CloudApiTypes.CloudApiReturns(param.target, dataArray)); // Null if offline.
|
||||
} else {
|
||||
retrievedJSON.add(new CloudApiTypes.CloudApiReturns(param.target, dataObject)); // Null if offline.
|
||||
}
|
||||
if (progressDialog != null) {
|
||||
progressDialog.setProgress(progressDialog.getProgress());
|
||||
}
|
||||
}
|
||||
|
||||
return new CloudCatalogDownloadReturns(retrievedJSON); // Will report empty arrays/objects if offline.
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(CloudCatalogDownloadReturns jsonTuple) {
|
||||
|
||||
callback.saveDataToCache(jsonTuple);
|
||||
|
||||
if (progressDialog != null && progressDialog.isShowing()) {
|
||||
try {
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
} catch (Exception e) {
|
||||
progressDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
callback.ensureInitCloudReturn(context,dataset,jsonTuple);
|
||||
|
||||
callback.processCloudReturns(dataset,jsonTuple, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -12,6 +12,11 @@ import com.tavultesoft.kmea.KMKeyboardDownloaderActivity;
|
|||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.KeyboardPickerActivity;
|
||||
import com.tavultesoft.kmea.R;
|
||||
import com.tavultesoft.kmea.cloud.CloudApiTypes;
|
||||
import com.tavultesoft.kmea.cloud.impl.CloudCatalogDownloadCallback;
|
||||
import com.tavultesoft.kmea.cloud.impl.CloudCatalogDownloadReturns;
|
||||
import com.tavultesoft.kmea.cloud.CloudDataJsonUtil;
|
||||
import com.tavultesoft.kmea.cloud.CloudDownloadMgr;
|
||||
import com.tavultesoft.kmea.packages.JSONUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
|
@ -28,9 +33,6 @@ 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;
|
||||
|
|
@ -165,8 +167,7 @@ public class CloudRepository {
|
|||
{
|
||||
preCacheDataSet(context,updateHandler,onSuccess,onFailure);
|
||||
|
||||
if(USE_DOWNLOAD_MANAGER)
|
||||
downloadMetaDataFromServer(context,updateHandler,onSuccess,onFailure);
|
||||
downloadMetaDataFromServer(context,updateHandler,onSuccess,onFailure);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -292,7 +293,7 @@ public class CloudRepository {
|
|||
|
||||
preCacheDataSet(context,null,null,null);
|
||||
|
||||
if(USE_DOWNLOAD_MANAGER && CloudDownloadMgr.getInstance().alreadyDownloadingData(DOWNLOAD_IDENTIFIER_CATALOGUE)) {
|
||||
if(CloudDownloadMgr.getInstance().alreadyDownloadingData(DOWNLOAD_IDENTIFIER_CATALOGUE)) {
|
||||
String msg = context.getString(R.string.catalog_download_is_running_in_background);
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
|
@ -307,7 +308,6 @@ public class CloudRepository {
|
|||
* @param updateHandler An object that can handle update notification if desired.
|
||||
* @param onSuccess A callback to be triggered on completion of all queries and operations.
|
||||
* @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 downloadMetaDataFromServer(@NonNull Context context, UpdateHandler updateHandler, Runnable onSuccess, Runnable onFailure) {
|
||||
boolean loadKeyboardsFromCache = this.shouldUseCache(context, CloudDataJsonUtil.getKeyboardCacheFile(context));
|
||||
|
|
@ -355,23 +355,15 @@ public class CloudRepository {
|
|||
// We need the array to be exactly the same size as our entry count.
|
||||
CloudApiTypes.CloudApiParam[] params = new CloudApiTypes.CloudApiParam[cloudQueryEntries];
|
||||
cloudQueries.toArray(params);
|
||||
if (USE_DOWNLOAD_MANAGER) {
|
||||
if (CloudDownloadMgr.getInstance().alreadyDownloadingData(DOWNLOAD_IDENTIFIER_CATALOGUE)) {
|
||||
String msg = context.getString(R.string.catalog_download_is_running_in_background);
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
String msg = context.getString(R.string.catalog_download_start_in_background);
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
CloudDownloadMgr.getInstance().executeAsDownload(
|
||||
context, DOWNLOAD_IDENTIFIER_CATALOGUE, memCachedDataset, _download_callback, params);
|
||||
}
|
||||
|
||||
|
||||
if (CloudDownloadMgr.getInstance().alreadyDownloadingData(DOWNLOAD_IDENTIFIER_CATALOGUE)) {
|
||||
String msg = context.getString(R.string.catalog_download_is_running_in_background);
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
CloudCatalogDownloadTask downloadTask = new CloudCatalogDownloadTask(context, memCachedDataset, _download_callback);
|
||||
|
||||
// We can pass in multiple URLs; this format is extensible if we need extra catalogs in the future.
|
||||
downloadTask.execute(params);
|
||||
String msg = context.getString(R.string.catalog_download_start_in_background);
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
CloudDownloadMgr.getInstance().executeAsDownload(
|
||||
context, DOWNLOAD_IDENTIFIER_CATALOGUE, memCachedDataset, _download_callback, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,8 +121,8 @@ public class JSONUtils {
|
|||
|
||||
/**
|
||||
* Iterate through a JSONArray to determine if a language/keyboard/model ID exists.
|
||||
* @param {a} JSONArray to search
|
||||
* @param {id} String of the language/keyboard ID
|
||||
* @param a JSONArray to search
|
||||
* @param id String of the language/keyboard ID
|
||||
* @return int - Index if the ID is found (starting with 0). -1 if the ID doesn't exist
|
||||
*/
|
||||
public static int findID(JSONArray a, String id) {
|
||||
|
|
@ -171,7 +171,7 @@ public class JSONUtils {
|
|||
|
||||
/**
|
||||
* Mirror options information that comes from keyboard cloud catalog
|
||||
* @param String deviceType
|
||||
* @param deviceType
|
||||
* @return JSONObject
|
||||
*/
|
||||
public static JSONObject defaultOptions(String deviceType) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
## 13.0 alpha
|
||||
* Start version 13.0
|
||||
* New Features:
|
||||
* Adding a download manager to execute downloads in background (#2247,#2275)
|
||||
* Adding a download manager to execute downloads in background and cleanup the existing implementation (#2247, #2275, #2308)
|
||||
* Improve custom package installation: Show readme.htm before starting installation process (#2286)
|
||||
* Update target Android SDK version to 29 (#2279)
|
||||
* Add linting to Debug builds and resolve lint errors (#2305)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue