diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
7 files changed, 206 insertions, 23 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 5eab292fc..d725b9f14 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -25,6 +25,7 @@ import android.text.TextUtils; import android.util.Log; import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -162,9 +163,9 @@ public final class BinaryDictionaryFileDumper { InputStream inputStream = null; InputStream uncompressedStream = null; InputStream decryptedStream = null; - BufferedInputStream bufferedStream = null; + BufferedInputStream bufferedInputStream = null; File outputFile = null; - FileOutputStream outputStream = null; + BufferedOutputStream bufferedOutputStream = null; AssetFileDescriptor afd = null; final Uri wordListUri = wordListUriBuilder.build(); try { @@ -178,7 +179,6 @@ public final class BinaryDictionaryFileDumper { // Just to be sure, delete the file. This may fail silently, and return false: this // is the right thing to do, as we just want to continue anyway. outputFile.delete(); - outputStream = new FileOutputStream(outputFile); // Get the appropriate decryption method for this try switch (mode) { case COMPRESSED_CRYPTED_COMPRESSED: @@ -206,10 +206,11 @@ public final class BinaryDictionaryFileDumper { inputStream = originalSourceStream; break; } - bufferedStream = new BufferedInputStream(inputStream); - checkMagicAndCopyFileTo(bufferedStream, outputStream); - outputStream.flush(); - outputStream.close(); + bufferedInputStream = new BufferedInputStream(inputStream); + bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(outputFile)); + checkMagicAndCopyFileTo(bufferedInputStream, bufferedOutputStream); + bufferedOutputStream.flush(); + bufferedOutputStream.close(); final File finalFile = new File(finalFileName); finalFile.delete(); if (!outputFile.renameTo(finalFile)) { @@ -241,12 +242,12 @@ public final class BinaryDictionaryFileDumper { if (null != inputStream) inputStream.close(); if (null != uncompressedStream) uncompressedStream.close(); if (null != decryptedStream) decryptedStream.close(); - if (null != bufferedStream) bufferedStream.close(); + if (null != bufferedInputStream) bufferedInputStream.close(); } catch (Exception e) { Log.e(TAG, "Exception while closing a file descriptor : " + e); } try { - if (null != outputStream) outputStream.close(); + if (null != bufferedOutputStream) bufferedOutputStream.close(); } catch (Exception e) { Log.e(TAG, "Exception while closing a file : " + e); } @@ -301,9 +302,8 @@ public final class BinaryDictionaryFileDumper { * @param input the stream to be copied. * @param output an output stream to copy the data to. */ - // TODO: make output a BufferedOutputStream - private static void checkMagicAndCopyFileTo(final BufferedInputStream input, - final FileOutputStream output) throws FileNotFoundException, IOException { + public static void checkMagicAndCopyFileTo(final BufferedInputStream input, + final BufferedOutputStream output) throws FileNotFoundException, IOException { // Check the magic number final int length = MAGIC_NUMBER_VERSION_2.length; final byte[] magicNumberBuffer = new byte[length]; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 83dabbede..ecb63e890 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -56,7 +56,7 @@ final class BinaryDictionaryGetter { private static final String COMMON_PREFERENCES_NAME = "LatinImeDictPrefs"; // Name of the category for the main dictionary - private static final String MAIN_DICTIONARY_CATEGORY = "main"; + public static final String MAIN_DICTIONARY_CATEGORY = "main"; public static final String ID_CATEGORY_SEPARATOR = ":"; // The key considered to read the version attribute in a dictionary file. diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java index 94680718d..ad52adfa0 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/DebugSettings.java @@ -75,7 +75,9 @@ public final class DebugSettings extends PreferenceFragment new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(final Preference arg0) { - // TODO: actually read the dictionary + ExternalDictionaryGetterForDebug.chooseAndInstallDictionary( + getActivity()); + mServiceNeedsRestart = true; return true; } }); diff --git a/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java new file mode 100644 index 000000000..03e87636e --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.latin; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.os.Environment; +import android.util.Log; + +import com.android.inputmethod.latin.makedict.BinaryDictIOUtils; +import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader; +import com.android.inputmethod.latin.makedict.UnsupportedFormatException; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Locale; + +/** + * A class to read a local file as a dictionary for debugging purposes. + */ +public class ExternalDictionaryGetterForDebug { + private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath() + + "/Download"; + private static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale"; + + private static FileHeader getDictionaryFileHeaderOrNull(final File file) { + try { + final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeader(file); + return header; + } catch (UnsupportedFormatException e) { + return null; + } catch (IOException e) { + return null; + } + } + + private static String[] findDictionariesInTheDownloadedFolder() { + final File[] files = new File(SOURCE_FOLDER).listFiles(); + final ArrayList<String> eligibleList = CollectionUtils.newArrayList(); + for (File f : files) { + final FileHeader header = getDictionaryFileHeaderOrNull(f); + if (null == header) continue; + eligibleList.add(f.getName()); + } + return eligibleList.toArray(new String[0]); + } + + public static void chooseAndInstallDictionary(final Context context) { + final String[] fileNames = findDictionariesInTheDownloadedFolder(); + if (0 == fileNames.length) { + showNoFileDialog(context); + } else if (1 == fileNames.length) { + askInstallFile(context, fileNames[0]); + } else { + showChooseFileDialog(context, fileNames); + } + } + + private static void showNoFileDialog(final Context context) { + new AlertDialog.Builder(context) + .setMessage(R.string.read_external_dictionary_no_files_message) + .setPositiveButton(android.R.string.ok, new OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int which) { + dialog.dismiss(); + } + }).create().show(); + } + + private static void showChooseFileDialog(final Context context, final String[] fileNames) { + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.read_external_dictionary_multiple_files_title) + .setItems(fileNames, new OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int which) { + askInstallFile(context, fileNames[which]); + } + }) + .create().show(); + } + + private static void askInstallFile(final Context context, final String fileName) { + final File file = new File(SOURCE_FOLDER, fileName.toString()); + final FileHeader header = getDictionaryFileHeaderOrNull(file); + final StringBuilder message = new StringBuilder(); + final String locale = + header.mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_ATTRIBUTE); + for (String key : header.mDictionaryOptions.mAttributes.keySet()) { + message.append(key + " = " + header.mDictionaryOptions.mAttributes.get(key)); + message.append("\n"); + } + final String languageName = LocaleUtils.constructLocaleFromString(locale) + .getDisplayName(Locale.getDefault()); + final String title = String.format( + context.getString(R.string.read_external_dictionary_confirm_install_message), + languageName); + new AlertDialog.Builder(context) + .setTitle(title) + .setMessage(message) + .setNegativeButton(android.R.string.cancel, new OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int which) { + dialog.dismiss(); + } + }).setPositiveButton(android.R.string.ok, new OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int which) { + installFile(context, file, header); + dialog.dismiss(); + } + }).create().show(); + } + + private static void installFile(final Context context, final File file, + final FileHeader header) { + BufferedOutputStream outputStream = null; + File tempFile = null; + try { + final String locale = + header.mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_ATTRIBUTE); + // Create the id for a main dictionary for this locale + final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY + + BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale; + final String finalFileName = + BinaryDictionaryGetter.getCacheFileName(id, locale, context); + final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); + tempFile = new File(tempFileName); + tempFile.delete(); + outputStream = new BufferedOutputStream(new FileOutputStream(tempFile)); + final BufferedInputStream bufferedStream = new BufferedInputStream( + new FileInputStream(file)); + BinaryDictionaryFileDumper.checkMagicAndCopyFileTo(bufferedStream, outputStream); + outputStream.flush(); + final File finalFile = new File(finalFileName); + finalFile.delete(); + if (!tempFile.renameTo(finalFile)) { + throw new IOException("Can't move the file to its final name"); + } + } catch (IOException e) { + // There was an error: show a dialog + new AlertDialog.Builder(context) + .setTitle(R.string.error) + .setMessage(e.toString()) + .setPositiveButton(android.R.string.ok, new OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int which) { + dialog.dismiss(); + } + }).create().show(); + return; + } finally { + try { + if (null != outputStream) outputStream.close(); + if (null != tempFile) tempFile.delete(); + } catch (IOException e) { + // Don't do anything + } + } + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d9e63da1b..75bf3f29e 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1617,7 +1617,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, final boolean dismissGestureFloatingPreviewText) { showSuggestionStrip(suggestedWords, null); - final KeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); + final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); mainKeyboardView.showGestureFloatingPreviewText(suggestedWords); if (dismissGestureFloatingPreviewText) { mainKeyboardView.dismissGestureFloatingPreviewText(); diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 705f66414..d55fe1c52 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -252,7 +252,7 @@ public final class FormatSpec { /** * Class representing file header. */ - static final class FileHeader { + public static final class FileHeader { public final int mHeaderSize; public final DictionaryOptions mDictionaryOptions; public final FormatOptions mFormatOptions; diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 14bb95b3c..5b440c368 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -52,7 +52,7 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.keyboard.KeyboardView; +import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.keyboard.MoreKeysPanel; import com.android.inputmethod.keyboard.ViewLayoutUtils; import com.android.inputmethod.latin.AutoCorrection; @@ -81,7 +81,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick static final boolean DBG = LatinImeLogger.sDBG; private final ViewGroup mSuggestionsStrip; - KeyboardView mKeyboardView; + MainKeyboardView mMainKeyboardView; private final View mMoreSuggestionsContainer; private final MoreSuggestionsView mMoreSuggestionsView; @@ -610,7 +610,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick */ public void setListener(final Listener listener, final View inputView) { mListener = listener; - mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view); + mMainKeyboardView = (MainKeyboardView)inputView.findViewById(R.id.keyboard_view); } public void setSuggestions(final SuggestedWords suggestedWords) { @@ -676,13 +676,13 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick new MoreKeysPanel.Controller() { @Override public boolean onDismissMoreKeysPanel() { - mKeyboardView.dimEntireKeyboard(false /* dimmed */); - return mKeyboardView.onDismissMoreKeysPanel(); + mMainKeyboardView.dimEntireKeyboard(false /* dimmed */); + return mMainKeyboardView.onDismissMoreKeysPanel(); } @Override public void onShowMoreKeysPanel(MoreKeysPanel panel) { - mKeyboardView.onShowMoreKeysPanel(panel); + mMainKeyboardView.onShowMoreKeysPanel(panel); } @Override @@ -728,7 +728,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING; mOriginX = mLastX; mOriginY = mLastY; - mKeyboardView.dimEntireKeyboard(true /* dimmed */); + mMainKeyboardView.dimEntireKeyboard(true /* dimmed */); for (int i = 0; i < params.mSuggestionsCountInStrip; i++) { mWords.get(i).setPressed(false); } |