diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 07dae168f483c1c5ad4ca0fe7ee5a7fef7aa3743..5e73d6300ef39e568296a247b62caa15637bea25 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.keyboard;
 
 import com.android.inputmethod.latin.Utils;
+import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -59,6 +60,15 @@ public class ProximityInfo {
         return new ProximityInfo(1, 1, 1, 1, 1, Collections.<Key>emptyList());
     }
 
+    public static ProximityInfo getSpellCheckerProximityInfo() {
+        final ProximityInfo spellCheckerProximityInfo = getDummyProximityInfo();
+        spellCheckerProximityInfo.mNativeProximityInfo =
+                spellCheckerProximityInfo.setProximityInfoNative(
+                        SpellCheckerProximityInfo.ROW_SIZE,
+                        480, 300, 10, 3, SpellCheckerProximityInfo.PROXIMITY);
+        return spellCheckerProximityInfo;
+    }
+
     private int mNativeProximityInfo;
     static {
         Utils.loadNativeLibrary();
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 7c92bc82a38c3e20b88844ec00c1cd84e2b49f1d..44e999572668a2e8a73aaefc5fbba2822a2cf472 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -19,7 +19,6 @@ package com.android.inputmethod.latin.spellcheck;
 import android.content.res.Resources;
 import android.service.textservice.SpellCheckerService;
 import android.service.textservice.SpellCheckerService.Session;
-import android.util.Log;
 import android.view.textservice.SuggestionsInfo;
 import android.view.textservice.TextInfo;
 
@@ -33,6 +32,7 @@ import com.android.inputmethod.latin.DictionaryFactory;
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.WordComposer;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.LinkedList;
@@ -48,7 +48,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
     private static final boolean DBG = true;
 
     private final static String[] emptyArray = new String[0];
-    private final ProximityInfo mProximityInfo = ProximityInfo.getDummyProximityInfo();
+    private final ProximityInfo mProximityInfo = ProximityInfo.getSpellCheckerProximityInfo();
     private final Map<String, Dictionary> mDictionaries =
             Collections.synchronizedMap(new TreeMap<String, Dictionary>());
 
@@ -141,8 +141,16 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
             final WordComposer composer = new WordComposer();
             final int length = text.length();
             for (int i = 0; i < length; ++i) {
-                int character = text.codePointAt(i);
-                composer.add(character, new int[] { character },
+                final int character = text.codePointAt(i);
+                final int proximityIndex = SpellCheckerProximityInfo.getIndexOf(character);
+                final int[] proximities;
+                if (-1 == proximityIndex) {
+                    proximities = new int[] { character };
+                } else {
+                    proximities = Arrays.copyOfRange(SpellCheckerProximityInfo.PROXIMITY,
+                            proximityIndex, proximityIndex + SpellCheckerProximityInfo.ROW_SIZE);
+                }
+                composer.add(character, proximities,
                         WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
             }
             dictionary.getWords(composer, suggestionsGatherer, mProximityInfo);
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..abcf7e52a11f4fc222e6edb450d472bd8149e9b7
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
@@ -0,0 +1,94 @@
+/*
+ * 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.spellcheck;
+
+import com.android.inputmethod.keyboard.KeyDetector;
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+public class SpellCheckerProximityInfo {
+    final private static int NUL = KeyDetector.NOT_A_CODE;
+
+    // This must be the same as MAX_PROXIMITY_CHARS_SIZE else it will not work inside
+    // native code - this value is passed at creation of the binary object and reused
+    // as the size of the passed array afterwards so they can't be different.
+    final public static int ROW_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE;
+
+    // This is a map from the code point to the index in the PROXIMITY array.
+    // At the time the native code to read the binary dictionary needs the proximity info be passed
+    // as a flat array spaced by MAX_PROXIMITY_CHARS_SIZE columns, one for each input character.
+    // Since we need to build such an array, we want to be able to search in our big proximity data
+    // quickly by character, and a map is probably the best way to do this.
+    final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>();
+
+    // The proximity here is the union of
+    // - the proximity for a QWERTY keyboard.
+    // - the proximity for an AZERTY keyboard.
+    // - the proximity for a QWERTZ keyboard.
+    // ...plus, add all characters in the ('a', 'e', 'i', 'o', 'u') set to each other.
+    //
+    // The reasoning behind this construction is, almost any alphabetic text we may want
+    // to spell check has been entered with one of the keyboards above. Also, specifically
+    // to English, many spelling errors consist of the last vowel of the word being wrong
+    // because in English vowels tend to merge with each other in pronunciation.
+    final public static int[] PROXIMITY = {
+        'q', 'w', 's', 'a', 'z', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'w', 'q', 'a', 's', 'd', 'e', 'x', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'e', 'w', 's', 'd', 'f', 'r', 'a', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL,
+        'r', 'e', 'd', 'f', 'g', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        't', 'r', 'f', 'g', 'h', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'y', 't', 'g', 'h', 'j', 'u', 'a', 's', 'd', 'x', NUL, NUL, NUL, NUL, NUL, NUL,
+        'u', 'y', 'h', 'j', 'k', 'i', 'a', 'e', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'i', 'u', 'j', 'k', 'l', 'o', 'a', 'e', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'o', 'i', 'k', 'l', 'p', 'a', 'e', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'p', 'o', 'l', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+        'a', 'z', 'x', 's', 'w', 'q', 'e', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL,
+        's', 'q', 'a', 'z', 'x', 'c', 'd', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'd', 'w', 's', 'x', 'c', 'v', 'f', 'r', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL,
+        'f', 'e', 'd', 'c', 'v', 'b', 'g', 't', 'r', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'g', 'r', 'f', 'v', 'b', 'n', 'h', 'y', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'h', 't', 'g', 'b', 'n', 'm', 'j', 'u', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'j', 'y', 'h', 'n', 'm', 'k', 'i', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'k', 'u', 'j', 'm', 'l', 'o', 'i', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'l', 'i', 'k', 'p', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+        'z', 'a', 's', 'd', 'x', 't', 'g', 'h', 'j', 'u', 'q', 'e', NUL, NUL, NUL, NUL,
+        'x', 'z', 'a', 's', 'd', 'c', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'c', 'x', 's', 'd', 'f', 'v', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'v', 'c', 'd', 'f', 'g', 'b', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'b', 'v', 'f', 'g', 'h', 'n', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'n', 'b', 'g', 'h', 'j', 'm', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        'm', 'n', 'h', 'j', 'k', 'l', 'o', 'p', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+        NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+    };
+    static {
+        for (int i = 0; i < PROXIMITY.length; i += ROW_SIZE) {
+            if (NUL != PROXIMITY[i]) INDICES.put(PROXIMITY[i], i);
+        }
+    }
+    public static int getIndexOf(int characterCode) {
+        final Integer result = INDICES.get(characterCode);
+        if (null == result) return -1;
+        return result;
+    }
+}