1/** 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v13.view.inputmethod; 18 19import android.support.annotation.RequiresApi; 20import android.os.Build; 21import android.os.Bundle; 22import android.support.annotation.NonNull; 23import android.support.annotation.Nullable; 24import android.view.inputmethod.EditorInfo; 25 26/** 27 * Helper for accessing features in {@link EditorInfo} introduced after API level 13 in a backwards 28 * compatible fashion. 29 */ 30public final class EditorInfoCompat { 31 32 /** 33 * Flag of {@link EditorInfo#imeOptions}: used to request that the IME does not update any 34 * personalized data such as typing history and personalized language model based on what the 35 * user typed on this text editing object. Typical use cases are: 36 * <ul> 37 * <li>When the application is in a special mode, where user's activities are expected to be 38 * not recorded in the application's history. Some web browsers and chat applications may 39 * have this kind of modes.</li> 40 * <li>When storing typing history does not make much sense. Specifying this flag in typing 41 * games may help to avoid typing history from being filled up with words that the user is 42 * less likely to type in their daily life. Another example is that when the application 43 * already knows that the expected input is not a valid word (e.g. a promotion code that is 44 * not a valid word in any natural language).</li> 45 * </ul> 46 * 47 * <p>Applications need to be aware that the flag is not a guarantee, and some IMEs may not 48 * respect it.</p> 49 */ 50 public static final int IME_FLAG_NO_PERSONALIZED_LEARNING = 0x1000000; 51 52 /** 53 * Flag of {@link EditorInfo#imeOptions}: used to request an IME that is capable of inputting 54 * ASCII characters. 55 * 56 * <p>The intention of this flag is to ensure that the user can type Roman alphabet characters 57 * in a {@link android.widget.TextView}. It is typically used for an account ID or password 58 * input.</p> 59 * 60 * <p>In many cases, IMEs are already able to input ASCII even without being told so (such IMEs 61 * already respect this flag in a sense), but there are cases when this is not the default. For 62 * instance, users of languages using a different script like Arabic, Greek, Hebrew or Russian 63 * typically have a keyboard that can't input ASCII characters by default.</p> 64 * 65 * <p>Applications need to be aware that the flag is not a guarantee, and some IMEs may not 66 * respect it. However, it is strongly recommended for IME authors to respect this flag 67 * especially when their IME could end up with a state where only languages using non-ASCII are 68 * enabled.</p> 69 */ 70 public static final int IME_FLAG_FORCE_ASCII = 0x80000000; 71 72 private interface EditorInfoCompatImpl { 73 void setContentMimeTypes(@NonNull EditorInfo editorInfo, 74 @Nullable String[] contentMimeTypes); 75 @NonNull 76 String[] getContentMimeTypes(@NonNull EditorInfo editorInfo); 77 } 78 79 private static final String[] EMPTY_STRING_ARRAY = new String[0]; 80 81 private static final class EditorInfoCompatBaseImpl implements EditorInfoCompatImpl { 82 private static String CONTENT_MIME_TYPES_KEY = 83 "android.support.v13.view.inputmethod.EditorInfoCompat.CONTENT_MIME_TYPES"; 84 85 @Override 86 public void setContentMimeTypes(@NonNull EditorInfo editorInfo, 87 @Nullable String[] contentMimeTypes) { 88 if (editorInfo.extras == null) { 89 editorInfo.extras = new Bundle(); 90 } 91 editorInfo.extras.putStringArray(CONTENT_MIME_TYPES_KEY, contentMimeTypes); 92 } 93 94 @NonNull 95 @Override 96 public String[] getContentMimeTypes(@NonNull EditorInfo editorInfo) { 97 if (editorInfo.extras == null) { 98 return EMPTY_STRING_ARRAY; 99 } 100 String[] result = editorInfo.extras.getStringArray(CONTENT_MIME_TYPES_KEY); 101 return result != null ? result : EMPTY_STRING_ARRAY; 102 } 103 } 104 105 @RequiresApi(25) 106 private static final class EditorInfoCompatApi25Impl implements EditorInfoCompatImpl { 107 @Override 108 public void setContentMimeTypes(@NonNull EditorInfo editorInfo, 109 @Nullable String[] contentMimeTypes) { 110 editorInfo.contentMimeTypes = contentMimeTypes; 111 } 112 113 @NonNull 114 @Override 115 public String[] getContentMimeTypes(@NonNull EditorInfo editorInfo) { 116 final String[] result = editorInfo.contentMimeTypes; 117 return result != null ? result : EMPTY_STRING_ARRAY; 118 } 119 } 120 121 private static final EditorInfoCompatImpl IMPL; 122 static { 123 if (Build.VERSION.SDK_INT >= 25) { 124 IMPL = new EditorInfoCompatApi25Impl(); 125 } else { 126 IMPL = new EditorInfoCompatBaseImpl(); 127 } 128 } 129 130 /** 131 * Sets MIME types that can be accepted by the target editor if the IME calls 132 * {@link InputConnectionCompat#commitContent(InputConnection, EditorInfo, 133 * InputContentInfoCompat, int, Bundle)}. 134 * 135 * @param editorInfo the editor with which we associate supported MIME types 136 * @param contentMimeTypes an array of MIME types. {@code null} and an empty array means that 137 * {@link InputConnectionCompat#commitContent( 138 * InputConnection, EditorInfo, InputContentInfoCompat, int, Bundle)} 139 * is not supported on this Editor 140 */ 141 public static void setContentMimeTypes(@NonNull EditorInfo editorInfo, 142 @Nullable String[] contentMimeTypes) { 143 IMPL.setContentMimeTypes(editorInfo, contentMimeTypes); 144 } 145 146 /** 147 * Gets MIME types that can be accepted by the target editor if the IME calls 148 * {@link InputConnectionCompat#commitContent(InputConnection, EditorInfo, 149 * InputContentInfoCompat, int, Bundle)} 150 * 151 * @param editorInfo the editor from which we get the MIME types 152 * @return an array of MIME types. An empty array means that {@link 153 * InputConnectionCompat#commitContent(InputConnection, EditorInfo, InputContentInfoCompat, 154 * int, Bundle)} is not supported on this editor 155 */ 156 @NonNull 157 public static String[] getContentMimeTypes(EditorInfo editorInfo) { 158 return IMPL.getContentMimeTypes(editorInfo); 159 } 160 161} 162