Included PluginManager.java,
prepared for use in KP2A (KeyboardBridge) Added ImeSwitcher.java for SecureSettings based switching
This commit is contained in:
		| @@ -0,0 +1,90 @@ | ||||
| package keepass2android.kbbridge; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import android.content.ComponentName; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.content.SharedPreferences; | ||||
| import android.content.SharedPreferences.Editor; | ||||
| import android.content.pm.ActivityInfo; | ||||
| import android.content.pm.ResolveInfo; | ||||
| import android.inputmethodservice.InputMethodService; | ||||
| import android.os.Bundle; | ||||
| import android.util.Log; | ||||
| import android.view.inputmethod.InputMethod; | ||||
| import android.view.inputmethod.InputMethodManager; | ||||
| import android.widget.Toast; | ||||
|  | ||||
| public class ImeSwitcher { | ||||
| 	private static final String PREVIOUS_KEYBOARD = "previous_keyboard"; | ||||
| 	private static final String KP2A_SWITCHER = "KP2A_Switcher"; | ||||
| 	private static final String Tag = "KP2A_SWITCHER"; | ||||
| 	 | ||||
| 	public static void switchToPreviousKeyboard(Context ctx) | ||||
| 	{ | ||||
| 		SharedPreferences prefs = ctx.getSharedPreferences(KP2A_SWITCHER, Context.MODE_PRIVATE); | ||||
| 		switchToKeyboard(ctx, prefs.getString(PREVIOUS_KEYBOARD, null)); | ||||
| 	} | ||||
|  | ||||
| 	public static void switchToKeyboard(Context ctx, String newImeName) | ||||
| 	{ | ||||
| 		if (newImeName == null) | ||||
| 		{ | ||||
| 			showPicker(ctx); | ||||
| 			return; | ||||
| 			 | ||||
| 		} | ||||
| 		Intent qi = new Intent("com.twofortyfouram.locale.intent.action.FIRE_SETTING"); | ||||
| 		List<ResolveInfo> pkgAppsList = ctx.getPackageManager().queryBroadcastReceivers(qi, 0); | ||||
| 		boolean sentBroadcast = false; | ||||
| 		for (ResolveInfo ri: pkgAppsList) | ||||
| 		{ | ||||
| 			 | ||||
| 			if (ri.activityInfo.packageName.equals("com.intangibleobject.securesettings.plugin")) | ||||
| 			{ | ||||
| 				 | ||||
| 				String currentIme = android.provider.Settings.Secure.getString( | ||||
|                         ctx.getContentResolver(), | ||||
|                         android.provider.Settings.Secure.DEFAULT_INPUT_METHOD); | ||||
| 								 | ||||
| 				SharedPreferences prefs = ctx.getSharedPreferences(KP2A_SWITCHER, Context.MODE_PRIVATE); | ||||
| 				Editor edit = prefs.edit(); | ||||
| 				 | ||||
| 				edit.putString(PREVIOUS_KEYBOARD, currentIme); | ||||
| 				edit.commit(); | ||||
| 				 | ||||
| 				Intent i=new Intent("com.twofortyfouram.locale.intent.action.FIRE_SETTING"); | ||||
| 				Bundle b = new Bundle(); | ||||
|  | ||||
| 				b.putString("com.intangibleobject.securesettings.plugin.extra.BLURB", "Input Method/Switch IME"); | ||||
| 				b.putString("com.intangibleobject.securesettings.plugin.extra.INPUT_METHOD", newImeName); | ||||
| 				b.putString("com.intangibleobject.securesettings.plugin.extra.SETTING","default_input_method"); | ||||
| 				i.putExtra("com.twofortyfouram.locale.intent.extra.BUNDLE", b); | ||||
| 				ctx.sendBroadcast(i); | ||||
| 				sentBroadcast = true; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if (!sentBroadcast) | ||||
| 		{ | ||||
| 			//report that switch failed: | ||||
| 			try | ||||
| 			{ | ||||
| 				Toast.makeText(ctx, "SecureSettings not found on system!", Toast.LENGTH_LONG).show();	 | ||||
| 			} | ||||
| 			catch (Exception e) | ||||
| 			{ | ||||
| 				Log.e(Tag, e.toString()); | ||||
| 			} | ||||
| 				 | ||||
| 			showPicker(ctx);	 | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	private static void showPicker(Context ctx) { | ||||
| 		((InputMethodManager) ctx.getSystemService(InputMethodService.INPUT_METHOD_SERVICE)) | ||||
| 			.showInputMethodPicker(); | ||||
| 	} | ||||
| } | ||||
| @@ -4,12 +4,13 @@ import java.util.HashMap; | ||||
| public class KeyboardDataBuilder { | ||||
| 	 private ArrayList<StringForTyping> availableFields = new ArrayList<StringForTyping>(); | ||||
| 	  | ||||
| 	 public void addPair(String displayName, String valueToType) | ||||
| 	 public void addString(String key, String displayName, String valueToType) | ||||
| 	 { | ||||
| 		 StringForTyping pair = new StringForTyping(); | ||||
| 		 pair.displayName = displayName; | ||||
| 		 pair.value = valueToType; | ||||
| 		 availableFields.add(pair); | ||||
| 		 StringForTyping stringToType = new StringForTyping(); | ||||
| 		 stringToType.key = key; | ||||
| 		 stringToType.displayName = displayName; | ||||
| 		 stringToType.value = valueToType; | ||||
| 		 availableFields.add(stringToType); | ||||
| 	 } | ||||
| 	  | ||||
| 	 public void commit() | ||||
|   | ||||
| @@ -78,7 +78,20 @@ public class BinaryDictionary extends Dictionary { | ||||
|         } | ||||
|         mDicTypeId = dicTypeId; | ||||
|     } | ||||
|  | ||||
|      | ||||
|     /** | ||||
|      * Create a dictionary from input streams | ||||
|      * @param context application context for reading resources | ||||
|      * @param streams the resource streams containing the raw binary dictionary | ||||
|      */ | ||||
|     public BinaryDictionary(Context context, InputStream[] streams, int dicTypeId) { | ||||
|         if (streams != null && streams.length > 0) { | ||||
|             loadDictionary(context, streams); | ||||
|         } | ||||
|         mDicTypeId = dicTypeId; | ||||
|     } | ||||
|      | ||||
|      | ||||
|     /** | ||||
|      * Create a dictionary from a byte buffer. This is used for testing. | ||||
|      * @param context application context for reading resources | ||||
| @@ -115,28 +128,13 @@ public class BinaryDictionary extends Dictionary { | ||||
|         InputStream[] is = null; | ||||
|         try { | ||||
|             // merging separated dictionary into one if dictionary is separated | ||||
|             int total = 0; | ||||
|             is = new InputStream[resId.length]; | ||||
|             for (int i = 0; i < resId.length; i++) { | ||||
|                 is[i] = context.getResources().openRawResource(resId[i]); | ||||
|                 total += is[i].available(); | ||||
|             } | ||||
|  | ||||
|             mNativeDictDirectBuffer = | ||||
|                 ByteBuffer.allocateDirect(total).order(ByteOrder.nativeOrder()); | ||||
|             int got = 0; | ||||
|             for (int i = 0; i < resId.length; i++) { | ||||
|                  got += Channels.newChannel(is[i]).read(mNativeDictDirectBuffer); | ||||
|             } | ||||
|             if (got != total) { | ||||
|                 Log.e(TAG, "Read " + got + " bytes, expected " + total); | ||||
|             } else { | ||||
|                 mNativeDict = openNative(mNativeDictDirectBuffer, | ||||
|                         TYPED_LETTER_MULTIPLIER, FULL_WORD_FREQ_MULTIPLIER); | ||||
|                 mDictLength = total; | ||||
|             } | ||||
|         } catch (IOException e) { | ||||
|             Log.w(TAG, "No available memory for binary dictionary"); | ||||
|             loadDictionary(context, is); | ||||
|              | ||||
|              | ||||
|         } finally { | ||||
|             try { | ||||
|                 if (is != null) { | ||||
| @@ -151,7 +149,48 @@ public class BinaryDictionary extends Dictionary { | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     private void loadDictionary(Context context, InputStream[] is)  | ||||
|     { | ||||
|     	try | ||||
|     	{ | ||||
| 	    	int total = 0; | ||||
| 	        for (int i = 0; i < is.length; i++) | ||||
| 	        	total += is[i].available(); | ||||
| 	 | ||||
| 	        mNativeDictDirectBuffer = | ||||
| 	            ByteBuffer.allocateDirect(total).order(ByteOrder.nativeOrder()); | ||||
| 	        int got = 0; | ||||
| 	        for (int i = 0; i < is.length; i++) { | ||||
| 	             got += Channels.newChannel(is[i]).read(mNativeDictDirectBuffer); | ||||
| 	        } | ||||
| 	        if (got != total) { | ||||
| 	            Log.e(TAG, "Read " + got + " bytes, expected " + total); | ||||
| 	        } else { | ||||
| 	            mNativeDict = openNative(mNativeDictDirectBuffer, | ||||
| 	                    TYPED_LETTER_MULTIPLIER, FULL_WORD_FREQ_MULTIPLIER); | ||||
| 	            mDictLength = total; | ||||
| 	        }	 | ||||
| 	  | ||||
|     	} | ||||
|     	catch (IOException e) { | ||||
|             Log.w(TAG, "No available memory for binary dictionary"); | ||||
|         } catch (UnsatisfiedLinkError e) { | ||||
|             Log.w(TAG, "Failed to load native dictionary", e); | ||||
|         } finally { | ||||
|             try { | ||||
|                 if (is != null) { | ||||
|                     for (int i = 0; i < is.length; i++) { | ||||
|                         is[i].close(); | ||||
|                     } | ||||
|                 } | ||||
|             } catch (IOException e) { | ||||
|                 Log.w(TAG, "Failed to close input stream"); | ||||
|             } | ||||
|         } | ||||
|     	        | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
|     public void getBigrams(final WordComposer codes, final CharSequence previousWord, | ||||
|             final WordCallback callback, int[] nextLettersFrequencies) { | ||||
|  | ||||
|   | ||||
| @@ -120,6 +120,15 @@ public class InputLanguageSelection extends PreferenceActivity { | ||||
|         if (bd.getSize() > Suggest.LARGE_DICTIONARY_THRESHOLD / 4) { | ||||
|             haveDictionary = true; | ||||
|         } | ||||
|         else  | ||||
|         { | ||||
|             BinaryDictionary plug = PluginManager.getDictionary(getApplicationContext(), locale.getLanguage()); | ||||
|             if (plug != null) { | ||||
|                 bd.close(); | ||||
|                 bd = plug; | ||||
|                 haveDictionary = true; | ||||
|             } | ||||
|         } | ||||
|         bd.close(); | ||||
|         conf.locale = saveLocale; | ||||
|         res.updateConfiguration(conf, res.getDisplayMetrics()); | ||||
|   | ||||
| @@ -452,6 +452,8 @@ public class KP2AKeyboard extends InputMethodService | ||||
|         }*/ | ||||
|         unregisterReceiver(mReceiver); | ||||
|          | ||||
|         unregisterReceiver(mClearKeyboardReceiver); | ||||
|          | ||||
|         LatinImeLogger.commit(); | ||||
|         LatinImeLogger.onDestroy(); | ||||
|         super.onDestroy(); | ||||
| @@ -571,25 +573,29 @@ public class KP2AKeyboard extends InputMethodService | ||||
| 		 | ||||
| 		int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION; | ||||
|          | ||||
|         if (keepass2android.kbbridge.KeyboardData.hasData() !=  | ||||
|         		mHadKp2aData) | ||||
|         { | ||||
|         	if (keepass2android.kbbridge.KeyboardData.hasData()) | ||||
|         	{ | ||||
|         		//new data available -> show kp2a keyboard: | ||||
|         		mShowKp2aKeyboard = true; | ||||
|         	} | ||||
|         	else | ||||
|         	{ | ||||
|         		//data no longer available. hide kp2a keyboard: | ||||
|         		mShowKp2aKeyboard = false; | ||||
|         	} | ||||
| 		if (!keepass2android.kbbridge.KeyboardData.hasData()) | ||||
| 		{ | ||||
| 			//data no longer available. hide kp2a keyboard: | ||||
|     		mShowKp2aKeyboard = false; | ||||
|     		mHadKp2aData = false; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 		 | ||||
| 	        if (!mHadKp2aData) | ||||
| 	        { | ||||
| 	        	if (keepass2android.kbbridge.KeyboardData.hasData()) | ||||
| 	        	{ | ||||
| 	        		//new data available -> show kp2a keyboard: | ||||
| 	        		mShowKp2aKeyboard = true; | ||||
| 	        	} | ||||
| 	        } | ||||
|         	 | ||||
|         	mHadKp2aData = keepass2android.kbbridge.KeyboardData.hasData(); | ||||
|         } | ||||
|          | ||||
|         Log.d("KP2AK", "show: " + mShowKp2aKeyboard); | ||||
|         if (mShowKp2aKeyboard) | ||||
|         if ((mShowKp2aKeyboard) && (mKp2aEnableSimpleKeyboard)) | ||||
|         { | ||||
|         	mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_KP2A, attribute.imeOptions); | ||||
|             mPredictionOn = false; | ||||
| @@ -2204,7 +2210,7 @@ public class KP2AKeyboard extends InputMethodService | ||||
|         return mWord.isFirstCharCapitalized(); | ||||
|     } | ||||
|  | ||||
|     private void toggleLanguage(boolean reset, boolean next) { | ||||
|     void toggleLanguage(boolean reset, boolean next) { | ||||
|         if (reset) { | ||||
|             mLanguageSwitcher.reset(); | ||||
|         } else { | ||||
|   | ||||
| @@ -0,0 +1,259 @@ | ||||
| package keepass2android.softkeyboard; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| import org.xmlpull.v1.XmlPullParserException; | ||||
|  | ||||
| import android.content.BroadcastReceiver; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.content.pm.ApplicationInfo; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.content.pm.ResolveInfo; | ||||
| import android.content.pm.PackageManager.NameNotFoundException; | ||||
| import android.content.res.Resources; | ||||
| import android.content.res.XmlResourceParser; | ||||
| import android.util.Log; | ||||
|  | ||||
| public class PluginManager extends BroadcastReceiver { | ||||
|     private static String TAG = "PCKeyboard"; | ||||
|     private static String HK_INTENT_DICT = "org.pocketworkstation.DICT"; | ||||
|     private static String SOFTKEYBOARD_INTENT_DICT = "com.menny.android.anysoftkeyboard.DICTIONARY"; | ||||
|     private KP2AKeyboard mIME; | ||||
|      | ||||
|     // Apparently anysoftkeyboard doesn't use ISO 639-1 language codes for its locales? | ||||
|     // Add exceptions as needed. | ||||
|     private static Map<String, String> SOFTKEYBOARD_LANG_MAP = new HashMap<String, String>(); | ||||
|     static { | ||||
|         SOFTKEYBOARD_LANG_MAP.put("dk", "da"); | ||||
|     } | ||||
|      | ||||
|     PluginManager(KP2AKeyboard ime) { | ||||
|     	super(); | ||||
|     	mIME = ime; | ||||
|     } | ||||
|      | ||||
|     private static Map<String, DictPluginSpec> mPluginDicts = | ||||
|         new HashMap<String, DictPluginSpec>(); | ||||
|      | ||||
|     static interface DictPluginSpec { | ||||
|         BinaryDictionary getDict(Context context); | ||||
|     } | ||||
|  | ||||
|     static private abstract class DictPluginSpecBase | ||||
|             implements DictPluginSpec { | ||||
|         String mPackageName; | ||||
|          | ||||
|         Resources getResources(Context context) { | ||||
|             PackageManager packageManager = context.getPackageManager(); | ||||
|             Resources res = null; | ||||
|             try { | ||||
|                 ApplicationInfo appInfo = packageManager.getApplicationInfo(mPackageName, 0); | ||||
|                 res = packageManager.getResourcesForApplication(appInfo); | ||||
|             } catch (NameNotFoundException e) { | ||||
|                 Log.i(TAG, "couldn't get resources"); | ||||
|             } | ||||
|             return res; | ||||
|         } | ||||
|  | ||||
|         abstract InputStream[] getStreams(Resources res); | ||||
|  | ||||
|         public BinaryDictionary getDict(Context context) { | ||||
|             Resources res = getResources(context); | ||||
|             if (res == null) return null; | ||||
|  | ||||
|             InputStream[] dicts = getStreams(res); | ||||
|             if (dicts == null) return null; | ||||
|             BinaryDictionary dict = new BinaryDictionary( | ||||
|                     context, dicts, Suggest.DIC_MAIN); | ||||
|             if (dict.getSize() == 0) return null; | ||||
|             //Log.i(TAG, "dict size=" + dict.getSize()); | ||||
|             return dict; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static private class DictPluginSpecHK | ||||
|             extends DictPluginSpecBase { | ||||
|          | ||||
|         int[] mRawIds; | ||||
|  | ||||
|         public DictPluginSpecHK(String pkg, int[] ids) { | ||||
|             mPackageName = pkg; | ||||
|             mRawIds = ids; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         InputStream[] getStreams(Resources res) { | ||||
|             if (mRawIds == null || mRawIds.length == 0) return null; | ||||
|             InputStream[] streams = new InputStream[mRawIds.length]; | ||||
|             for (int i = 0; i < mRawIds.length; ++i) { | ||||
|                 streams[i] = res.openRawResource(mRawIds[i]); | ||||
|             } | ||||
|             return streams; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     static private class DictPluginSpecSoftKeyboard | ||||
|             extends DictPluginSpecBase { | ||||
|          | ||||
|         String mAssetName; | ||||
|  | ||||
|         public DictPluginSpecSoftKeyboard(String pkg, String asset) { | ||||
|             mPackageName = pkg; | ||||
|             mAssetName = asset; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         InputStream[] getStreams(Resources res) { | ||||
|             if (mAssetName == null) return null; | ||||
|             try { | ||||
|                 InputStream in = res.getAssets().open(mAssetName); | ||||
|                 return new InputStream[] {in}; | ||||
|             } catch (IOException e) { | ||||
|                 Log.e(TAG, "Dictionary asset loading failure"); | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public void onReceive(Context context, Intent intent) { | ||||
|         Log.i(TAG, "Package information changed, updating dictionaries."); | ||||
|         getPluginDictionaries(context); | ||||
|         Log.i(TAG, "Finished updating dictionaries."); | ||||
|         mIME.toggleLanguage(true, true); | ||||
|     } | ||||
|  | ||||
|     static void getSoftKeyboardDictionaries(PackageManager packageManager) { | ||||
|         Intent dictIntent = new Intent(SOFTKEYBOARD_INTENT_DICT); | ||||
|         List<ResolveInfo> dictPacks = packageManager.queryBroadcastReceivers( | ||||
|         		dictIntent, PackageManager.GET_RECEIVERS); | ||||
|         for (ResolveInfo ri : dictPacks) { | ||||
|             ApplicationInfo appInfo = ri.activityInfo.applicationInfo; | ||||
|             String pkgName = appInfo.packageName; | ||||
|             boolean success = false; | ||||
|             try { | ||||
|                 Resources res = packageManager.getResourcesForApplication(appInfo); | ||||
|                 Log.i("KP2AK", "Found dictionary plugin package: " + pkgName); | ||||
|                 int dictId = res.getIdentifier("dictionaries", "xml", pkgName); | ||||
|                 if (dictId == 0) continue; | ||||
|                 XmlResourceParser xrp = res.getXml(dictId); | ||||
|  | ||||
|                 String assetName = null; | ||||
|                 String lang = null; | ||||
|                 try { | ||||
|                     int current = xrp.getEventType(); | ||||
|                     while (current != XmlResourceParser.END_DOCUMENT) { | ||||
|                         if (current == XmlResourceParser.START_TAG) { | ||||
|                             String tag = xrp.getName(); | ||||
|                             if (tag != null) { | ||||
|                                 if (tag.equals("Dictionary")) { | ||||
|                                     lang = xrp.getAttributeValue(null, "locale"); | ||||
|                                     String convLang = SOFTKEYBOARD_LANG_MAP.get(lang); | ||||
|                                     if (convLang != null) lang = convLang; | ||||
|                                     String type = xrp.getAttributeValue(null, "type"); | ||||
|                                     if (type == null || type.equals("raw") || type.equals("binary")) { | ||||
|                                         assetName = xrp.getAttributeValue(null, "dictionaryAssertName"); // sic | ||||
|                                     } else { | ||||
|                                         Log.w(TAG, "Unsupported AnySoftKeyboard dict type " + type); | ||||
|                                     } | ||||
|                                     //Log.i(TAG, "asset=" + assetName + " lang=" + lang); | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         xrp.next(); | ||||
|                         current = xrp.getEventType(); | ||||
|                     } | ||||
|                 } catch (XmlPullParserException e) { | ||||
|                     Log.e(TAG, "Dictionary XML parsing failure"); | ||||
|                 } catch (IOException e) { | ||||
|                     Log.e(TAG, "Dictionary XML IOException"); | ||||
|                 } | ||||
|  | ||||
|                 if (assetName == null || lang == null) continue; | ||||
|                 DictPluginSpec spec = new DictPluginSpecSoftKeyboard(pkgName, assetName); | ||||
|                 mPluginDicts.put(lang, spec); | ||||
|                 Log.i("KP2AK", "Found plugin dictionary: lang=" + lang + ", pkg=" + pkgName); | ||||
|                 success = true; | ||||
|             } catch (NameNotFoundException e) { | ||||
|                 Log.i("KP2AK", "bad"); | ||||
|             } finally { | ||||
|                 if (!success) { | ||||
|                     Log.i("KP2AK", "failed to load plugin dictionary spec from " + pkgName); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static void getHKDictionaries(PackageManager packageManager) { | ||||
|         Intent dictIntent = new Intent(HK_INTENT_DICT); | ||||
|         List<ResolveInfo> dictPacks = packageManager.queryIntentActivities(dictIntent, 0); | ||||
|         for (ResolveInfo ri : dictPacks) { | ||||
|             ApplicationInfo appInfo = ri.activityInfo.applicationInfo; | ||||
|             String pkgName = appInfo.packageName; | ||||
|             boolean success = false; | ||||
|             try { | ||||
|                 Resources res = packageManager.getResourcesForApplication(appInfo); | ||||
|                 Log.i("KP2AK", "Found dictionary plugin package: " + pkgName); | ||||
|                 int langId = res.getIdentifier("dict_language", "string", pkgName); | ||||
|                 if (langId == 0) continue; | ||||
|                 String lang = res.getString(langId); | ||||
|                 int[] rawIds = null; | ||||
|                  | ||||
|                 // Try single-file version first | ||||
|                 int rawId = res.getIdentifier("main", "raw", pkgName); | ||||
|                 if (rawId != 0) { | ||||
|                     rawIds = new int[] { rawId }; | ||||
|                 } else { | ||||
|                     // try multi-part version | ||||
|                     int parts = 0; | ||||
|                     List<Integer> ids = new ArrayList<Integer>(); | ||||
|                     while (true) { | ||||
|                         int id = res.getIdentifier("main" + parts, "raw", pkgName); | ||||
|                         if (id == 0) break; | ||||
|                         ids.add(id); | ||||
|                         ++parts; | ||||
|                     } | ||||
|                     if (parts == 0) continue; // no parts found | ||||
|                     rawIds = new int[parts]; | ||||
|                     for (int i = 0; i < parts; ++i) rawIds[i] = ids.get(i); | ||||
|                 } | ||||
|                 DictPluginSpec spec = new DictPluginSpecHK(pkgName, rawIds); | ||||
|                 mPluginDicts.put(lang, spec); | ||||
|                 Log.i("KP2AK", "Found plugin dictionary: lang=" + lang + ", pkg=" + pkgName); | ||||
|                 success = true; | ||||
|             } catch (NameNotFoundException e) { | ||||
|                 Log.i("KP2AK", "bad"); | ||||
|             } finally { | ||||
|                 if (!success) { | ||||
|                     Log.i("KP2AK", "failed to load plugin dictionary spec from " + pkgName); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static void getPluginDictionaries(Context context) { | ||||
|         mPluginDicts.clear(); | ||||
|         PackageManager packageManager = context.getPackageManager(); | ||||
|         getSoftKeyboardDictionaries(packageManager); | ||||
|         getHKDictionaries(packageManager); | ||||
|     } | ||||
|      | ||||
|     static BinaryDictionary getDictionary(Context context, String lang) { | ||||
|         Log.i("KP2AK", "Looking for plugin dictionary for lang=" + lang); | ||||
|         DictPluginSpec spec = mPluginDicts.get(lang); | ||||
|         if (spec == null) spec = mPluginDicts.get(lang.substring(0, 2)); | ||||
|         if (spec == null) { | ||||
|             Log.i("KP2AK", "No plugin found."); | ||||
|             return null; | ||||
|         } | ||||
|         BinaryDictionary dict = spec.getDict(context); | ||||
|         Log.i("KP2AK", "Found plugin dictionary for " + lang + (dict == null ? " is null" : ", size=" + dict.getSize())); | ||||
|         return dict; | ||||
|     } | ||||
| } | ||||
| @@ -26,6 +26,7 @@ import java.nio.ByteBuffer; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
|  | ||||
| /** | ||||
|  * This class loads a dictionary and provides a list of suggestions for a given sequence of  | ||||
| @@ -105,14 +106,28 @@ public class Suggest implements Dictionary.WordCallback { | ||||
|  | ||||
|     public Suggest(Context context, int[] dictionaryResId) { | ||||
|         mMainDict = new BinaryDictionary(context, dictionaryResId, DIC_MAIN); | ||||
|         Log.d("KP2AK", "main size: " + mMainDict.getSize()+ " " +dictionaryResId[0]); | ||||
|          | ||||
|          | ||||
|         Locale locale = context.getResources().getConfiguration().locale; | ||||
|         Log.d("KP2AK", "locale: " + locale.getISO3Language()); | ||||
|          | ||||
|         if (!hasMainDictionary()  | ||||
|         		|| (!"eng".equals(locale.getISO3Language())))  | ||||
|         { | ||||
|         	Log.d("KP2AK", "try get plug"); | ||||
|             BinaryDictionary plug = PluginManager.getDictionary(context, locale.getLanguage()); | ||||
|             if (plug != null) { | ||||
|             	Log.d("KP2AK", "ok"); | ||||
|                 mMainDict.close(); | ||||
|                 mMainDict = plug; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|          | ||||
|         initPool(); | ||||
|     } | ||||
|  | ||||
|     public Suggest(Context context, ByteBuffer byteBuffer) { | ||||
|         mMainDict = new BinaryDictionary(context, byteBuffer, DIC_MAIN); | ||||
|         initPool(); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     private void initPool() { | ||||
|         for (int i = 0; i < mPrefMaxSuggestions; i++) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll