mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-27 01:57:41 +00:00
Merge pull request #3255 from keymanapp/modify/android/add-language-from-package
feat(android): Implement menu to add language for installed keyboard pkg
This commit is contained in:
commit
3a6dcc2ddd
7 changed files with 366 additions and 15 deletions
|
|
@ -226,6 +226,18 @@
|
|||
android:parentActivityName=".KeymanSettingsActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme.Base" />
|
||||
<activity
|
||||
android:name=".SelectPackageActivity"
|
||||
android:label="@string/app_name"
|
||||
android:parentActivityName=".KeymanSettingsInstallActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme.Base" />
|
||||
<activity
|
||||
android:name=".SelectLanguageActivity"
|
||||
android:label="@string/app_name"
|
||||
android:parentActivityName=".SelectPackageActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme.Base" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import android.widget.TextView;
|
|||
|
||||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.KMPBrowserActivity;
|
||||
import com.tavultesoft.kmea.data.KeyboardController;
|
||||
import com.tavultesoft.kmea.util.MapCompat;
|
||||
|
||||
public class KeymanSettingsInstallActivity extends AppCompatActivity {
|
||||
|
|
@ -107,6 +108,11 @@ public class KeymanSettingsInstallActivity extends AppCompatActivity {
|
|||
if (itemTitle.equals(getString(R.string.install_from_other_device))) {
|
||||
// Scan QR code not implemented yet
|
||||
return false;
|
||||
} else if (itemTitle.equals(getString(R.string.add_language_to_installed_keyboard))) {
|
||||
if (KeyboardController.getInstance().getInstalledPackagesList() == null) {
|
||||
// Disable if no keyboard packages installed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return super.isEnabled(position);
|
||||
|
|
@ -150,7 +156,8 @@ public class KeymanSettingsInstallActivity extends AppCompatActivity {
|
|||
|
||||
// Add language from keyboard package already installed
|
||||
} else if (itemTitle.equals(getString(R.string.add_language_to_installed_keyboard))) {
|
||||
// TODO
|
||||
Intent intent = new Intent(context, SelectPackageActivity.class);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,126 @@
|
|||
/**
|
||||
* Copyright (C) 2020 SIL International. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.tavultesoft.kmapro;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.data.Keyboard;
|
||||
import com.tavultesoft.kmea.data.KeyboardController;
|
||||
import com.tavultesoft.kmea.packages.PackageProcessor;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Keyman Settings --> 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<HashMap<String, String>> 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<Keyboard> availableKeyboardsList = kmpProcessor.getKeyboardList(
|
||||
packageID, keyboardID, excludeInstalledLanguages);
|
||||
|
||||
final String noIcon = "0";
|
||||
list = new ArrayList<HashMap<String, String>>();
|
||||
for (Keyboard k : availableKeyboardsList) {
|
||||
HashMap<String, String> 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<String, String> hashMap = (HashMap<String, String>) 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<HashMap<String, String>> 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<Keyboard> packagesList = KeyboardController.getInstance().getInstalledPackagesList();
|
||||
if (packagesList == null) {
|
||||
// Should never actually happen
|
||||
KMLog.LogError(TAG, "Installed keyboard package list is empty");
|
||||
finish();
|
||||
}
|
||||
|
||||
list = new ArrayList<HashMap<String, String>>();
|
||||
for (Keyboard k : packagesList) {
|
||||
String keyboardName = k.getKeyboardName();
|
||||
String pkgID = k.getPackageID();
|
||||
final String noIcon = "0";
|
||||
HashMap<String, String> 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<String, String> hashMap = (HashMap<String, String>) 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +58,12 @@
|
|||
<string name="add_language_to_installed_keyboard">Add language to installed keyboard</string>
|
||||
<string name="add_language_subtext">(from keyboard package)</string>
|
||||
|
||||
<!-- Select Package and Select Language menu strings -->
|
||||
<string name="title_select_keyboard_package_list">Select Keyboard Package</string>
|
||||
<string name="title_select_language_for_package">Select language for %1$s</string>
|
||||
<string name="added_language_to_keyboard">Added language %1$s to %2$s</string>
|
||||
<string name="all_languages_installed">All languages already installed</string>
|
||||
|
||||
<!-- Web Browser strings -->
|
||||
<string name="hint_text">Search or type URL</string>
|
||||
<string name="title_bookmarks">Bookmarks</string>
|
||||
|
|
|
|||
|
|
@ -122,6 +122,37 @@ public class KeyboardController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of installed keyboards with unique packageID/keyboardID
|
||||
*/
|
||||
public List<Keyboard> getInstalledPackagesList() {
|
||||
if (!isInitialized) {
|
||||
KMLog.LogError(TAG, "getInstalledPackagesList while KeyboardController() not initialized");
|
||||
return null;
|
||||
}
|
||||
synchronized (list) {
|
||||
List<Keyboard> packagesList = new ArrayList<Keyboard>();
|
||||
// Iterate through the installed keyboards list to find unique packageID/keyboardID
|
||||
for (int i=0; i<list.size(); i++) {
|
||||
Keyboard k = list.get(i);
|
||||
String pkgID = k.getPackageID();
|
||||
String keyboardID = k.getKeyboardID();
|
||||
// Ignore "cloud" keyboards"
|
||||
if (pkgID.equals(KMManager.KMDefault_UndefinedPackageID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we search getKeyboardIndex with blank languageID, it will give us the first
|
||||
// unique pkgID/keyboardID keyboard in the list
|
||||
int firstMatchingIndex = getKeyboardIndex(pkgID, keyboardID, "");
|
||||
if (firstMatchingIndex != KeyboardController.INDEX_NOT_FOUND && (firstMatchingIndex == i)) {
|
||||
packagesList.add(k);
|
||||
}
|
||||
}
|
||||
return packagesList;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the keyboard info at index
|
||||
* @param index - int
|
||||
|
|
@ -176,20 +207,6 @@ public class KeyboardController {
|
|||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a languageID and keyboardID, return the index of the matching keyboard.
|
||||
* If no match, returns INDEX_NOT_FOUND
|
||||
* @param languageID - String of the language ID
|
||||
* @param keyboardID - String of the keyboard ID
|
||||
* @return int - Index of the matching keyboard
|
||||
*/
|
||||
/*
|
||||
public int getKeyboardIndex(String languageID, String keyboardID) {
|
||||
String key = String.format("%s_%s", languageID, keyboardID);
|
||||
return getKeyboardIndex(key);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Given a packageID, keyboardID, and languageID, return the index of the matching keyboard.
|
||||
* If language ID not specified, only the package ID and keyboard ID are matched
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import androidx.annotation.NonNull;
|
|||
|
||||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.JSONParser;
|
||||
import com.tavultesoft.kmea.data.Keyboard;
|
||||
import com.tavultesoft.kmea.data.KeyboardController;
|
||||
import com.tavultesoft.kmea.util.FileUtils;
|
||||
import com.tavultesoft.kmea.util.KMLog;
|
||||
import com.tavultesoft.kmea.util.ZipUtils;
|
||||
|
|
@ -408,6 +410,75 @@ public class PackageProcessor {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a list of Keyboards from the keyboard JSONObject. baseKeyboard contains
|
||||
* keyboard information that's already installed.
|
||||
* @param keyboardJSON JSONObject - Keyboard JSONObject from kmp.json (entry for keyboardID)
|
||||
* @param baseKeyboard Keyboard - information of the keyboard that's already installed
|
||||
* @param excludeInstalledLanguages - boolean whether to exclude languages that are already installed
|
||||
* @return List<Keyboard>
|
||||
*/
|
||||
private List<Keyboard> getKeyboards(JSONObject keyboardJSON, Keyboard baseKeyboard,
|
||||
boolean excludeInstalledLanguages ) {
|
||||
List<Keyboard> list = new ArrayList<Keyboard>();
|
||||
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 <Keyboard> based on kmp.json. If excludeInstalledLanguages is true, this list
|
||||
* excludes languages already installed
|
||||
*/
|
||||
public List<Keyboard> getKeyboardList(String packageID, String keyboardID, boolean excludeInstalledLanguages) {
|
||||
File packagePath = new File(resourceRoot, KMManager.KMDefault_AssetPackages + File.separator + packageID);
|
||||
List<Keyboard> list = new ArrayList<Keyboard>();
|
||||
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.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue