diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java index ccf851b0fa..676ab7bbd0 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java @@ -2,6 +2,7 @@ package com.tavultesoft.kmapro; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.view.inputmethod.InputMethodManager; @@ -19,7 +20,7 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { private static final String TAG = "SettingsFragment"; private static Context context; - private Preference languagesPreference; + private Preference languagesPreference, addKeyboardFromDevice; private CheckBoxPreference setSystemKeyboardPreference; private CheckBoxPreference setDefaultKeyboardPreference; @@ -40,6 +41,24 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { languagesIntent.putExtra(KMManager.KMKey_DisplayKeyboardSwitcher, false); languagesPreference.setIntent(languagesIntent); + // Launch System file browser for user to navigate to local .kmp files + // Using generic "Add keyboard" title even though this can also install lexical model .kmp's. + addKeyboardFromDevice = new Preference(context); + addKeyboardFromDevice.setTitle(getString(R.string.title_add_keyboard_from_device)); + addKeyboardFromDevice.setWidgetLayoutResource(R.layout.preference_file_browser_layout); + addKeyboardFromDevice.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.putExtra("android.content.extra.SHOW_ADVANCED", false); + // Unfortunately, we can't filter for a "kmp" mime type + intent.setType("*/*"); + startActivityForResult(intent, MainActivity.READ_REQUEST_CODE); + return false; + } + }); + /* Automatically does the following: SharedPreferences.Editor editor = prefs.edit(); @@ -92,6 +111,8 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { setDefaultKeyboardPreference.setOnPreferenceChangeListener(checkBlocker); screen.addPreference(languagesPreference); + screen.addPreference(addKeyboardFromDevice); + screen.addPreference(setSystemKeyboardPreference); screen.addPreference(setDefaultKeyboardPreference); @@ -132,6 +153,16 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { // .update() on our behalf. } + + public void onActivityResult(int requestCode, int resultCode, Intent returnIntent) { + // Handle kmp file selected from file browser + if ((requestCode == MainActivity.READ_REQUEST_CODE) && (returnIntent != null)) { + String kmpFilename = returnIntent.getDataString(); + Uri data = Uri.parse(kmpFilename); + MainActivity.useLocalKMP(this.getContext(), data); + } + } + public void update() { setSystemKeyboardPreference.setChecked(SystemIMESettings.isEnabledAsSystemKB(context)); setDefaultKeyboardPreference.setChecked(SystemIMESettings.isDefaultKB(context)); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index d5219d4868..4e1f6bd466 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -75,10 +75,12 @@ import android.widget.SeekBar; import android.widget.Toast; public class MainActivity extends AppCompatActivity implements OnKeyboardEventListener, OnKeyboardDownloadEventListener, - ActivityCompat.OnRequestPermissionsResultCallback { + ActivityCompat.OnRequestPermissionsResultCallback { + public static Context context; // Fields used for installing kmp packages private static final int PERMISSION_REQUEST_STORAGE = 0; + public static final int READ_REQUEST_CODE = 42; Uri data; private static final String TAG = "MainActivity"; @@ -132,6 +134,7 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi protected void onCreate(Bundle savedInstanceState) { setTheme(R.style.AppTheme); super.onCreate(savedInstanceState); + context = this; resultReceiver = new DownloadResultReceiver(new Handler()); mFirebaseAnalytics = FirebaseAnalytics.getInstance(this); @@ -619,7 +622,7 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi // Request for storage permission if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission has been granted. Resume task needing this permission - useLocalKMP(data); + useLocalKMP(context, data); } else { // Permission request denied String message = "Storage permission request was denied. Unable to install keyboard package"; @@ -634,14 +637,14 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - useLocalKMP(data); + useLocalKMP(context, data); } else { // Permission is missing and must be requested requestStoragePermission(); } } else { // Permission automatically granted on older Android versions - useLocalKMP(data); + useLocalKMP(context, data); } } @@ -664,7 +667,8 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi } } - private void useLocalKMP(Uri data) { + // TODO: Move this to KMEA during Keyman 13.0 refactoring + public static void useLocalKMP(Context context, Uri data) { String filename = ""; String cacheKMPFilename = ""; File cacheKMPFile = null; @@ -675,13 +679,13 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi switch (data.getScheme().toLowerCase()) { case "content": // DownloadManager passes a path "/document/number" so we need to extract the .kmp filename - Cursor cursor = getContentResolver().query(data, null, null, null, null); + Cursor cursor = context.getContentResolver().query(data, null, null, null, null); cursor.moveToFirst(); int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); filename = cursor.getString(nameIndex); isKMP = FileUtils.hasKeymanPackageExtension(filename); cacheKMPFilename = filename; - inputFile = getContentResolver().openInputStream(data); + inputFile = context.getContentResolver().openInputStream(data); break; case "file": @@ -695,21 +699,22 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi if (isKMP) { // Copy KMP to app cache - cacheKMPFile = new File(MainActivity.this.getCacheDir().toString(), cacheKMPFilename); + cacheKMPFile = new File(context.getCacheDir().toString(), cacheKMPFilename); if (cacheKMPFile.exists()) { cacheKMPFile.delete(); } FileUtils.copy(inputFile, new FileOutputStream(cacheKMPFile)); } else { - String noKeyboardsInstalledMessage = " is not a valid keyboard package file.\nNo keyboards were installed."; - Toast.makeText(getApplicationContext(), + String noKeyboardsInstalledMessage = " is not a valid Keyman package file.\n" + + "No keyboards/dictionaries were installed."; + Toast.makeText(context, filename + noKeyboardsInstalledMessage, Toast.LENGTH_LONG).show(); } } catch (Exception e) { String message = "Access denied to " + filename + ".\nCheck Android Settings --> Apps --> Keyman to grant storage permissions"; - Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); + Toast.makeText(context, message, Toast.LENGTH_LONG).show(); Log.e(TAG, "Unable to copy " + filename + " to app cache"); return; } @@ -717,9 +722,9 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi if (cacheKMPFile != null) { bundle.putString("kmpFile", cacheKMPFile.getAbsolutePath()); - Intent packageIntent = new Intent(getApplicationContext(), PackageActivity.class); + Intent packageIntent = new Intent(context, PackageActivity.class); packageIntent.putExtras(bundle); - startActivity(packageIntent); + context.startActivity(packageIntent); } } diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/ic_folder_open.png b/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/ic_folder_open.png new file mode 100644 index 0000000000..4f90c63104 Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/ic_folder_open.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/ic_folder_open.png b/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/ic_folder_open.png new file mode 100644 index 0000000000..4f90c63104 Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/ic_folder_open.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/ic_folder_open.png b/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/ic_folder_open.png new file mode 100644 index 0000000000..f55b92e9ba Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/ic_folder_open.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/ic_folder_open.png b/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/ic_folder_open.png new file mode 100644 index 0000000000..1eb3365e09 Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/ic_folder_open.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/ic_folder_open.png b/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/ic_folder_open.png new file mode 100644 index 0000000000..e6faa991f4 Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/ic_folder_open.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/layout/preference_file_browser_layout.xml b/android/KMAPro/kMAPro/src/main/res/layout/preference_file_browser_layout.xml new file mode 100644 index 0000000000..9483748278 --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/res/layout/preference_file_browser_layout.xml @@ -0,0 +1,5 @@ + + diff --git a/android/KMAPro/kMAPro/src/main/res/menu-land/main.xml b/android/KMAPro/kMAPro/src/main/res/menu-land/main.xml index 892a1f24ec..6cb3ec10a3 100644 --- a/android/KMAPro/kMAPro/src/main/res/menu-land/main.xml +++ b/android/KMAPro/kMAPro/src/main/res/menu-land/main.xml @@ -14,7 +14,7 @@ app:showAsAction="always" android:title="@string/action_web" android:icon="@drawable/ic_light_action_web" /> - + - + Share Web Browser + File Browser Text Size More Clear Text diff --git a/android/KMEA/app/src/main/res/values/strings.xml b/android/KMEA/app/src/main/res/values/strings.xml index 698fc4c9f7..4756b8bd9c 100644 --- a/android/KMEA/app/src/main/res/values/strings.xml +++ b/android/KMEA/app/src/main/res/values/strings.xml @@ -12,6 +12,7 @@ Keyboard Add New Language Add New Keyboard + Add Keyboard from Device Installed Languages %s Settings diff --git a/android/history.md b/android/history.md index 44dd6ff0ac..3bfd484b14 100644 --- a/android/history.md +++ b/android/history.md @@ -3,6 +3,10 @@ ## 13.0 alpha * Start version 13.0 +## 2019-08-30 12.0.4081 beta +* New Feature: + * Allow user to "Add keyboard from local device" from Settings menu (#1992) + ## 2019-08-27 12.0.4080 beta * Fix menu icon and text alignment (#1999)