am 063b2e8d: Merge "Make LocaleUtils.constructLocaleFromString as @Nonnull"
* commit '063b2e8d7141641dff06093c807e75737a082818': Make LocaleUtils.constructLocaleFromString as @Nonnullmain
commit
c9952fa7d0
|
@ -104,7 +104,8 @@ public final class LocaleUtils {
|
||||||
* @param testedLocale the locale to test.
|
* @param testedLocale the locale to test.
|
||||||
* @return a constant that measures how well the tested locale matches the reference locale.
|
* @return a constant that measures how well the tested locale matches the reference locale.
|
||||||
*/
|
*/
|
||||||
public static int getMatchLevel(final String referenceLocale, final String testedLocale) {
|
public static int getMatchLevel(@Nullable final String referenceLocale,
|
||||||
|
@Nullable final String testedLocale) {
|
||||||
if (StringUtils.isEmpty(referenceLocale)) {
|
if (StringUtils.isEmpty(referenceLocale)) {
|
||||||
return StringUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
|
return StringUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
|
||||||
}
|
}
|
||||||
|
@ -167,11 +168,8 @@ public final class LocaleUtils {
|
||||||
* @param localeString a string specification of a locale, in a format of "ll_cc_variant" where
|
* @param localeString a string specification of a locale, in a format of "ll_cc_variant" where
|
||||||
* "ll" is a language code, "cc" is a country code.
|
* "ll" is a language code, "cc" is a country code.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nonnull
|
||||||
public static Locale constructLocaleFromString(@Nullable final String localeString) {
|
public static Locale constructLocaleFromString(@Nonnull final String localeString) {
|
||||||
if (localeString == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
synchronized (sLocaleCache) {
|
synchronized (sLocaleCache) {
|
||||||
if (sLocaleCache.containsKey(localeString)) {
|
if (sLocaleCache.containsKey(localeString)) {
|
||||||
return sLocaleCache.get(localeString);
|
return sLocaleCache.get(localeString);
|
||||||
|
|
|
@ -118,11 +118,7 @@ public final class SuggestionSpanUtils {
|
||||||
if (TextUtils.isEmpty(localeString)) {
|
if (TextUtils.isEmpty(localeString)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
|
return LocaleUtils.constructLocaleFromString(localeString);
|
||||||
if (locale == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return locale;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
|
@ -33,6 +34,8 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that handles background tasks for the dictionary provider.
|
* Service that handles background tasks for the dictionary provider.
|
||||||
*
|
*
|
||||||
|
@ -51,6 +54,8 @@ import java.util.concurrent.TimeUnit;
|
||||||
* to access, and mark the current state as such.
|
* to access, and mark the current state as such.
|
||||||
*/
|
*/
|
||||||
public final class DictionaryService extends Service {
|
public final class DictionaryService extends Service {
|
||||||
|
private static final String TAG = DictionaryService.class.getSimpleName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The package name, to use in the intent actions.
|
* The package name, to use in the intent actions.
|
||||||
*/
|
*/
|
||||||
|
@ -156,9 +161,14 @@ public final class DictionaryService extends Service {
|
||||||
final int startId) {
|
final int startId) {
|
||||||
final DictionaryService self = this;
|
final DictionaryService self = this;
|
||||||
if (SHOW_DOWNLOAD_TOAST_INTENT_ACTION.equals(intent.getAction())) {
|
if (SHOW_DOWNLOAD_TOAST_INTENT_ACTION.equals(intent.getAction())) {
|
||||||
// This is a UI action, it can't be run in another thread
|
final String localeString = intent.getStringExtra(LOCALE_INTENT_ARGUMENT);
|
||||||
showStartDownloadingToast(this, LocaleUtils.constructLocaleFromString(
|
if (localeString == null) {
|
||||||
intent.getStringExtra(LOCALE_INTENT_ARGUMENT)));
|
Log.e(TAG, "Received " + intent.getAction() + " without locale; skipped");
|
||||||
|
} else {
|
||||||
|
// This is a UI action, it can't be run in another thread
|
||||||
|
showStartDownloadingToast(
|
||||||
|
this, LocaleUtils.constructLocaleFromString(localeString));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If it's a command that does not require UI, arrange for the work to be done on a
|
// If it's a command that does not require UI, arrange for the work to be done on a
|
||||||
// separate thread, so that we can return right away. The executor will spawn a thread
|
// separate thread, so that we can return right away. The executor will spawn a thread
|
||||||
|
@ -245,7 +255,8 @@ public final class DictionaryService extends Service {
|
||||||
/**
|
/**
|
||||||
* Shows a toast informing the user that an automatic dictionary download is starting.
|
* Shows a toast informing the user that an automatic dictionary download is starting.
|
||||||
*/
|
*/
|
||||||
private static void showStartDownloadingToast(final Context context, final Locale locale) {
|
private static void showStartDownloadingToast(final Context context,
|
||||||
|
@Nonnull final Locale locale) {
|
||||||
final String toastText = String.format(
|
final String toastText = String.format(
|
||||||
context.getString(R.string.toast_downloading_suggestions),
|
context.getString(R.string.toast_downloading_suggestions),
|
||||||
locale.getDisplayName());
|
locale.getDisplayName());
|
||||||
|
|
|
@ -28,7 +28,7 @@ import com.android.inputmethod.annotations.ExternallyReferenced;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.common.LocaleUtils;
|
import com.android.inputmethod.latin.common.LocaleUtils;
|
||||||
|
|
||||||
import java.util.Locale;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implements the dialog for asking the user whether it's okay to download dictionaries over
|
* This implements the dialog for asking the user whether it's okay to download dictionaries over
|
||||||
|
@ -54,11 +54,11 @@ public final class DownloadOverMeteredDialog extends Activity {
|
||||||
setTexts(localeString, size);
|
setTexts(localeString, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTexts(final String localeString, final long size) {
|
private void setTexts(@Nullable final String localeString, final long size) {
|
||||||
final String promptFormat = getString(R.string.should_download_over_metered_prompt);
|
final String promptFormat = getString(R.string.should_download_over_metered_prompt);
|
||||||
final String allowButtonFormat = getString(R.string.download_over_metered);
|
final String allowButtonFormat = getString(R.string.download_over_metered);
|
||||||
final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
|
final String language = (null == localeString) ? ""
|
||||||
final String language = (null == locale ? "" : locale.getDisplayLanguage());
|
: LocaleUtils.constructLocaleFromString(localeString).getDisplayLanguage();
|
||||||
final TextView prompt = (TextView)findViewById(R.id.download_over_metered_prompt);
|
final TextView prompt = (TextView)findViewById(R.id.download_over_metered_prompt);
|
||||||
prompt.setText(Html.fromHtml(String.format(promptFormat, language)));
|
prompt.setText(Html.fromHtml(String.format(promptFormat, language)));
|
||||||
final Button allowButton = (Button)findViewById(R.id.allow_button);
|
final Button allowButton = (Button)findViewById(R.id.allow_button);
|
||||||
|
|
|
@ -57,7 +57,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@ -880,8 +879,8 @@ public final class UpdateHandler {
|
||||||
// None of those are expected to happen, but just in case...
|
// None of those are expected to happen, but just in case...
|
||||||
if (null == notificationIntent || null == notificationManager) return;
|
if (null == notificationIntent || null == notificationManager) return;
|
||||||
|
|
||||||
final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
|
final String language = (null == localeString) ? ""
|
||||||
final String language = (null == locale ? "" : locale.getDisplayLanguage());
|
: LocaleUtils.constructLocaleFromString(localeString).getDisplayLanguage();
|
||||||
final String titleFormat = context.getString(R.string.dict_available_notification_title);
|
final String titleFormat = context.getString(R.string.dict_available_notification_title);
|
||||||
final String notificationTitle = String.format(titleFormat, language);
|
final String notificationTitle = String.format(titleFormat, language);
|
||||||
final Notification.Builder builder = new Notification.Builder(context)
|
final Notification.Builder builder = new Notification.Builder(context)
|
||||||
|
|
|
@ -264,7 +264,7 @@ public class DictionaryFacilitator {
|
||||||
return mMostProbableDictionaryGroup;
|
return mMostProbableDictionaryGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void switchMostProbableLanguage(final Locale locale) {
|
public void switchMostProbableLanguage(@Nullable final Locale locale) {
|
||||||
if (null == locale) {
|
if (null == locale) {
|
||||||
// In many cases, there is no locale to a committed word. For example, a typed word
|
// In many cases, there is no locale to a committed word. For example, a typed word
|
||||||
// that is in none of the currently active dictionaries but still does not
|
// that is in none of the currently active dictionaries but still does not
|
||||||
|
|
|
@ -98,25 +98,23 @@ public final class DictionaryFactory {
|
||||||
}
|
}
|
||||||
final String wordlistId =
|
final String wordlistId =
|
||||||
DictionaryInfoUtils.getWordListIdFromFileName(new File(f.mFilename).getName());
|
DictionaryInfoUtils.getWordListIdFromFileName(new File(f.mFilename).getName());
|
||||||
if (null != wordlistId) {
|
// TODO: this is a reasonable last resort, but it is suboptimal.
|
||||||
// TODO: this is a reasonable last resort, but it is suboptimal.
|
// The following will remove the entry for this dictionary with the dictionary
|
||||||
// The following will remove the entry for this dictionary with the dictionary
|
// provider. When the metadata is downloaded again, we will try downloading it
|
||||||
// provider. When the metadata is downloaded again, we will try downloading it
|
// again.
|
||||||
// again.
|
// However, in the practice that will mean the user will find themselves without
|
||||||
// However, in the practice that will mean the user will find themselves without
|
// the new dictionary. That's fine for languages where it's included in the APK,
|
||||||
// the new dictionary. That's fine for languages where it's included in the APK,
|
// but for other languages it will leave the user without a dictionary at all until
|
||||||
// but for other languages it will leave the user without a dictionary at all until
|
// the next update, which may be a few days away.
|
||||||
// the next update, which may be a few days away.
|
// Ideally, we would trigger a new download right away, and use increasing retry
|
||||||
// Ideally, we would trigger a new download right away, and use increasing retry
|
// delays for this particular id/version combination.
|
||||||
// delays for this particular id/version combination.
|
// Then again, this is expected to only ever happen in case of human mistake. If
|
||||||
// Then again, this is expected to only ever happen in case of human mistake. If
|
// the wrong file is on the server, the following is still doing the right thing.
|
||||||
// the wrong file is on the server, the following is still doing the right thing.
|
// If it's a file left over from the last version however, it's not great.
|
||||||
// If it's a file left over from the last version however, it's not great.
|
BinaryDictionaryFileDumper.reportBrokenFileToDictionaryProvider(
|
||||||
BinaryDictionaryFileDumper.reportBrokenFileToDictionaryProvider(
|
providerClient,
|
||||||
providerClient,
|
context.getString(R.string.dictionary_pack_client_id),
|
||||||
context.getString(R.string.dictionary_pack_client_id),
|
wordlistId);
|
||||||
wordlistId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,12 +101,12 @@ public class ExternalDictionaryGetterForDebug {
|
||||||
final File file = new File(dirPath, fileName.toString());
|
final File file = new File(dirPath, fileName.toString());
|
||||||
final DictionaryHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file);
|
final DictionaryHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file);
|
||||||
final StringBuilder message = new StringBuilder();
|
final StringBuilder message = new StringBuilder();
|
||||||
final String locale = header.getLocaleString();
|
final String localeString = header.mLocaleString;
|
||||||
for (String key : header.mDictionaryOptions.mAttributes.keySet()) {
|
for (final String key : header.mDictionaryOptions.mAttributes.keySet()) {
|
||||||
message.append(key + " = " + header.mDictionaryOptions.mAttributes.get(key));
|
message.append(key + " = " + header.mDictionaryOptions.mAttributes.get(key));
|
||||||
message.append("\n");
|
message.append("\n");
|
||||||
}
|
}
|
||||||
final String languageName = LocaleUtils.constructLocaleFromString(locale)
|
final String languageName = LocaleUtils.constructLocaleFromString(localeString)
|
||||||
.getDisplayName(Locale.getDefault());
|
.getDisplayName(Locale.getDefault());
|
||||||
final String title = String.format(
|
final String title = String.format(
|
||||||
context.getString(R.string.read_external_dictionary_confirm_install_message),
|
context.getString(R.string.read_external_dictionary_confirm_install_message),
|
||||||
|
@ -146,11 +146,12 @@ public class ExternalDictionaryGetterForDebug {
|
||||||
BufferedOutputStream outputStream = null;
|
BufferedOutputStream outputStream = null;
|
||||||
File tempFile = null;
|
File tempFile = null;
|
||||||
try {
|
try {
|
||||||
final String locale = header.getLocaleString();
|
final String localeString = header.mLocaleString;
|
||||||
// Create the id for a main dictionary for this locale
|
// Create the id for a main dictionary for this locale
|
||||||
final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY
|
final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY
|
||||||
+ BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale;
|
+ BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + localeString;
|
||||||
final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context);
|
final String finalFileName = DictionaryInfoUtils.getCacheFileName(
|
||||||
|
id, localeString, context);
|
||||||
final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
|
final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
|
||||||
tempFile = new File(tempFileName);
|
tempFile = new File(tempFileName);
|
||||||
tempFile.delete();
|
tempFile.delete();
|
||||||
|
|
|
@ -19,13 +19,24 @@ package com.android.inputmethod.latin.makedict;
|
||||||
import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
|
import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
|
||||||
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
|
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing dictionary header.
|
* Class representing dictionary header.
|
||||||
*/
|
*/
|
||||||
public final class DictionaryHeader {
|
public final class DictionaryHeader {
|
||||||
public final int mBodyOffset;
|
public final int mBodyOffset;
|
||||||
|
@Nonnull
|
||||||
public final DictionaryOptions mDictionaryOptions;
|
public final DictionaryOptions mDictionaryOptions;
|
||||||
|
@Nonnull
|
||||||
public final FormatOptions mFormatOptions;
|
public final FormatOptions mFormatOptions;
|
||||||
|
@Nonnull
|
||||||
|
public final String mLocaleString;
|
||||||
|
@Nonnull
|
||||||
|
public final String mVersionString;
|
||||||
|
@Nonnull
|
||||||
|
public final String mIdString;
|
||||||
|
|
||||||
// Note that these are corresponding definitions in native code in latinime::HeaderPolicy
|
// Note that these are corresponding definitions in native code in latinime::HeaderPolicy
|
||||||
// and latinime::HeaderReadWriteUtils.
|
// and latinime::HeaderReadWriteUtils.
|
||||||
|
@ -46,39 +57,32 @@ public final class DictionaryHeader {
|
||||||
public static final String ATTRIBUTE_VALUE_TRUE = "1";
|
public static final String ATTRIBUTE_VALUE_TRUE = "1";
|
||||||
public static final String CODE_POINT_TABLE_KEY = "codePointTable";
|
public static final String CODE_POINT_TABLE_KEY = "codePointTable";
|
||||||
|
|
||||||
public DictionaryHeader(final int headerSize, final DictionaryOptions dictionaryOptions,
|
public DictionaryHeader(final int headerSize,
|
||||||
final FormatOptions formatOptions) throws UnsupportedFormatException {
|
@Nonnull final DictionaryOptions dictionaryOptions,
|
||||||
|
@Nonnull final FormatOptions formatOptions) throws UnsupportedFormatException {
|
||||||
mDictionaryOptions = dictionaryOptions;
|
mDictionaryOptions = dictionaryOptions;
|
||||||
mFormatOptions = formatOptions;
|
mFormatOptions = formatOptions;
|
||||||
mBodyOffset = formatOptions.mVersion < FormatSpec.VERSION4 ? headerSize : 0;
|
mBodyOffset = formatOptions.mVersion < FormatSpec.VERSION4 ? headerSize : 0;
|
||||||
if (null == getLocaleString()) {
|
final String localeString = dictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_KEY);
|
||||||
|
if (null == localeString) {
|
||||||
throw new UnsupportedFormatException("Cannot create a FileHeader without a locale");
|
throw new UnsupportedFormatException("Cannot create a FileHeader without a locale");
|
||||||
}
|
}
|
||||||
if (null == getVersion()) {
|
final String versionString = dictionaryOptions.mAttributes.get(DICTIONARY_VERSION_KEY);
|
||||||
|
if (null == versionString) {
|
||||||
throw new UnsupportedFormatException(
|
throw new UnsupportedFormatException(
|
||||||
"Cannot create a FileHeader without a version");
|
"Cannot create a FileHeader without a version");
|
||||||
}
|
}
|
||||||
if (null == getId()) {
|
final String idString = dictionaryOptions.mAttributes.get(DICTIONARY_ID_KEY);
|
||||||
|
if (null == idString) {
|
||||||
throw new UnsupportedFormatException("Cannot create a FileHeader without an ID");
|
throw new UnsupportedFormatException("Cannot create a FileHeader without an ID");
|
||||||
}
|
}
|
||||||
}
|
mLocaleString = localeString;
|
||||||
|
mVersionString = versionString;
|
||||||
// Helper method to get the locale as a String
|
mIdString = idString;
|
||||||
public String getLocaleString() {
|
|
||||||
return mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method to get the version String
|
|
||||||
public String getVersion() {
|
|
||||||
return mDictionaryOptions.mAttributes.get(DICTIONARY_VERSION_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method to get the dictionary ID as a String
|
|
||||||
public String getId() {
|
|
||||||
return mDictionaryOptions.mAttributes.get(DICTIONARY_ID_KEY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method to get the description
|
// Helper method to get the description
|
||||||
|
@Nullable
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
// TODO: Right now each dictionary file comes with a description in its own language.
|
// TODO: Right now each dictionary file comes with a description in its own language.
|
||||||
// It will display as is no matter the device's locale. It should be internationalized.
|
// It will display as is no matter the device's locale. It should be internationalized.
|
||||||
|
|
|
@ -115,7 +115,8 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
final String localeString = getLocale();
|
final String localeString = getLocale();
|
||||||
mLocale = LocaleUtils.constructLocaleFromString(localeString);
|
mLocale = (null == localeString) ? null
|
||||||
|
: LocaleUtils.constructLocaleFromString(localeString);
|
||||||
mScript = ScriptUtils.getScriptFromSpellCheckerLocale(mLocale);
|
mScript = ScriptUtils.getScriptFromSpellCheckerLocale(mLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
// Caveat: This class is basically taken from
|
// Caveat: This class is basically taken from
|
||||||
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
|
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
|
||||||
// in order to deal with some devices that have issues with the user dictionary handling
|
// in order to deal with some devices that have issues with the user dictionary handling
|
||||||
|
@ -218,8 +220,8 @@ public class UserDictionaryAddWordContents {
|
||||||
public static class LocaleRenderer {
|
public static class LocaleRenderer {
|
||||||
private final String mLocaleString;
|
private final String mLocaleString;
|
||||||
private final String mDescription;
|
private final String mDescription;
|
||||||
// LocaleString may NOT be null.
|
|
||||||
public LocaleRenderer(final Context context, final String localeString) {
|
public LocaleRenderer(final Context context, @Nullable final String localeString) {
|
||||||
mLocaleString = localeString;
|
mLocaleString = localeString;
|
||||||
if (null == localeString) {
|
if (null == localeString) {
|
||||||
mDescription = context.getString(R.string.user_dict_settings_more_languages);
|
mDescription = context.getString(R.string.user_dict_settings_more_languages);
|
||||||
|
|
|
@ -37,6 +37,8 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
// Caveat: This class is basically taken from
|
// Caveat: This class is basically taken from
|
||||||
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryList.java
|
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryList.java
|
||||||
// in order to deal with some devices that have issues with the user dictionary handling
|
// in order to deal with some devices that have issues with the user dictionary handling
|
||||||
|
@ -131,21 +133,23 @@ public class UserDictionaryList extends PreferenceFragment {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a single User Dictionary Preference object, with its parameters set.
|
* Create a single User Dictionary Preference object, with its parameters set.
|
||||||
* @param locale The locale for which this user dictionary is for.
|
* @param localeString The locale for which this user dictionary is for.
|
||||||
* @return The corresponding preference.
|
* @return The corresponding preference.
|
||||||
*/
|
*/
|
||||||
protected Preference createUserDictionaryPreference(final String locale) {
|
protected Preference createUserDictionaryPreference(@Nullable final String localeString) {
|
||||||
final Preference newPref = new Preference(getActivity());
|
final Preference newPref = new Preference(getActivity());
|
||||||
final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
|
final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
|
||||||
if (null == locale) {
|
if (null == localeString) {
|
||||||
newPref.setTitle(Locale.getDefault().getDisplayName());
|
newPref.setTitle(Locale.getDefault().getDisplayName());
|
||||||
} else {
|
} else {
|
||||||
if ("".equals(locale))
|
if (localeString.isEmpty()) {
|
||||||
newPref.setTitle(getString(R.string.user_dict_settings_all_languages));
|
newPref.setTitle(getString(R.string.user_dict_settings_all_languages));
|
||||||
else
|
} else {
|
||||||
newPref.setTitle(LocaleUtils.constructLocaleFromString(locale).getDisplayName());
|
newPref.setTitle(
|
||||||
intent.putExtra("locale", locale);
|
LocaleUtils.constructLocaleFromString(localeString).getDisplayName());
|
||||||
newPref.getExtras().putString("locale", locale);
|
}
|
||||||
|
intent.putExtra("locale", localeString);
|
||||||
|
newPref.getExtras().putString("locale", localeString);
|
||||||
}
|
}
|
||||||
newPref.setIntent(intent);
|
newPref.setIntent(intent);
|
||||||
newPref.setFragment(UserDictionarySettings.class.getName());
|
newPref.setFragment(UserDictionarySettings.class.getName());
|
||||||
|
|
|
@ -40,6 +40,9 @@ import java.util.Iterator;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class encapsulates the logic for the Latin-IME side of dictionary information management.
|
* This class encapsulates the logic for the Latin-IME side of dictionary information management.
|
||||||
*/
|
*/
|
||||||
|
@ -59,19 +62,26 @@ public class DictionaryInfoUtils {
|
||||||
private static final String DATE_COLUMN = "date";
|
private static final String DATE_COLUMN = "date";
|
||||||
private static final String FILESIZE_COLUMN = "filesize";
|
private static final String FILESIZE_COLUMN = "filesize";
|
||||||
private static final String VERSION_COLUMN = "version";
|
private static final String VERSION_COLUMN = "version";
|
||||||
|
@Nonnull
|
||||||
public final String mId;
|
public final String mId;
|
||||||
|
@Nonnull
|
||||||
public final Locale mLocale;
|
public final Locale mLocale;
|
||||||
|
@Nullable
|
||||||
public final String mDescription;
|
public final String mDescription;
|
||||||
|
@Nonnull
|
||||||
public final AssetFileAddress mFileAddress;
|
public final AssetFileAddress mFileAddress;
|
||||||
public final int mVersion;
|
public final int mVersion;
|
||||||
public DictionaryInfo(final String id, final Locale locale, final String description,
|
|
||||||
final AssetFileAddress fileAddress, final int version) {
|
public DictionaryInfo(@Nonnull final String id, @Nonnull final Locale locale,
|
||||||
|
@Nullable final String description, @Nonnull final AssetFileAddress fileAddress,
|
||||||
|
final int version) {
|
||||||
mId = id;
|
mId = id;
|
||||||
mLocale = locale;
|
mLocale = locale;
|
||||||
mDescription = description;
|
mDescription = description;
|
||||||
mFileAddress = fileAddress;
|
mFileAddress = fileAddress;
|
||||||
mVersion = version;
|
mVersion = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentValues toContentValues() {
|
public ContentValues toContentValues() {
|
||||||
final ContentValues values = new ContentValues();
|
final ContentValues values = new ContentValues();
|
||||||
values.put(WORDLISTID_COLUMN, mId);
|
values.put(WORDLISTID_COLUMN, mId);
|
||||||
|
@ -144,7 +154,8 @@ public class DictionaryInfoUtils {
|
||||||
/**
|
/**
|
||||||
* Reverse escaping done by replaceFileNameDangerousCharacters.
|
* Reverse escaping done by replaceFileNameDangerousCharacters.
|
||||||
*/
|
*/
|
||||||
public static String getWordListIdFromFileName(final String fname) {
|
@Nonnull
|
||||||
|
public static String getWordListIdFromFileName(@Nonnull final String fname) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
final int fnameLength = fname.length();
|
final int fnameLength = fname.length();
|
||||||
for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
|
for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
|
||||||
|
@ -176,12 +187,15 @@ public class DictionaryInfoUtils {
|
||||||
* {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
|
* {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
|
||||||
* @return The category as a string or null if it can't be found in the file name.
|
* @return The category as a string or null if it can't be found in the file name.
|
||||||
*/
|
*/
|
||||||
public static String getCategoryFromFileName(final String fileName) {
|
@Nullable
|
||||||
|
public static String getCategoryFromFileName(@Nonnull final String fileName) {
|
||||||
final String id = getWordListIdFromFileName(fileName);
|
final String id = getWordListIdFromFileName(fileName);
|
||||||
final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
|
final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
|
||||||
// An id is supposed to be in format category:locale, so splitting on the separator
|
// An id is supposed to be in format category:locale, so splitting on the separator
|
||||||
// should yield a 2-elements array
|
// should yield a 2-elements array
|
||||||
if (2 != idArray.length) return null;
|
if (2 != idArray.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return idArray[0];
|
return idArray[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +239,9 @@ public class DictionaryInfoUtils {
|
||||||
final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
|
final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
|
||||||
// An id is supposed to be in format category:locale, so splitting on the separator
|
// An id is supposed to be in format category:locale, so splitting on the separator
|
||||||
// should yield a 2-elements array
|
// should yield a 2-elements array
|
||||||
if (2 != idArray.length) return false;
|
if (2 != idArray.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
|
return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +293,9 @@ public class DictionaryInfoUtils {
|
||||||
*/
|
*/
|
||||||
public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
|
public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
|
||||||
int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
|
int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
|
||||||
if (0 != resourceId) return resourceId;
|
if (0 != resourceId) {
|
||||||
|
return resourceId;
|
||||||
|
}
|
||||||
return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
|
return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,10 +364,10 @@ public class DictionaryInfoUtils {
|
||||||
if (header == null) {
|
if (header == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final String id = header.getId();
|
final String id = header.mIdString;
|
||||||
final Locale locale = LocaleUtils.constructLocaleFromString(header.getLocaleString());
|
final Locale locale = LocaleUtils.constructLocaleFromString(header.mLocaleString);
|
||||||
final String description = header.getDescription();
|
final String description = header.getDescription();
|
||||||
final String version = header.getVersion();
|
final String version = header.mVersionString;
|
||||||
return new DictionaryInfo(id, locale, description, fileAddress, Integer.parseInt(version));
|
return new DictionaryInfo(id, locale, description, fileAddress, Integer.parseInt(version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,10 +395,13 @@ public class DictionaryInfoUtils {
|
||||||
if (null != directoryList) {
|
if (null != directoryList) {
|
||||||
for (final File directory : directoryList) {
|
for (final File directory : directoryList) {
|
||||||
final String localeString = getWordListIdFromFileName(directory.getName());
|
final String localeString = getWordListIdFromFileName(directory.getName());
|
||||||
File[] dicts = BinaryDictionaryGetter.getCachedWordLists(localeString, context);
|
final File[] dicts = BinaryDictionaryGetter.getCachedWordLists(
|
||||||
|
localeString, context);
|
||||||
for (final File dict : dicts) {
|
for (final File dict : dicts) {
|
||||||
final String wordListId = getWordListIdFromFileName(dict.getName());
|
final String wordListId = getWordListIdFromFileName(dict.getName());
|
||||||
if (!DictionaryInfoUtils.isMainWordListId(wordListId)) continue;
|
if (!DictionaryInfoUtils.isMainWordListId(wordListId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
|
final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
|
||||||
final AssetFileAddress fileAddress = AssetFileAddress.makeFromFile(dict);
|
final AssetFileAddress fileAddress = AssetFileAddress.makeFromFile(dict);
|
||||||
final DictionaryInfo dictionaryInfo =
|
final DictionaryInfo dictionaryInfo =
|
||||||
|
@ -388,7 +409,9 @@ public class DictionaryInfoUtils {
|
||||||
// Protect against cases of a less-specific dictionary being found, like an
|
// Protect against cases of a less-specific dictionary being found, like an
|
||||||
// en dictionary being used for an en_US locale. In this case, the en dictionary
|
// en dictionary being used for an en_US locale. In this case, the en dictionary
|
||||||
// should be used for en_US but discounted for listing purposes.
|
// should be used for en_US but discounted for listing purposes.
|
||||||
if (dictionaryInfo == null || !dictionaryInfo.mLocale.equals(locale)) continue;
|
if (dictionaryInfo == null || !dictionaryInfo.mLocale.equals(locale)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
addOrUpdateDictInfo(dictList, dictionaryInfo);
|
addOrUpdateDictInfo(dictList, dictionaryInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,14 +425,18 @@ public class DictionaryInfoUtils {
|
||||||
final int resourceId =
|
final int resourceId =
|
||||||
DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale(
|
DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale(
|
||||||
context.getResources(), locale);
|
context.getResources(), locale);
|
||||||
if (0 == resourceId) continue;
|
if (0 == resourceId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final AssetFileAddress fileAddress =
|
final AssetFileAddress fileAddress =
|
||||||
BinaryDictionaryGetter.loadFallbackResource(context, resourceId);
|
BinaryDictionaryGetter.loadFallbackResource(context, resourceId);
|
||||||
final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress);
|
final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress);
|
||||||
// Protect against cases of a less-specific dictionary being found, like an
|
// Protect against cases of a less-specific dictionary being found, like an
|
||||||
// en dictionary being used for an en_US locale. In this case, the en dictionary
|
// en dictionary being used for an en_US locale. In this case, the en dictionary
|
||||||
// should be used for en_US but discounted for listing purposes.
|
// should be used for en_US but discounted for listing purposes.
|
||||||
if (!dictionaryInfo.mLocale.equals(locale)) continue;
|
if (!dictionaryInfo.mLocale.equals(locale)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
addOrUpdateDictInfo(dictList, dictionaryInfo);
|
addOrUpdateDictInfo(dictList, dictionaryInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +446,9 @@ public class DictionaryInfoUtils {
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
public static boolean looksValidForDictionaryInsertion(final CharSequence text,
|
public static boolean looksValidForDictionaryInsertion(final CharSequence text,
|
||||||
final SpacingAndPunctuations spacingAndPunctuations) {
|
final SpacingAndPunctuations spacingAndPunctuations) {
|
||||||
if (TextUtils.isEmpty(text)) return false;
|
if (TextUtils.isEmpty(text)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
final int length = text.length();
|
final int length = text.length();
|
||||||
if (length > Constants.DICTIONARY_MAX_WORD_LENGTH) {
|
if (length > Constants.DICTIONARY_MAX_WORD_LENGTH) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -435,7 +464,9 @@ public class DictionaryInfoUtils {
|
||||||
digitCount += charCount;
|
digitCount += charCount;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!spacingAndPunctuations.isWordCodePoint(codePoint)) return false;
|
if (!spacingAndPunctuations.isWordCodePoint(codePoint)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// We reject strings entirely comprised of digits to avoid using PIN codes or credit
|
// We reject strings entirely comprised of digits to avoid using PIN codes or credit
|
||||||
// card numbers. It would come in handy for word prediction though; a good example is
|
// card numbers. It would come in handy for word prediction though; a good example is
|
||||||
|
|
|
@ -199,8 +199,7 @@ public final class SubtypeLocaleUtils {
|
||||||
if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
|
if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
|
||||||
languageString = localeString;
|
languageString = localeString;
|
||||||
} else {
|
} else {
|
||||||
final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
|
languageString = LocaleUtils.constructLocaleFromString(localeString).getLanguage();
|
||||||
languageString = locale.getLanguage();
|
|
||||||
}
|
}
|
||||||
return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale);
|
return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale);
|
||||||
}
|
}
|
||||||
|
@ -232,8 +231,8 @@ public final class SubtypeLocaleUtils {
|
||||||
};
|
};
|
||||||
displayName = getExceptionalName.runInLocale(sResources, displayLocale);
|
displayName = getExceptionalName.runInLocale(sResources, displayLocale);
|
||||||
} else {
|
} else {
|
||||||
final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
|
displayName = LocaleUtils.constructLocaleFromString(localeString)
|
||||||
displayName = locale.getDisplayName(displayLocale);
|
.getDisplayName(displayLocale);
|
||||||
}
|
}
|
||||||
return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale);
|
return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue