首页 > 代码库 > bootstrap之PressKeyCode&&LongPressKeyCode

bootstrap之PressKeyCode&&LongPressKeyCode

PressKeyCode


package io.appium.android.bootstrap.handler;

import com.android.uiautomator.core.UiDevice;
import io.appium.android.bootstrap.AndroidCommand;
import io.appium.android.bootstrap.AndroidCommandResult;
import io.appium.android.bootstrap.CommandHandler;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.Hashtable;

/**
 * This handler is used to PressKeyCode.
 *
 */
public class PressKeyCode extends CommandHandler {
  public Integer keyCode;
  public Integer metaState;

  /*
   * @param command The {@link AndroidCommand} used for this handler.
   *
   * @return {@link AndroidCommandResult}
   *
   * @throws JSONException
   *
   * @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android.
   * bootstrap.AndroidCommand)
   */
  @Override
  public AndroidCommandResult execute(final AndroidCommand command)
      throws JSONException {
    try {
      final Hashtable<String, Object> params = command.params();
      Object kc = params.get("keycode");
      if (kc instanceof Integer) {
        keyCode = (Integer) kc;
      } else if (kc instanceof String) {
        keyCode = Integer.parseInt((String) kc);
      } else {
        throw new IllegalArgumentException("Keycode of type " + kc.getClass() + "not supported.");
      }

      if (params.get("metastate") != JSONObject.NULL) {
        metaState = (Integer) params.get("metastate");
        UiDevice.getInstance().pressKeyCode(keyCode, metaState);
      } else {
        UiDevice.getInstance().pressKeyCode(keyCode);
      }

      return getSuccessResult(true);
    } catch (final Exception e) {
      return getErrorResult(e.getMessage());
    }
  }
}


有的时候手机键盘的一些键需要按,但是又没有像pressBack这种方法供我们直接调用,这个时候我们就需要发送键盘的keycode来模拟这些键被点击。所以PressKeyCode就是封装这类事件的,通过上面的代码可以看出,发送keycode分2类事件,每一类调用的方法不一样

  • 单点键:pressKeyCode(keyCode,metaState)
  • 组合键:  pressKeyCode(keyCode,metaState)


LongPressKeyCode


package io.appium.android.bootstrap.handler;

import android.os.SystemClock;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import com.android.uiautomator.common.ReflectionUtils;
import io.appium.android.bootstrap.AndroidCommand;
import io.appium.android.bootstrap.AndroidCommandResult;
import io.appium.android.bootstrap.CommandHandler;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Method;
import java.util.Hashtable;

/**
 * This handler is used to LongPressKeyCode.
 * 
 */
public class LongPressKeyCode extends CommandHandler {
  public Integer keyCode;

  public Integer metaState;

  /*
   * @param command The {@link AndroidCommand} used for this handler.
   * 
   * @return {@link AndroidCommandResult}
   * 
   * @throws JSONException
   * 
   * @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android.
   * bootstrap.AndroidCommand)
   */
  @Override
  public AndroidCommandResult execute(final AndroidCommand command)
      throws JSONException {
    try {
      final ReflectionUtils utils = new ReflectionUtils();
      final Method injectEventSync = utils.getControllerMethod("injectEventSync",
          InputEvent.class);
      final Hashtable<String, Object> params = command.params();
      keyCode = (Integer) params.get("keycode");
      metaState = params.get("metastate") != JSONObject.NULL ? (Integer) params
          .get("metastate") : 0;
      final long eventTime = SystemClock.uptimeMillis();
      // Send an initial down event
      final KeyEvent downEvent = new KeyEvent(eventTime, eventTime,
          KeyEvent.ACTION_DOWN, keyCode, 0, metaState,
          KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD);
      if ((Boolean) injectEventSync.invoke(utils.getController(), downEvent)) {
        // Send a repeat event. This will cause the FLAG_LONG_PRESS to be set.
        final KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(downEvent,
            eventTime, 1);
        injectEventSync.invoke(utils.getController(), repeatEvent);
        // Finally, send the up event
        final KeyEvent upEvent = new KeyEvent(eventTime, eventTime,
            KeyEvent.ACTION_UP, keyCode, 0, metaState,
            KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD);
        injectEventSync.invoke(utils.getController(), upEvent);
      }
      return getSuccessResult(true);
    } catch (final Exception e) {
      return getErrorResult(e.getMessage());
    }
  }
}

长点击某个键盘键,和上面的单击是有区别的,因为没有直接的API可以调用,所以又要用到反射来做这件事,这次的反射呢调用的是InteractionController中的injectEventSync方法,首先会执行ACTION_DOWN,然后在一段时间里会重复执行这个down的动作,等事件到了以后,执行ACTION_UP这个动作松开键盘键。从而达到了我们到长按到要求。

bootstrap之PressKeyCode&&LongPressKeyCode