TV测试中的按键长按操作模拟

从UiAutomator在TV测试中的局限性说起:        

         智能TV的操作和手机的操作有很大不同,一般智能TV的操作为遥控器按键操作,来向TV OS发送  KeyCode,以完成指定操作。

         UiAutomator在API中提供了控件和长按操作,也提供了点坐标的长按操作,但无法设置长按的时间。

         UiAutomator在API中也提供了模拟发送KeyCode的方法,即UiDevice类中的pressKeyCode方法。

         但TV遥控器按键的长按模拟方法,UiAutomator并没有直接提供,而电视中的视频快进等操作需要按         键长按,自动化测试有此方面的要求。

 

一.   KeyCode按键长按操作通过Adb命令模拟

        

         COMMAND:               adb shell input keyevent --longpress 3

     虽然可以实现长按操作,但长按只能实现简单的长按操作,长按时间较短,针对快进等需较长时间长按实现的操作无用。

 

二.   Appium的KeyCode长按模拟

          Appium里面实现了按键的长按操作,实现源码核心如下:

public AndroidCommandResult execute(final AndroidCommand command)
      throws JSONException {
    try {
      InteractionController interactionController = UiAutomatorBridge.getInstance().getInteractionController();

      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 (interactionController.injectEventSync(downEvent)) {
        // Send a repeat event. This will cause the FLAG_LONG_PRESS to be set.
        final KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(downEvent,
            eventTime, 1);
        interactionController.injectEventSync(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);
        interactionController.injectEventSync(upEvent);
      }
      return getSuccessResult(true);
    } catch (final Exception e) {
      return getErrorResult(e.getMessage());
    }
  }



        核心主要是:injectEventSync方法,剖析其源码发现最终是调用了uiautomator JAR包中                         com.android.uiautomator.core.InteractionController类的injectEventSync方法

         只是在uiautomator JAR包中,上述类类型为default且上述方法private方法

     若要调用需要使用反射技术 

 

        

三.   自己实现的时间可控的长按操作模拟源码

public void execute(int keycode, int times) {
	 
	int keyCode = keycode;
	int timeCount = times;
    try {
    // InteractionController interactionController = UiAutomatorBridge.getInstance().getInteractionController();
    	System.out.println("......ttt....");
   
      UiDevice device = UiDevice.getInstance();

      Class UiDevice_class = UiDevice.class;
      Field field_UiD = UiDevice_class.getDeclaredField("mUiAutomationBridge");
      field_UiD.setAccessible(true);
      Object uiAutomatorBridge  =  field_UiD.get(device);
      
      Class tmp = Class.forName("com.android.uiautomator.core.UiAutomatorBridge");
      Field field = tmp.getDeclaredField("mInteractionController");
      field.setAccessible(true);
      Object interactionController = field.get(uiAutomatorBridge);

      
      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);
      System.out.println("......lll,....");
      if (injectEventSync(downEvent,interactionController)) {
        // Send a repeat event. This will cause the FLAG_LONG_PRESS to be set.
        final KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(downEvent,
            eventTime, 1);
       for(int i=0; i<timeCount; i++){
    	   
    	   injectEventSync(repeatEvent,interactionController);
    	   
       }
        
        // Finally, send the up event
        System.out.println("......lll,....");
        final KeyEvent upEvent = new KeyEvent(eventTime, eventTime,
            KeyEvent.ACTION_UP, keyCode, 0, metaState,
            KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD);
        injectEventSync(upEvent,interactionController);

      }
      return ;
    } catch (final Exception e) {
      return ;
    }
  }



        

 

原文地址:https://www.cnblogs.com/udld/p/5746377.html