Merge "Add different ways of reading the dictionary file."
commit
0a7cf81ca2
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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 java.io.File;
|
||||
|
||||
/**
|
||||
* Immutable class to hold the address of an asset.
|
||||
* As opposed to a normal file, an asset is usually represented as a contiguous byte array in
|
||||
* the package file. Open it correctly thus requires the name of the package it is in, but
|
||||
* also the offset in the file and the length of this data. This class encapsulates these three.
|
||||
*/
|
||||
class AssetFileAddress {
|
||||
public final String mFilename;
|
||||
public final long mOffset;
|
||||
public final long mLength;
|
||||
|
||||
public AssetFileAddress(final String filename, final long offset, final long length) {
|
||||
mFilename = filename;
|
||||
mOffset = offset;
|
||||
mLength = length;
|
||||
}
|
||||
|
||||
public static AssetFileAddress makeFromFileName(final String filename) {
|
||||
if (null == filename) return null;
|
||||
File f = new File(filename);
|
||||
if (null == f || !f.isFile()) return null;
|
||||
return new AssetFileAddress(filename, 0l, f.length());
|
||||
}
|
||||
|
||||
public static AssetFileAddress makeFromFileNameAndOffset(final String filename,
|
||||
final long offset, final long length) {
|
||||
if (null == filename) return null;
|
||||
File f = new File(filename);
|
||||
if (null == f || !f.isFile()) return null;
|
||||
return new AssetFileAddress(filename, offset, length);
|
||||
}
|
||||
}
|
|
@ -26,14 +26,18 @@ import android.util.Log;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Implements a static, compacted, binary dictionary of standard words.
|
||||
*/
|
||||
public class BinaryDictionary extends Dictionary {
|
||||
|
||||
public static final String DICTIONARY_PACK_AUTHORITY =
|
||||
"com.android.inputmethod.latin.dictionarypack";
|
||||
|
||||
/**
|
||||
* There is difference between what java and native code can handle.
|
||||
* There is a difference between what java and native code can handle.
|
||||
* This value should only be used in BinaryDictionary.java
|
||||
* It is necessary to keep it at this value because some languages e.g. German have
|
||||
* really long words.
|
||||
|
@ -85,10 +89,11 @@ public class BinaryDictionary extends Dictionary {
|
|||
}
|
||||
|
||||
/**
|
||||
* Initialize a dictionary from a raw resource file
|
||||
* Initializes a dictionary from a raw resource file
|
||||
* @param context application context for reading resources
|
||||
* @param resId the resource containing the raw binary dictionary
|
||||
* @return initialized instance of BinaryDictionary
|
||||
* @param dicTypeId the type of the dictionary being created, out of the list in Suggest.DIC_*
|
||||
* @return an initialized instance of BinaryDictionary
|
||||
*/
|
||||
public static BinaryDictionary initDictionary(Context context, int resId, int dicTypeId) {
|
||||
synchronized (sInstance) {
|
||||
|
@ -146,6 +151,37 @@ public class BinaryDictionary extends Dictionary {
|
|||
Utils.loadNativeLibrary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a dictionary from a dictionary pack.
|
||||
*
|
||||
* This searches for a content provider providing a dictionary pack for the specified
|
||||
* locale. If none is found, it falls back to using the resource passed as fallBackResId
|
||||
* as a dictionary.
|
||||
* @param context application context for reading resources
|
||||
* @param dicTypeId the type of the dictionary being created, out of the list in Suggest.DIC_*
|
||||
* @param locale the locale for which to create the dictionary
|
||||
* @param fallBackResId the id of the resource to use as a fallback if no pack is found
|
||||
* @return an initialized instance of BinaryDictionary
|
||||
*/
|
||||
public static BinaryDictionary initDictionaryFromManager(Context context, int dicTypeId,
|
||||
Locale locale, int fallbackResId) {
|
||||
if (null == locale) {
|
||||
Log.e(TAG, "No locale defined for dictionary");
|
||||
return initDictionary(context, fallbackResId, dicTypeId);
|
||||
}
|
||||
synchronized (sInstance) {
|
||||
sInstance.closeInternal();
|
||||
|
||||
final AssetFileAddress dictFile = BinaryDictionaryGetter.getDictionaryFile(locale,
|
||||
context, fallbackResId);
|
||||
if (null != dictFile) {
|
||||
sInstance.loadDictionary(dictFile.mFilename, dictFile.mOffset, dictFile.mLength);
|
||||
sInstance.mDicTypeId = dicTypeId;
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private native int openNative(String sourceDir, long dictOffset, long dictSize,
|
||||
int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength,
|
||||
int maxWords, int maxAlternatives);
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Group class for static methods to help with creation and getting of the binary dictionary
|
||||
* file from the dictionary provider
|
||||
*/
|
||||
public class BinaryDictionaryFileDumper {
|
||||
/**
|
||||
* The size of the temporary buffer to copy files.
|
||||
*/
|
||||
static final int FILE_READ_BUFFER_SIZE = 1024;
|
||||
|
||||
// Prevents this class to be accidentally instantiated.
|
||||
private BinaryDictionaryFileDumper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a file name that matches the locale passed as an argument.
|
||||
* The file name is basically the result of the .toString() method, except we replace
|
||||
* any @File.separator with an underscore to avoid generating a file name that may not
|
||||
* be created.
|
||||
* @param locale the locale for which to get the file name
|
||||
* @param context the context to use for getting the directory
|
||||
* @return the name of the file to be created
|
||||
*/
|
||||
private static String getCacheFileNameForLocale(Locale locale, Context context) {
|
||||
// The following assumes two things :
|
||||
// 1. That File.separator is not the same character as "_"
|
||||
// I don't think any android system will ever use "_" as a path separator
|
||||
// 2. That no two locales differ by only a File.separator versus a "_"
|
||||
// Since "_" can't be part of locale components this should be safe.
|
||||
// Examples:
|
||||
// en -> en
|
||||
// en_US_POSIX -> en_US_POSIX
|
||||
// en__foo/bar -> en__foo_bar
|
||||
final String[] separator = { File.separator };
|
||||
final String[] empty = { "_" };
|
||||
final CharSequence basename = TextUtils.replace(locale.toString(), separator, empty);
|
||||
return context.getFilesDir() + File.separator + basename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return for a given locale the provider URI to query to get the dictionary.
|
||||
*/
|
||||
public static Uri getProviderUri(Locale locale) {
|
||||
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
|
||||
locale.toString()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries a content provider for dictionary data for some locale and returns it as a file name.
|
||||
*
|
||||
* This will query a content provider for dictionary data for a given locale, and return
|
||||
* the name of a file suitable to be mmap'ed. It will copy it to local storage if needed.
|
||||
* It should also check the dictionary version to avoid unnecessary copies but this is
|
||||
* still in TODO state.
|
||||
* This will make the data from the content provider the cached dictionary for this locale,
|
||||
* overwriting any previous cached data.
|
||||
* @returns the name of the file, or null if no data could be obtained.
|
||||
* @throw FileNotFoundException if the provider returns non-existent data.
|
||||
* @throw IOException if the provider-returned data could not be read.
|
||||
*/
|
||||
public static String getDictionaryFileFromContentProvider(Locale locale, Context context)
|
||||
throws FileNotFoundException, IOException {
|
||||
// TODO: check whether the dictionary is the same or not and if it is, return the cached
|
||||
// file.
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
final Uri dictionaryPackUri = getProviderUri(locale);
|
||||
final InputStream stream = resolver.openInputStream(dictionaryPackUri);
|
||||
if (null == stream) return null;
|
||||
return copyFileTo(stream, getCacheFileNameForLocale(locale, context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a file as dictionary data for some locale and returns the name of a file.
|
||||
*
|
||||
* This will make the data in the input file the cached dictionary for this locale, overwriting
|
||||
* any previous cached data.
|
||||
*/
|
||||
public static String getDictionaryFileFromFile(String fileName, Locale locale,
|
||||
Context context) throws FileNotFoundException, IOException {
|
||||
return copyFileTo(new FileInputStream(fileName), getCacheFileNameForLocale(locale,
|
||||
context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a resource number as dictionary data for some locale and returns the name of a file.
|
||||
*
|
||||
* This will make the resource the cached dictionary for this locale, overwriting any previous
|
||||
* cached data.
|
||||
*/
|
||||
public static String getDictionaryFileFromResource(int resource, Locale locale,
|
||||
Context context) throws FileNotFoundException, IOException {
|
||||
return copyFileTo(context.getResources().openRawResource(resource),
|
||||
getCacheFileNameForLocale(locale, context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the data in an input stream to a target file, creating the file if necessary and
|
||||
* overwriting it if it already exists.
|
||||
*/
|
||||
private static String copyFileTo(final InputStream input, final String outputFileName)
|
||||
throws FileNotFoundException, IOException {
|
||||
final byte[] buffer = new byte[FILE_READ_BUFFER_SIZE];
|
||||
final FileOutputStream output = new FileOutputStream(outputFileName);
|
||||
for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer))
|
||||
output.write(buffer, 0, readBytes);
|
||||
input.close();
|
||||
return outputFileName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.content.Context;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Helper class to get the address of a mmap'able dictionary file.
|
||||
*/
|
||||
class BinaryDictionaryGetter {
|
||||
|
||||
/**
|
||||
* Used for Log actions from this class
|
||||
*/
|
||||
private static final String TAG = BinaryDictionaryGetter.class.getSimpleName();
|
||||
|
||||
// Prevents this from being instantiated
|
||||
private BinaryDictionaryGetter() {}
|
||||
|
||||
/**
|
||||
* Returns a file address from a resource, or null if it cannot be opened.
|
||||
*/
|
||||
private static AssetFileAddress loadFallbackResource(Context context, int fallbackResId) {
|
||||
final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId);
|
||||
if (afd == null) {
|
||||
Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId="
|
||||
+ fallbackResId);
|
||||
return null;
|
||||
}
|
||||
return AssetFileAddress.makeFromFileNameAndOffset(
|
||||
context.getApplicationInfo().sourceDir, afd.getStartOffset(), afd.getLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a file address for a given locale, trying relevant methods in order.
|
||||
*
|
||||
* Tries to get a binary dictionary from various sources, in order:
|
||||
* - Uses a private method of getting a private dictionary, as implemented by the
|
||||
* PrivateBinaryDictionaryGetter class.
|
||||
* If that fails:
|
||||
* - Uses a content provider to get a public dictionary, as per the protocol described
|
||||
* in BinaryDictionaryFileDumper.
|
||||
* If that fails:
|
||||
* - Gets a file name from the fallback resource passed as an argument.
|
||||
* If that fails:
|
||||
* - Returns null.
|
||||
* @return The address of a valid file, or null.
|
||||
* @throws FileNotFoundException if a dictionary provider returned a file name, but the
|
||||
* file cannot be found.
|
||||
* @throws IOException if there was an I/O problem reading or copying a file.
|
||||
*/
|
||||
public static AssetFileAddress getDictionaryFile(Locale locale, Context context,
|
||||
int fallbackResId) {
|
||||
// Try first to query a private file signed the same way.
|
||||
final AssetFileAddress privateFile =
|
||||
PrivateBinaryDictionaryGetter.getDictionaryFile(locale, context);
|
||||
if (null != privateFile) {
|
||||
return privateFile;
|
||||
} else {
|
||||
try {
|
||||
// If that was no-go, try to find a publicly exported dictionary.
|
||||
final String fileName = BinaryDictionaryFileDumper.
|
||||
getDictionaryFileFromContentProvider(locale, context);
|
||||
return AssetFileAddress.makeFromFileName(fileName);
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e(TAG, "Unable to create dictionary file from provider for locale "
|
||||
+ locale.toString() + ": falling back to internal dictionary");
|
||||
return loadFallbackResource(context, fallbackResId);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to read source data for locale "
|
||||
+ locale.toString() + ": falling back to internal dictionary");
|
||||
return loadFallbackResource(context, fallbackResId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* Takes action to reload the necessary data when a dictionary pack was added/removed.
|
||||
*/
|
||||
public class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
final LatinIME mService;
|
||||
|
||||
public DictionaryPackInstallBroadcastReceiver(final LatinIME service) {
|
||||
mService = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
final PackageManager manager = context.getPackageManager();
|
||||
|
||||
// We need to reread the dictionary if a new dictionary package is installed.
|
||||
if (action.equals(Intent.ACTION_PACKAGE_ADDED)) {
|
||||
final Uri packageUri = intent.getData();
|
||||
if (null == packageUri) return; // No package name : we can't do anything
|
||||
final String packageName = packageUri.getSchemeSpecificPart();
|
||||
if (null == packageName) return;
|
||||
final PackageInfo packageInfo;
|
||||
try {
|
||||
packageInfo = manager.getPackageInfo(packageName, PackageManager.GET_PROVIDERS);
|
||||
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
|
||||
return; // No package info : we can't do anything
|
||||
}
|
||||
final ProviderInfo[] providers = packageInfo.providers;
|
||||
if (null == providers) return; // No providers : it is not a dictionary.
|
||||
|
||||
// Search for some dictionary pack in the just-installed package. If found, reread.
|
||||
boolean found = false;
|
||||
for (ProviderInfo info : providers) {
|
||||
if (BinaryDictionary.DICTIONARY_PACK_AUTHORITY.equals(info.authority)) {
|
||||
mService.resetSuggestMainDict();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If we come here none of the authorities matched the one we searched for.
|
||||
// We can exit safely.
|
||||
return;
|
||||
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
|
||||
&& !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
|
||||
// When the dictionary package is removed, we need to reread dictionary (to use the
|
||||
// next-priority one, or stop using a dictionary at all if this was the only one,
|
||||
// since this is the user request).
|
||||
// If we are replacing the package, we will receive ADDED right away so no need to
|
||||
// remove the dictionary at the moment, since we will do it when we receive the
|
||||
// ADDED broadcast.
|
||||
|
||||
// TODO: Only reload dictionary on REMOVED when the removed package is the one we
|
||||
// read dictionary from?
|
||||
mService.resetSuggestMainDict();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -106,8 +106,8 @@ public class InputLanguageSelection extends PreferenceActivity {
|
|||
conf.locale = locale;
|
||||
res.updateConfiguration(conf, res.getDisplayMetrics());
|
||||
|
||||
int mainDicResId = Utils.getMainDictionaryResourceId(res);
|
||||
BinaryDictionary bd = BinaryDictionary.initDictionary(this, mainDicResId, Suggest.DIC_MAIN);
|
||||
BinaryDictionary bd = BinaryDictionary.initDictionaryFromManager(this, Suggest.DIC_MAIN,
|
||||
locale, Utils.getMainDictionaryResourceId(res));
|
||||
|
||||
// Is the dictionary larger than a placeholder? Arbitrarily chose a lower limit of
|
||||
// 4000-5000 words, whereas the LARGE_DICTIONARY is about 20000+ words.
|
||||
|
|
|
@ -120,6 +120,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// Key events coming any faster than this are long-presses.
|
||||
private static final int QUICK_PRESS = 200;
|
||||
|
||||
/**
|
||||
* The name of the scheme used by the Package Manager to warn of a new package installation,
|
||||
* replacement or removal.
|
||||
*/
|
||||
private static final String SCHEME_PACKAGE = "package";
|
||||
|
||||
private int mSuggestionVisibility;
|
||||
private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE
|
||||
= R.string.prefs_suggestion_visibility_show_value;
|
||||
|
@ -208,6 +214,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// TODO: Move this flag to VoiceIMEConnector
|
||||
private boolean mConfigurationChanging;
|
||||
|
||||
// Object for reacting to adding/removing a dictionary pack.
|
||||
private BroadcastReceiver mDictionaryPackInstallReceiver =
|
||||
new DictionaryPackInstallBroadcastReceiver(this);
|
||||
|
||||
// Keeps track of most recently inserted text (multi-character key) for reverting
|
||||
private CharSequence mEnteredText;
|
||||
|
||||
|
@ -415,18 +425,26 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mOrientation = res.getConfiguration().orientation;
|
||||
initSuggestPuncList();
|
||||
|
||||
// register to receive ringer mode change and network state change.
|
||||
// Register to receive ringer mode change and network state change.
|
||||
// Also receive installation and removal of a dictionary pack.
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
registerReceiver(mReceiver, filter);
|
||||
mVoiceConnector = VoiceConnector.init(this, prefs, mHandler);
|
||||
|
||||
final IntentFilter packageFilter = new IntentFilter();
|
||||
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
packageFilter.addDataScheme(SCHEME_PACKAGE);
|
||||
registerReceiver(mDictionaryPackInstallReceiver, packageFilter);
|
||||
}
|
||||
|
||||
private void initSuggest() {
|
||||
String locale = mSubtypeSwitcher.getInputLocaleStr();
|
||||
final String localeStr = mSubtypeSwitcher.getInputLocaleStr();
|
||||
final Locale keyboardLocale = new Locale(localeStr);
|
||||
|
||||
Locale savedLocale = mSubtypeSwitcher.changeSystemLocale(new Locale(locale));
|
||||
final Locale savedLocale = mSubtypeSwitcher.changeSystemLocale(keyboardLocale);
|
||||
if (mSuggest != null) {
|
||||
mSuggest.close();
|
||||
}
|
||||
|
@ -435,20 +453,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
final Resources res = mResources;
|
||||
int mainDicResId = Utils.getMainDictionaryResourceId(res);
|
||||
mSuggest = new Suggest(this, mainDicResId);
|
||||
mSuggest = new Suggest(this, mainDicResId, keyboardLocale);
|
||||
loadAndSetAutoCorrectionThreshold(prefs);
|
||||
updateAutoTextEnabled();
|
||||
|
||||
mUserDictionary = new UserDictionary(this, locale);
|
||||
mUserDictionary = new UserDictionary(this, localeStr);
|
||||
mSuggest.setUserDictionary(mUserDictionary);
|
||||
|
||||
mContactsDictionary = new ContactsDictionary(this, Suggest.DIC_CONTACTS);
|
||||
mSuggest.setContactsDictionary(mContactsDictionary);
|
||||
|
||||
mAutoDictionary = new AutoDictionary(this, this, locale, Suggest.DIC_AUTO);
|
||||
mAutoDictionary = new AutoDictionary(this, this, localeStr, Suggest.DIC_AUTO);
|
||||
mSuggest.setAutoDictionary(mAutoDictionary);
|
||||
|
||||
mUserBigramDictionary = new UserBigramDictionary(this, this, locale, Suggest.DIC_USER);
|
||||
mUserBigramDictionary = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER);
|
||||
mSuggest.setUserBigramDictionary(mUserBigramDictionary);
|
||||
|
||||
updateCorrectionMode();
|
||||
|
@ -458,6 +476,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mSubtypeSwitcher.changeSystemLocale(savedLocale);
|
||||
}
|
||||
|
||||
/* package private */ void resetSuggestMainDict() {
|
||||
final String localeStr = mSubtypeSwitcher.getInputLocaleStr();
|
||||
final Locale keyboardLocale = new Locale(localeStr);
|
||||
int mainDicResId = Utils.getMainDictionaryResourceId(mResources);
|
||||
mSuggest.resetMainDict(this, mainDicResId, keyboardLocale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mSuggest != null) {
|
||||
|
@ -465,6 +490,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mSuggest = null;
|
||||
}
|
||||
unregisterReceiver(mReceiver);
|
||||
unregisterReceiver(mDictionaryPackInstallReceiver);
|
||||
mVoiceConnector.destroy();
|
||||
LatinImeLogger.commit();
|
||||
LatinImeLogger.onDestroy();
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.content.Context;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
class PrivateBinaryDictionaryGetter {
|
||||
private PrivateBinaryDictionaryGetter() {}
|
||||
public static AssetFileAddress getDictionaryFile(Locale locale, Context context) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -106,8 +107,9 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
|
||||
private int mCorrectionMode = CORRECTION_BASIC;
|
||||
|
||||
public Suggest(Context context, int dictionaryResId) {
|
||||
init(context, BinaryDictionary.initDictionary(context, dictionaryResId, DIC_MAIN));
|
||||
public Suggest(Context context, int dictionaryResId, Locale locale) {
|
||||
init(context, BinaryDictionary.initDictionaryFromManager(context, DIC_MAIN, locale,
|
||||
dictionaryResId));
|
||||
}
|
||||
|
||||
/* package for test */ Suggest(File dictionary, long startOffset, long length,
|
||||
|
@ -130,6 +132,19 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
initPool();
|
||||
}
|
||||
|
||||
public void resetMainDict(Context context, int dictionaryResId, Locale locale) {
|
||||
final BinaryDictionary newMainDict = BinaryDictionary.initDictionaryFromManager(context,
|
||||
DIC_MAIN, locale, dictionaryResId);
|
||||
mMainDict = newMainDict;
|
||||
if (null == newMainDict) {
|
||||
mUnigramDictionaries.remove(DICT_KEY_MAIN);
|
||||
mBigramDictionaries.remove(DICT_KEY_MAIN);
|
||||
} else {
|
||||
mUnigramDictionaries.put(DICT_KEY_MAIN, newMainDict);
|
||||
mBigramDictionaries.put(DICT_KEY_MAIN, newMainDict);
|
||||
}
|
||||
}
|
||||
|
||||
private void initPool() {
|
||||
for (int i = 0; i < mPrefMaxSuggestions; i++) {
|
||||
StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
|
||||
|
|
|
@ -551,7 +551,9 @@ public class Utils {
|
|||
* @return main dictionary resource id
|
||||
*/
|
||||
public static int getMainDictionaryResourceId(Resources res) {
|
||||
return res.getIdentifier("main", "raw", LatinIME.class.getPackage().getName());
|
||||
final String MAIN_DIC_NAME = "main";
|
||||
String packageName = LatinIME.class.getPackage().getName();
|
||||
return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName);
|
||||
}
|
||||
|
||||
public static void loadNativeLibrary() {
|
||||
|
|
|
@ -34,7 +34,9 @@ public class SuggestHelper {
|
|||
private final KeyDetector mKeyDetector;
|
||||
|
||||
public SuggestHelper(Context context, int dictionaryId, KeyboardId keyboardId) {
|
||||
mSuggest = new Suggest(context, dictionaryId);
|
||||
// Use null as the locale for Suggest so as to force it to use the internal dictionary
|
||||
// (and not try to find a dictionary provider for a specified locale)
|
||||
mSuggest = new Suggest(context, dictionaryId, null);
|
||||
mKeyboard = new LatinKeyboard(context, keyboardId);
|
||||
mKeyDetector = new ProximityKeyDetector();
|
||||
init();
|
||||
|
|
Loading…
Reference in New Issue