mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-30 11:37:45 +00:00
Merge pull request #2020 from keymanapp/android-uninstall
[Android] Fix keyboard and model info pages
This commit is contained in:
commit
a476a1e2df
15 changed files with 91 additions and 41 deletions
|
|
@ -192,15 +192,6 @@
|
|||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme.Base" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.tavultesoft.kmapro.fileProvider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -69,6 +69,16 @@
|
|||
android:theme="@style/Theme.AppCompat.Light.Dialog" >
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.tavultesoft.kmea.fileProvider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -39,6 +39,7 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity {
|
|||
public static final String ARG_MODEL_ID = "KMKeyboardActivity.modelID";
|
||||
public static final String ARG_MODEL_NAME = "KMKeyboardActivity.modelName";
|
||||
public static final String ARG_MODEL_URL = "KMKeyboardActivity.modelURL";
|
||||
public static final String ARG_MODEL_CUSTOM_HELP_LINK = "KMKeyboardActivity.customHelpLink";
|
||||
|
||||
// custom keyboard
|
||||
public static final String ARG_KEYBOARD = "KMKeyboardActivity.keyboard";
|
||||
|
|
|
|||
|
|
@ -701,6 +701,7 @@ public final class KMManager {
|
|||
languageJSONArray.put(languageID);
|
||||
modelObj.put("languages", languageJSONArray);
|
||||
modelObj.put("path", path);
|
||||
modelObj.put("CustomHelpLink", lexicalModelInfo.get(KMKey_CustomHelpLink));
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Invalid lexical model to register");
|
||||
return false;
|
||||
|
|
@ -770,7 +771,7 @@ public final class KMManager {
|
|||
* Search the installed lexical models list and see if there's an
|
||||
* associated model for a given language ID
|
||||
* @param langId - String of the language ID
|
||||
* @return HashMap<String, String> Keyboard information if it exists. Otherwise null
|
||||
* @return HashMap<String, String> Model information if it exists. Otherwise null
|
||||
*/
|
||||
public static HashMap<String, String> getAssociatedLexicalModel(String langId) {
|
||||
ArrayList<HashMap<String, String>> lexicalModelsList = getLexicalModelsList(appContext);
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ public final class KeyboardInfoActivity extends AppCompatActivity {
|
|||
// Starting with Android N, you can't pass file:// to intents, so we use FileProvider
|
||||
try {
|
||||
Uri contentUri = FileProvider.getUriForFile(
|
||||
context, getApplication().getPackageName() + ".fileProvider", customHelp);
|
||||
context, "com.tavultesoft.kmea.fileProvider", customHelp);
|
||||
i.setDataAndType(contentUri, "text/html");
|
||||
} catch (Exception e) {
|
||||
Log.e("KeyboardInfoActivity", "Failed to access " + customHelp.toString());
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import android.widget.SimpleAdapter;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.tavultesoft.kmea.util.FileUtils;
|
||||
import com.tavultesoft.kmea.util.MapCompat;
|
||||
|
||||
import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_DELETE_KEYBOARD;
|
||||
|
||||
|
|
@ -41,6 +42,7 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
private final String titleKey = "title";
|
||||
private final String subtitleKey = "subtitle";
|
||||
private final String iconKey = "icon";
|
||||
private final String isEnabledKey = "isEnabled";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
|
@ -68,9 +70,10 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
if (titleFont != null)
|
||||
textView.setTypeface(titleFont, Typeface.BOLD);
|
||||
|
||||
boolean isCustomKeyboard = getIntent().getBooleanExtra(KMManager.KMKey_CustomKeyboard, false);
|
||||
final boolean isCustomKeyboard = getIntent().getBooleanExtra(KMManager.KMKey_CustomKeyboard, false);
|
||||
|
||||
infoList = new ArrayList<HashMap<String, String>>();
|
||||
// Display keyboard version title
|
||||
String icon = "0";
|
||||
HashMap<String, String> hashMap = new HashMap<String, String>();
|
||||
hashMap.put(titleKey, getString(R.string.keyboard_version));
|
||||
|
|
@ -78,15 +81,18 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
hashMap.put(iconKey, icon);
|
||||
infoList.add(hashMap);
|
||||
|
||||
// Display keyboard help link
|
||||
final String customHelpLink = getIntent().getStringExtra(KMManager.KMKey_CustomHelpLink);
|
||||
if (!isCustomKeyboard || customHelpLink != null) {
|
||||
if (isCustomKeyboard && customHelpLink == null) {
|
||||
icon = "0";
|
||||
} else {
|
||||
icon = String.valueOf(R.drawable.ic_arrow_forward);
|
||||
hashMap = new HashMap<String, String>();
|
||||
hashMap.put(titleKey, getString(R.string.help_link));
|
||||
hashMap.put(subtitleKey, "");
|
||||
hashMap.put(iconKey, icon);
|
||||
infoList.add(hashMap);
|
||||
}
|
||||
hashMap = new HashMap<String, String>();
|
||||
hashMap.put(titleKey, getString(R.string.help_link));
|
||||
hashMap.put(subtitleKey, "");
|
||||
hashMap.put(iconKey, icon);
|
||||
infoList.add(hashMap);
|
||||
|
||||
if (!packageID.equalsIgnoreCase(KMManager.KMDefault_UndefinedPackageID) ||
|
||||
!kbID.equalsIgnoreCase(KMManager.KMDefault_KeyboardID)) {
|
||||
|
|
@ -100,13 +106,34 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
|
||||
String[] from = new String[]{titleKey, subtitleKey, iconKey};
|
||||
int[] to = new int[]{R.id.text1, R.id.text2, R.id.image1};
|
||||
ListAdapter adapter = new SimpleAdapter(context, infoList, R.layout.list_row_layout2, from, to);
|
||||
|
||||
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);
|
||||
String itemTitle = MapCompat.getOrDefault(hashMap, titleKey, "");
|
||||
|
||||
if (itemTitle.equals(getString(R.string.keyboard_version))) {
|
||||
// No point in 'clicking' on version info.
|
||||
return false;
|
||||
// Visibly disables the help option when help isn't available.
|
||||
} else if (itemTitle.equals(getString(R.string.help_link)) && isCustomKeyboard && customHelpLink == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.isEnabled(position);
|
||||
}
|
||||
};
|
||||
listView.setAdapter(adapter);
|
||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (position == 1) {
|
||||
HashMap<String, String> hashMap = (HashMap<String, String>)parent.getItemAtPosition(position);
|
||||
String itemTitle = MapCompat.getOrDefault(hashMap, titleKey, "");
|
||||
|
||||
// "Help" link clicked
|
||||
if (itemTitle.equals(getString(R.string.help_link))) {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
|
||||
if (customHelpLink != null) {
|
||||
|
|
@ -116,7 +143,7 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
// Starting with Android N, you can't pass file:// to intents, so we use FileProvider
|
||||
try {
|
||||
Uri contentUri = FileProvider.getUriForFile(
|
||||
context, getApplication().getPackageName() + ".fileProvider", customHelp);
|
||||
context, "com.tavultesoft.kmea.fileProvider", customHelp);
|
||||
i.setDataAndType(contentUri, "text/html");
|
||||
} catch (Exception e) {
|
||||
Log.e("KeyboardInfoActivity", "Failed to access " + customHelp.toString());
|
||||
|
|
@ -131,7 +158,8 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
i.setData(Uri.parse(helpUrlStr));
|
||||
startActivity(i);
|
||||
}
|
||||
} else if (position == 2) {
|
||||
// "Uninstall Keyboard" clicked
|
||||
} else if (itemTitle.equals(getString(R.string.uninstall_keyboard))) {
|
||||
// Uninstall selected keyboard
|
||||
String title = String.format("%s: %s", languageName, kbName);
|
||||
String keyboardKey = String.format("%s_%s", languageID, kbID);
|
||||
|
|
@ -140,11 +168,7 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
|
|||
dialog.show(getFragmentManager(), "dialog");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public final class LanguageSettingsActivity extends AppCompatActivity {
|
|||
private String associatedLexicalModel = "";
|
||||
private String lgCode;
|
||||
private String lgName;
|
||||
private String customHelpLink;
|
||||
private SharedPreferences prefs;
|
||||
|
||||
private final static String TAG = "LanguageSettingsAct";
|
||||
|
|
@ -119,6 +120,7 @@ public final class LanguageSettingsActivity extends AppCompatActivity {
|
|||
|
||||
lgCode = bundle.getString(KMManager.KMKey_LanguageID);
|
||||
lgName = bundle.getString(KMManager.KMKey_LanguageName);
|
||||
customHelpLink = bundle.getString(KMManager.KMKey_CustomHelpLink);
|
||||
|
||||
// Necessary to properly insert a language name into the title. (Has a %s slot for it.)
|
||||
String title = String.format(getString(R.string.title_language_settings), lgName);
|
||||
|
|
@ -168,6 +170,7 @@ public final class LanguageSettingsActivity extends AppCompatActivity {
|
|||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KMManager.KMKey_LanguageID, lgCode);
|
||||
bundle.putString(KMManager.KMKey_LanguageName, lgName);
|
||||
bundle.putString(KMManager.KMKey_CustomHelpLink, customHelpLink);
|
||||
Intent i = new Intent(context, ModelPickerActivity.class);
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
i.putExtras(bundle);
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ public final class LanguagesSettingsActivity extends AppCompatActivity
|
|||
|
||||
if(associatedLexicalModel != null) {
|
||||
args.putString(KMManager.KMKey_LexicalModelName, associatedLexicalModel.get(KMManager.KMKey_LexicalModelName));
|
||||
args.putString(KMManager.KMKey_CustomHelpLink, associatedLexicalModel.get(KMManager.KMKey_CustomHelpLink));
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, LanguageSettingsActivity.class);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import android.widget.TextView;
|
|||
import android.widget.Toast;
|
||||
|
||||
import com.tavultesoft.kmea.util.FileUtils;
|
||||
import com.tavultesoft.kmea.util.MapCompat;
|
||||
|
||||
import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_DELETE_MODEL;
|
||||
|
||||
|
|
@ -72,10 +73,9 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
textView.setTypeface(titleFont, Typeface.BOLD);
|
||||
|
||||
final String modelVersion = getIntent().getStringExtra(KMManager.KMKey_LexicalModelVersion);
|
||||
final String customModel = getIntent().getStringExtra(KMManager.KMKey_CustomModel);
|
||||
|
||||
infoList = new ArrayList<HashMap<String, String>>();
|
||||
// Display model title
|
||||
// Display model version title
|
||||
final String noIcon = "0";
|
||||
HashMap<String, String> hashMap = new HashMap<String, String>();
|
||||
hashMap.put(titleKey, getString(R.string.model_version));
|
||||
|
|
@ -85,17 +85,16 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
|
||||
// Display model help link
|
||||
final String customHelpLink = getIntent().getStringExtra(KMManager.KMKey_CustomHelpLink);
|
||||
|
||||
String icon = String.valueOf(R.drawable.ic_arrow_forward);
|
||||
hashMap = new HashMap<String, String>();
|
||||
hashMap.put(titleKey, getString(R.string.help_link));
|
||||
hashMap.put(subtitleKey, "");
|
||||
if(customHelpLink != null) {
|
||||
// For now, lexical model help only available when installed via custom packages
|
||||
if(!customHelpLink.equals("")) {
|
||||
hashMap.put(iconKey, icon);
|
||||
} else {
|
||||
hashMap.put(iconKey, noIcon);
|
||||
}
|
||||
|
||||
infoList.add(hashMap);
|
||||
|
||||
// Display link to uninstall model
|
||||
|
|
@ -111,11 +110,14 @@ 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) {
|
||||
if(position == 0) {
|
||||
HashMap<String, String> hashMap = (HashMap<String, String>)infoList.get(position);
|
||||
String itemTitle = MapCompat.getOrDefault(hashMap, titleKey, "");
|
||||
|
||||
if (itemTitle.equals(getString(R.string.model_version))) {
|
||||
// No point in 'clicking' on version info.
|
||||
return false;
|
||||
// Visibly disables the help option when help isn't available.
|
||||
} else if(position == 1 && customHelpLink == null) {
|
||||
} else if (itemTitle.equals(getString(R.string.help_link)) && customHelpLink.equals("")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -127,18 +129,21 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (position == 1) {
|
||||
// Help link to model
|
||||
HashMap<String, String> hashMap = (HashMap<String, String>)parent.getItemAtPosition(position);
|
||||
String itemTitle = MapCompat.getOrDefault(hashMap, titleKey, "");
|
||||
|
||||
// "Help" link clicked
|
||||
if (itemTitle.equals(getString(R.string.help_link))) {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
|
||||
if (customHelpLink != null) {
|
||||
if (!customHelpLink.equals("")) {
|
||||
if (FileUtils.isWelcomeFile(customHelpLink)) {
|
||||
File customHelp = new File(new File(customHelpLink).getAbsolutePath());
|
||||
i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
// Starting with Android N, you can't pass file:// to intents, so we use FileProvider
|
||||
try {
|
||||
Uri contentUri = FileProvider.getUriForFile(
|
||||
context, getApplication().getPackageName() + ".fileProvider", customHelp);
|
||||
context, "com.tavultesoft.kmea.fileProvider", customHelp);
|
||||
i.setDataAndType(contentUri, "text/html");
|
||||
} catch (Exception e) {
|
||||
Log.e("ModelInfoActivity", "Failed to access " + customHelp.toString());
|
||||
|
|
@ -151,8 +156,9 @@ public final class ModelInfoActivity extends AppCompatActivity {
|
|||
} else {
|
||||
// We should always have a help file packaged with models.
|
||||
}
|
||||
} else if (position == 2) {
|
||||
// Confirmation to delete model
|
||||
// "Uninstall Model" clicked
|
||||
} 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(
|
||||
DIALOG_TYPE_DELETE_MODEL, modelName, getString(R.string.confirm_delete_model), lexicalModelKey);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public final class ModelPickerActivity extends AppCompatActivity {
|
|||
private final static String TAG = "ModelPickerActivity";
|
||||
|
||||
private String languageID = "";
|
||||
private String customHelpLink = "";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
|
@ -63,9 +64,11 @@ public final class ModelPickerActivity extends AppCompatActivity {
|
|||
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
String newLanguageID = bundle.getString(KMManager.KMKey_LanguageID);
|
||||
String newCustomHelpLink = bundle.getString(KMManager.KMKey_CustomHelpLink);
|
||||
|
||||
// Sometimes we need to re-initialize the list of models that are displayed in the ListView
|
||||
languageID = newLanguageID;
|
||||
customHelpLink = newCustomHelpLink;
|
||||
|
||||
final String languageName = bundle.getString(KMManager.KMKey_LanguageName);
|
||||
textView.setText(String.format(getString(R.string.model_picker_header), languageName));
|
||||
|
|
@ -123,8 +126,7 @@ public final class ModelPickerActivity extends AppCompatActivity {
|
|||
bundle.putString(KMManager.KMKey_LexicalModelName, modelName);
|
||||
bundle.putString(KMManager.KMKey_LexicalModelVersion,
|
||||
modelInfo.get(KMManager.KMKey_LexicalModelVersion));
|
||||
bundle.putString(KMManager.KMKey_CustomModel,
|
||||
MapCompat.getOrDefault(new HashMap<>(modelInfo), KMManager.KMKey_CustomModel, "N"));
|
||||
bundle.putString(KMManager.KMKey_CustomHelpLink, customHelpLink);
|
||||
Intent i = new Intent(context, ModelInfoActivity.class);
|
||||
i.putExtras(bundle);
|
||||
startActivityForResult(i, 1);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ public class LexicalModel implements Serializable, LanguageResource {
|
|||
return null;
|
||||
}
|
||||
|
||||
String customHelpLink = map.get(KMManager.KMKey_CustomHelpLink);
|
||||
|
||||
bundle.putString(KMKeyboardDownloaderActivity.ARG_PKG_ID, getPackage());
|
||||
bundle.putString(KMKeyboardDownloaderActivity.ARG_MODEL_ID, getResourceId());
|
||||
bundle.putString(KMKeyboardDownloaderActivity.ARG_LANG_ID, getLanguageCode());
|
||||
|
|
@ -71,6 +73,7 @@ public class LexicalModel implements Serializable, LanguageResource {
|
|||
bundle.putString(KMKeyboardDownloaderActivity.ARG_LANG_NAME, getLanguageName());
|
||||
bundle.putBoolean(KMKeyboardDownloaderActivity.ARG_IS_CUSTOM, false);
|
||||
bundle.putString(KMKeyboardDownloaderActivity.ARG_MODEL_URL, modelURL);
|
||||
bundle.putString(KMKeyboardDownloaderActivity.ARG_MODEL_CUSTOM_HELP_LINK, customHelpLink);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ public class LexicalModelPackageProcessor extends PackageProcessor {
|
|||
File welcomeFile = new File(packageDir, "welcome.htm");
|
||||
// Only storing relative instead of absolute paths as a convenience for unit tests.
|
||||
models[i].put(KMManager.KMKey_CustomHelpLink, welcomeFile.getPath());
|
||||
} else {
|
||||
models[i].put(KMManager.KMKey_CustomHelpLink, "");
|
||||
}
|
||||
}
|
||||
return models;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- path is relative to /data/data/com.tavultesoft.kmapro/files/ -->
|
||||
<files-path name="cloud" path="../app_data/cloud/" />
|
||||
<files-path name="models" path="../app_data/models/" />
|
||||
<files-path name="packages" path="../app_data/packages/" />
|
||||
</paths>
|
||||
|
|
@ -73,6 +73,7 @@ public class LexicalModelPackageProcessorTest {
|
|||
en_custom.put(KMManager.KMKey_LexicalModelVersion, "1.0.0");
|
||||
en_custom.put(KMManager.KMKey_LanguageID, "en");
|
||||
en_custom.put(KMManager.KMKey_LanguageName, "English");
|
||||
en_custom.put(KMManager.KMKey_CustomHelpLink, "");
|
||||
|
||||
Assert.assertEquals(en_custom, models[0]);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
* New Feature:
|
||||
* Allow user to "Add keyboard from local device" from Settings menu (#1992)
|
||||
|
||||
* Bug Fix:
|
||||
* Fix keyboard and dictionary info pages (#2020)
|
||||
|
||||
## 2019-08-27 12.0.4080 beta
|
||||
* Fix menu icon and text alignment (#1999)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue