1. 程式人生 > >TV測試中的按鍵長按操作模擬

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 ;
    }
  }