このメソッドは、引数で渡されたテキストの各文字に対応する KeyCode を入力するものです。
そのため、typeText("日本語") としても"日本語"は入力されませんし、ソフトキーボードが日本語キーボードのときに typeText("andoroido") とすると、"あんどろいど" と入力されます。
また困ったことに、ソフトキーボードが日本語キーボードのときに typeText("12345") とすると、全角で入力されます。orz
日本語を入力するには、setText() で直接セットするしかありません。
そのための ViewAction を実装したクラスを用意しました。
- public void testInputJapanese() {
- onView(R.id.editText1).perform(clearText(), new InputTextAction("日本語"));
- onView(R.id.editText1).check(matches(withText("日本語")));
- }
- public final class InputTextAction implements ViewAction {
- private final String mText;
- public InputTextAction(String text) {
- checkNotNull(text);
- mText = text;
- }
- @SuppressWarnings("unchecked")
- @Override
- public Matcher<view> getConstraints() {
- return allOf(isDisplayed(), isAssignableFrom(EditText.class));
- }
- @Override
- public void perform(UiController uiController, View view) {
- ((EditText) view).setText(mText);
- }
- @Override
- public String getDescription() {
- return "set text";
- }
- }
- </view>
ちなみに typeText() の実体は TypeTextAction クラスです。
ViewActions.java
- public final class ViewActions {
- ...
- public static ViewAction typeText(String stringToBeTyped) {
- return new TypeTextAction(stringToBeTyped);
- }
- }
TypeTextAction.java
- public final class TypeTextAction implements ViewAction {
- private static final String TAG = TypeTextAction.class.getSimpleName();
- private final String stringToBeTyped;
- /**
- * Constructs {@link TypeTextAction} with given string. If the string is empty it results in no-op
- * (nothing is typed).
- *
- * @param stringToBeTyped String To be typed by {@link TypeTextAction}
- */
- public TypeTextAction(String stringToBeTyped) {
- checkNotNull(stringToBeTyped);
- this.stringToBeTyped = stringToBeTyped;
- }
- @SuppressWarnings("unchecked")
- @Override
- public Matcher<view> getConstraints() {
- Matcher<view> matchers = allOf(isDisplayed());
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
- return allOf(matchers, supportsInputMethods());
- } else {
- // SearchView does not support input methods itself (rather it delegates to an internal text
- // view for input).
- return allOf(matchers, anyOf(supportsInputMethods(), isAssignableFrom(SearchView.class)));
- }
- }
- @Override
- public void perform(UiController uiController, View view) {
- // No-op if string is empty.
- if (stringToBeTyped.length() == 0) {
- Log.w(TAG, "Supplied string is empty resulting in no-op (nothing is typed).");
- return;
- }
- // Perform a click.
- new GeneralClickAction(Tap.SINGLE, GeneralLocation.CENTER, Press.PINPOINT)
- .perform(uiController, view);
- uiController.loopMainThreadUntilIdle();
- try {
- if (!uiController.injectString(stringToBeTyped)) {
- Log.e(TAG, "Failed to type text: " + stringToBeTyped);
- throw new PerformException.Builder()
- .withActionDescription(this.getDescription())
- .withViewDescription(HumanReadables.describe(view))
- .withCause(new RuntimeException("Failed to type text: " + stringToBeTyped))
- .build();
- }
- } catch (InjectEventSecurityException e) {
- Log.e(TAG, "Failed to type text: " + stringToBeTyped);
- throw new PerformException.Builder()
- .withActionDescription(this.getDescription())
- .withViewDescription(HumanReadables.describe(view))
- .withCause(e)
- .build();
- }
- }
- @Override
- public String getDescription() {
- return "type text";
- }
- }
- </view></view>
UiControllerImpl.java
- @Override
- public boolean injectString(String str) throws InjectEventSecurityException {
- checkNotNull(str);
- checkState(Looper.myLooper() == mainLooper, "Expecting to be on main thread!");
- initialize();
- // No-op if string is empty.
- if (str.length() == 0) {
- Log.w(TAG, "Supplied string is empty resulting in no-op (nothing is typed).");
- return true;
- }
- boolean eventInjected = false;
- KeyCharacterMap keyCharacterMap = getKeyCharacterMap();
- // TODO(user): Investigate why not use (as suggested in javadoc of keyCharacterMap.getEvents):
- // http://developer.android.com/reference/android/view/KeyEvent.html#KeyEvent(long,
- // java.lang.String, int, int)
- KeyEvent[] events = keyCharacterMap.getEvents(str.toCharArray());
- checkNotNull(events, "Failed to get events for string " + str);
- Log.d(TAG, String.format("Injecting string: \"%s\"", str));
- for (KeyEvent event : events) {
- checkNotNull(event, String.format("Failed to get event for character (%c) with key code (%s)",
- event.getKeyCode(), event.getUnicodeChar()));
- eventInjected = false;
- for (int attempts = 0; !eventInjected && attempts < 4; attempts++) {
- attempts++;
- // We have to change the time of an event before injecting it because
- // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
- // time stamp and the system rejects too old events. Hence, it is
- // possible for an event to become stale before it is injected if it
- // takes too long to inject the preceding ones.
- event = KeyEvent.changeTimeRepeat(event, SystemClock.uptimeMillis(), 0);
- eventInjected = injectKeyEvent(event);
- }
- if (!eventInjected) {
- Log.e(TAG, String.format("Failed to inject event for character (%c) with key code (%s)",
- event.getUnicodeChar(), event.getKeyCode()));
- break;
- }
- }
- return eventInjected;
- }
0 件のコメント:
コメントを投稿