Merge "Change the dictionary file passing schema to a list of ids"
This commit is contained in:
commit
81f227de5a
2 changed files with 72 additions and 37 deletions
|
@ -20,8 +20,10 @@ import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.AssetFileDescriptor;
|
import android.content.res.AssetFileDescriptor;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -29,7 +31,8 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@ -43,6 +46,8 @@ public class BinaryDictionaryFileDumper {
|
||||||
*/
|
*/
|
||||||
static final int FILE_READ_BUFFER_SIZE = 1024;
|
static final int FILE_READ_BUFFER_SIZE = 1024;
|
||||||
|
|
||||||
|
private static final String DICTIONARY_PROJECTION[] = { "id" };
|
||||||
|
|
||||||
// Prevents this class to be accidentally instantiated.
|
// Prevents this class to be accidentally instantiated.
|
||||||
private BinaryDictionaryFileDumper() {
|
private BinaryDictionaryFileDumper() {
|
||||||
}
|
}
|
||||||
|
@ -75,12 +80,47 @@ public class BinaryDictionaryFileDumper {
|
||||||
/**
|
/**
|
||||||
* Return for a given locale the provider URI to query to get the dictionary.
|
* Return for a given locale the provider URI to query to get the dictionary.
|
||||||
*/
|
*/
|
||||||
|
// TODO: remove this
|
||||||
public static Uri getProviderUri(Locale locale) {
|
public static Uri getProviderUri(Locale locale) {
|
||||||
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
.authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
|
.authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
|
||||||
locale.toString()).build();
|
locale.toString()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return for a given locale or dictionary id the provider URI to get the dictionary.
|
||||||
|
*/
|
||||||
|
private static Uri getProviderUri(String path) {
|
||||||
|
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
|
.authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
|
||||||
|
path).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries a content provider for the list of dictionaries for a specific locale
|
||||||
|
* available to copy into Latin IME.
|
||||||
|
*/
|
||||||
|
private static List<String> getDictIdList(final Locale locale, final Context context) {
|
||||||
|
final ContentResolver resolver = context.getContentResolver();
|
||||||
|
final Uri dictionaryPackUri = getProviderUri(locale);
|
||||||
|
|
||||||
|
final Cursor c = resolver.query(dictionaryPackUri, DICTIONARY_PROJECTION, null, null, null);
|
||||||
|
if (null == c) return Collections.<String>emptyList();
|
||||||
|
if (c.getCount() <= 0 || !c.moveToFirst()) {
|
||||||
|
c.close();
|
||||||
|
return Collections.<String>emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> list = new ArrayList<String>();
|
||||||
|
do {
|
||||||
|
final String id = c.getString(0);
|
||||||
|
if (TextUtils.isEmpty(id)) continue;
|
||||||
|
list.add(id);
|
||||||
|
} while (c.moveToNext());
|
||||||
|
c.close();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries a content provider for dictionary data for some locale and returns the file addresses
|
* Queries a content provider for dictionary data for some locale and returns the file addresses
|
||||||
*
|
*
|
||||||
|
@ -95,20 +135,26 @@ public class BinaryDictionaryFileDumper {
|
||||||
* @throw FileNotFoundException if the provider returns non-existent data.
|
* @throw FileNotFoundException if the provider returns non-existent data.
|
||||||
* @throw IOException if the provider-returned data could not be read.
|
* @throw IOException if the provider-returned data could not be read.
|
||||||
*/
|
*/
|
||||||
public static List<AssetFileAddress> getDictSetFromContentProvider(Locale locale,
|
public static List<AssetFileAddress> getDictSetFromContentProvider(final Locale locale,
|
||||||
Context context) throws FileNotFoundException, IOException {
|
final Context context) throws FileNotFoundException, IOException {
|
||||||
// TODO: check whether the dictionary is the same or not and if it is, return the cached
|
// TODO: check whether the dictionary is the same or not and if it is, return the cached
|
||||||
// file.
|
// file.
|
||||||
// TODO: This should be able to read a number of files from the dictionary pack, copy
|
// TODO: This should be able to read a number of files from the dictionary pack, copy
|
||||||
// them all and return them.
|
// them all and return them.
|
||||||
final ContentResolver resolver = context.getContentResolver();
|
final ContentResolver resolver = context.getContentResolver();
|
||||||
final Uri dictionaryPackUri = getProviderUri(locale);
|
final List<String> idList = getDictIdList(locale, context);
|
||||||
final AssetFileDescriptor afd = resolver.openAssetFileDescriptor(dictionaryPackUri, "r");
|
final List<AssetFileAddress> fileAddressList = new ArrayList<AssetFileAddress>();
|
||||||
if (null == afd) return null;
|
for (String id : idList) {
|
||||||
final String fileName =
|
final Uri dictionaryPackUri = getProviderUri(id);
|
||||||
copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context));
|
final AssetFileDescriptor afd =
|
||||||
afd.close();
|
resolver.openAssetFileDescriptor(dictionaryPackUri, "r");
|
||||||
return Arrays.asList(AssetFileAddress.makeFromFileName(fileName));
|
if (null == afd) continue;
|
||||||
|
final String fileName =
|
||||||
|
copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context));
|
||||||
|
afd.close();
|
||||||
|
fileAddressList.add(AssetFileAddress.makeFromFileName(fileName));
|
||||||
|
}
|
||||||
|
return fileAddressList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -63,9 +63,6 @@ class BinaryDictionaryGetter {
|
||||||
* Returns a list of file addresses for a given locale, trying relevant methods in order.
|
* Returns a list of file addresses for a given locale, trying relevant methods in order.
|
||||||
*
|
*
|
||||||
* Tries to get binary dictionaries from various sources, in order:
|
* Tries to get binary dictionaries from various sources, in order:
|
||||||
* - Uses a private method of getting a private dictionaries, as implemented by the
|
|
||||||
* PrivateBinaryDictionaryGetter class.
|
|
||||||
* If that fails:
|
|
||||||
* - Uses a content provider to get a public dictionary set, as per the protocol described
|
* - Uses a content provider to get a public dictionary set, as per the protocol described
|
||||||
* in BinaryDictionaryFileDumper.
|
* in BinaryDictionaryFileDumper.
|
||||||
* If that fails:
|
* If that fails:
|
||||||
|
@ -76,31 +73,23 @@ class BinaryDictionaryGetter {
|
||||||
*/
|
*/
|
||||||
public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context,
|
public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context,
|
||||||
int fallbackResId) {
|
int fallbackResId) {
|
||||||
// Try first to query a private package signed the same way for private files.
|
try {
|
||||||
final List<AssetFileAddress> privateFiles =
|
List<AssetFileAddress> listFromContentProvider =
|
||||||
PrivateBinaryDictionaryGetter.getDictionaryFiles(locale, context);
|
BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context);
|
||||||
if (null != privateFiles) {
|
if (null != listFromContentProvider) {
|
||||||
return privateFiles;
|
return listFromContentProvider;
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
// If that was no-go, try to find a publicly exported dictionary.
|
|
||||||
List<AssetFileAddress> listFromContentProvider =
|
|
||||||
BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context);
|
|
||||||
if (null != listFromContentProvider) {
|
|
||||||
return listFromContentProvider;
|
|
||||||
}
|
|
||||||
// If the list is null, fall through and return the fallback
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
Log.e(TAG, "Unable to create dictionary file from provider for locale "
|
|
||||||
+ locale.toString() + ": falling back to internal dictionary");
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Unable to read source data for locale "
|
|
||||||
+ locale.toString() + ": falling back to internal dictionary");
|
|
||||||
}
|
}
|
||||||
final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId,
|
// If the list is null, fall through and return the fallback
|
||||||
locale);
|
} catch (FileNotFoundException e) {
|
||||||
if (null == fallbackAsset) return null;
|
Log.e(TAG, "Unable to create dictionary file from provider for locale "
|
||||||
return Arrays.asList(fallbackAsset);
|
+ locale.toString() + ": falling back to internal dictionary");
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Unable to read source data for locale "
|
||||||
|
+ locale.toString() + ": falling back to internal dictionary");
|
||||||
}
|
}
|
||||||
|
final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId,
|
||||||
|
locale);
|
||||||
|
if (null == fallbackAsset) return null;
|
||||||
|
return Arrays.asList(fallbackAsset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue