diff --git a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml
index 49d7fdac07..83aad3d6d9 100644
--- a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml
+++ b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml
@@ -226,6 +226,18 @@
android:parentActivityName=".KeymanSettingsActivity"
android:launchMode="singleTask"
android:theme="@style/AppTheme.Base" />
+
+
KeymanInstallActivity --> SelectPackageActivity --> SelectLanguageActivity
+ * Displays a list of available languages for the user to add for a given installed packageID/keyboardID.
+ */
+public final class SelectLanguageActivity extends AppCompatActivity {
+ private static final String TAG = "SelectLanguageActivity";
+ private static ArrayList> list = null;
+ private static KMListAdapter adapter = null;
+ private static Typeface titleFont = null;
+ private static final String titleKey = "title";
+ private static final String subtitleKey = "subtitle";
+ private static final String iconKey = "icon";
+ private static final String isEnabledKey = "isEnabled";
+ private static Context context;
+ private static final boolean excludeInstalledLanguages = false;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
+ context = this;
+
+ setContentView(R.layout.activity_list_layout);
+ final Toolbar toolbar = findViewById(R.id.list_toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+ getSupportActionBar().setDisplayShowTitleEnabled(false);
+
+ final ListView listView = findViewById(R.id.listView);
+ listView.setFastScrollEnabled(true);
+
+ final Keyboard keyboard = (Keyboard)getIntent().getSerializableExtra("keyboard");
+ final String packageID = keyboard.getPackageID();
+ final String keyboardID = keyboard.getKeyboardID();
+ final String keyboardName = keyboard.getKeyboardName();
+ String title_install = String.format(getString(R.string.title_select_language_for_package), keyboardName);
+ String title_no_install = getString(R.string.all_languages_installed);
+ final TextView textView = findViewById(R.id.bar_title);
+ textView.setText(title_no_install);
+ if (titleFont != null) {
+ textView.setTypeface(titleFont, Typeface.BOLD);
+ }
+
+ // Get the list of available Keyboards from kmp.json
+ File resourceRoot = new File(context.getDir("data", Context.MODE_PRIVATE).toString() + File.separator);
+ PackageProcessor kmpProcessor = new PackageProcessor(resourceRoot);
+ List availableKeyboardsList = kmpProcessor.getKeyboardList(
+ packageID, keyboardID, excludeInstalledLanguages);
+
+ final String noIcon = "0";
+ list = new ArrayList>();
+ for (Keyboard k : availableKeyboardsList) {
+ HashMap hashMap = new HashMap<>();
+ hashMap.put(titleKey, k.getLanguageName());
+ hashMap.put(subtitleKey, k.getLanguageID());
+ String enable = "true";
+ String icon = String.valueOf(R.drawable.ic_arrow_forward);
+ if (!excludeInstalledLanguages && KeyboardController.getInstance().keyboardExists(
+ k.getPackageID(), k.getKeyboardID(), k.getLanguageID())) {
+ icon = String.valueOf(R.drawable.ic_check);
+ enable = "false";
+ } else {
+ // Update title
+ textView.setText(title_install);
+ }
+ hashMap.put(iconKey, icon);
+ hashMap.put(isEnabledKey, enable);
+ list.add(hashMap);
+ }
+
+ String[] from = new String[]{titleKey, subtitleKey, iconKey};
+ int[] to = new int[]{R.id.text1, R.id.text2, com.tavultesoft.kmea.R.id.image1};
+
+ adapter = new KMListAdapter(context, list, R.layout.list_row_layout2, from, to);
+ listView.setAdapter(adapter);
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ HashMap hashMap = (HashMap) parent.getItemAtPosition(position);
+ Keyboard k = availableKeyboardsList.get(position);
+ KMManager.addKeyboard(context, k);
+ String confirmation = String.format(getString(R.string.added_language_to_keyboard),
+ k.getLanguageName(), k.getKeyboardName());
+ Toast.makeText(context, confirmation, Toast.LENGTH_LONG).show();
+ finish();
+ }
+ });
+ }
+
+ @Override
+ public boolean onSupportNavigateUp() {
+ super.onBackPressed();
+ return true;
+ }
+}
diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java
new file mode 100644
index 0000000000..cf25028dae
--- /dev/null
+++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright (C) 2020 SIL International. All rights reserved.
+ */
+
+package com.tavultesoft.kmapro;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+
+import com.tavultesoft.kmea.data.Keyboard;
+import com.tavultesoft.kmea.data.KeyboardController;
+import com.tavultesoft.kmea.util.KMLog;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Keyman Settings --> KeymanInstallActivity --> SelectPackageActivity
+ * Displays a list of installed package ID / keyboard IDs so the user can select a language from the kmp.json
+ */
+public final class SelectPackageActivity extends AppCompatActivity {
+ private static final String TAG = "SelectPackageActivity";
+ private static ArrayList> list = null;
+ private static Typeface titleFont = null;
+ private static final String titleKey = "title";
+ private static final String subtitleKey = "subtitle";
+ private static final String iconKey = "icon";
+ private static Context context;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
+ context = this;
+
+ setContentView(R.layout.activity_list_layout);
+ final Toolbar toolbar = findViewById(R.id.list_toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+ getSupportActionBar().setDisplayShowTitleEnabled(false);
+
+ final ListView listView = findViewById(R.id.listView);
+ listView.setFastScrollEnabled(true);
+
+ Bundle bundle = getIntent().getExtras();
+
+ final TextView textView = findViewById(R.id.bar_title);
+ textView.setText(getString(R.string.title_select_keyboard_package_list));
+ if (titleFont != null) {
+ textView.setTypeface(titleFont, Typeface.BOLD);
+ }
+
+ List packagesList = KeyboardController.getInstance().getInstalledPackagesList();
+ if (packagesList == null) {
+ // Should never actually happen
+ KMLog.LogError(TAG, "Installed keyboard package list is empty");
+ finish();
+ }
+
+ list = new ArrayList>();
+ for (Keyboard k : packagesList) {
+ String keyboardName = k.getKeyboardName();
+ String pkgID = k.getPackageID();
+ final String noIcon = "0";
+ HashMap hashMap = new HashMap<>();
+ hashMap.put(titleKey, keyboardName);
+ hashMap.put(subtitleKey, pkgID);
+ String icon = String.valueOf(R.drawable.ic_arrow_forward);
+ hashMap.put(iconKey, icon);
+ list.add(hashMap);
+ }
+
+ String[] from = new String[]{titleKey, subtitleKey, iconKey};
+ int[] to = new int[]{com.tavultesoft.kmea.R.id.text1, com.tavultesoft.kmea.R.id.text2, com.tavultesoft.kmea.R.id.image1};
+
+ ListAdapter adapter = new SimpleAdapter(context, list, com.tavultesoft.kmea.R.layout.list_row_layout2, from, to) {
+ };
+ listView.setAdapter(adapter);
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ HashMap hashMap = (HashMap) parent.getItemAtPosition(position);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable("keyboard", packagesList.get(position));
+ Intent intent = new Intent(context, SelectLanguageActivity.class);
+ intent.putExtras(bundle);
+ context.startActivity(intent);
+ }
+ });
+ }
+
+ @Override
+ public boolean onSupportNavigateUp() {
+ super.onBackPressed();
+ return true;
+ }
+}
diff --git a/android/KMAPro/kMAPro/src/main/res/values/strings.xml b/android/KMAPro/kMAPro/src/main/res/values/strings.xml
index 910e2efd18..6cc1c176ca 100644
--- a/android/KMAPro/kMAPro/src/main/res/values/strings.xml
+++ b/android/KMAPro/kMAPro/src/main/res/values/strings.xml
@@ -58,6 +58,12 @@
Add language to installed keyboard
(from keyboard package)
+
+ Select Keyboard Package
+ Select language for %1$s
+ Added language %1$s to %2$s
+ All languages already installed
+
Search or type URL
Bookmarks
diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/KeyboardController.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/KeyboardController.java
index d5dfffd904..2e7c3c0eaa 100644
--- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/KeyboardController.java
+++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/KeyboardController.java
@@ -122,6 +122,37 @@ public class KeyboardController {
}
}
+ /**
+ * Returns the list of installed keyboards with unique packageID/keyboardID
+ */
+ public List getInstalledPackagesList() {
+ if (!isInitialized) {
+ KMLog.LogError(TAG, "getInstalledPackagesList while KeyboardController() not initialized");
+ return null;
+ }
+ synchronized (list) {
+ List packagesList = new ArrayList();
+ // Iterate through the installed keyboards list to find unique packageID/keyboardID
+ for (int i=0; i
+ */
+ private List getKeyboards(JSONObject keyboardJSON, Keyboard baseKeyboard,
+ boolean excludeInstalledLanguages ) {
+ List list = new ArrayList();
+ String packageID = baseKeyboard.getPackageID();
+ String keyboardID = baseKeyboard.getKeyboardID();
+ try {
+ JSONArray languages = keyboardJSON.getJSONArray("languages");
+ for (int j = 0; j < languages.length(); j++) {
+ JSONObject language = languages.getJSONObject(j);
+ String languageID = language.getString("id");
+ String languageName = language.getString("name");
+ if (!excludeInstalledLanguages ||
+ !(KeyboardController.getInstance().keyboardExists(packageID, keyboardID, languageID))) {
+ // Copy keyboard info and update language
+ Keyboard newKeyboard = new Keyboard(baseKeyboard);
+ newKeyboard.setLanguage(languageID, languageName);
+ list.add(newKeyboard);
+ }
+ }
+ } catch (Exception e) {
+ KMLog.LogException(TAG, "getKeyboards() ", e);
+ }
+ return list;
+ }
+
+ /**
+ * Get a list of available keyboard and language pairings that are available to add
+ * (parses the kmp.json for the language list)
+ * @param packageID - String of the package ID
+ * @param keyboardID - String of the keyboard ID
+ * @param excludeInstalledLanguages - Boolean whether to exclude
+ * installed languages from the returned list.
+ * @return List of based on kmp.json. If excludeInstalledLanguages is true, this list
+ * excludes languages already installed
+ */
+ public List getKeyboardList(String packageID, String keyboardID, boolean excludeInstalledLanguages) {
+ File packagePath = new File(resourceRoot, KMManager.KMDefault_AssetPackages + File.separator + packageID);
+ List list = new ArrayList();
+ JSONObject infoJSON = loadPackageInfo(packagePath);
+ try {
+ JSONArray keyboards = infoJSON.getJSONArray("keyboards");
+
+ for (int i = 0; i < keyboards.length(); i++) {
+ JSONObject keyboard = keyboards.getJSONObject(i);
+ if (keyboardID.equals(keyboard.getString("id"))) {
+ // Find the keyboard already installed. We'll use it as the base
+ // for creating new keyboards
+ int baseKeyboardIndex = KeyboardController.getInstance().getKeyboardIndex(packageID, keyboardID, "");
+ if (baseKeyboardIndex == KeyboardController.INDEX_NOT_FOUND) {
+ continue;
+ }
+ Keyboard baseKeyboard = KeyboardController.getInstance().getKeyboardInfo(baseKeyboardIndex);
+ return getKeyboards(keyboard, baseKeyboard, excludeInstalledLanguages);
+ }
+ }
+ } catch (Exception e) {
+ KMLog.LogException(TAG, "getKeyboardList() ", e);
+ }
+ return list;
+ }
+
/**
* The master KMP processing method; use after a .kmp download to fully install within the filesystem.
* This will overwrite an existing package.