У меня есть приложение barebones, написанное для проверки поддержки нескольких дисплеев. Моя установка представляет собой пользовательский планшет Android с ОС Android 8.1.0 («основной дисплей»), подключенный к сенсорному экрану («дополнительный дисплей») через HDMI (для передачи видеосигнала) и USB (для доставки сенсорных событий).
Приложение содержит одно действие, которое отображает «Hello World!»на основном дисплее, но также использует DisplayManager
и WindowManager
для добавления счетчика и двух кнопок +
/ -
на дополнительном дисплее:
Running the app normally and interacting with the buttons on the secondary display works as expected.
Now, I want to use UI Automator скажем, нажмите кнопку +
и убедитесь, что счетчик записывает правильное значение. Это кажется невозможным. Кто-нибудь знает, как я могу это сделать?
В качестве альтернативы, если UI Automator не является подходящим инструментом для работы, но есть какой-то другой инструмент, который позволит мне писать сквознойВ завершение тестов в стиле черного ящика для приложений, отображающих контент на дополнительном дисплее, я рад получить рекомендации.
Некоторые вещи, которые я исследовал
Я использовал uiautomatorviewer
инструмент для проверки иерархии макетов моего приложения. С помощью этого инструмента отображается только содержимое основного дисплея:
Я использовал UiDevice.dumpWindowHierarchy()
, чтобы получитьтекстовый дамп всего на устройстве. Выводится только содержимое основного устройства, хотя это включает информацию о системных окнах, таких как строка состояния и панель навигации.
Я использовал adb shell dumpsys window
(с обоими tokens
и windows
команды). Этот покажет мне информацию об окне, которое я создал на дополнительном дисплее, но у меня, похоже, нет способа получить доступ к этому окну через Ui Automator:
Display #1
WindowToken{551f82f android.os.BinderProxy@87f65ac}:
windows=[Window{e40e275 u0 com.example.stackoverflow}]
windowType=2038 hidden=false hasVisible=true
Window #10 Window{20ac4ce u0 com.example.stackoverflow}:
mDisplayId=1 mSession=Session{91fdd93 8079:u0a10089} mClient=android.os.BinderProxy@a3e65c9
mOwnerUid=10089 mShowToOwnerOnly=true package=com.example.stackoverflow appop=SYSTEM_ALERT_WINDOW
mAttrs=WM.LayoutParams{(0,0)(fillxfill) sim=#20 ty=2038 fl=#1280480 colorMode=0}
Requested w=1280 h=800 mLayoutSeq=908
mBaseLayer=121000 mSubLayer=0 mAnimLayer=121000+0=121000 mLastLayer=121000
mToken=WindowToken{a42e219 android.os.BinderProxy@a3e65c9}
...
Соответствующие примеры кода
Добавление содержимого на дополнительный дисплей (в методе моей деятельности onResume()
):
DisplayManager manager = (DisplayManager) getApplicationContext().getSystemService(Context.DISPLAY_SERVICE);
Display display = manager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION)[0];
Context displayContext = getApplicationContext().createDisplayContext(display);
WindowManager windowManager = (WindowManager) displayContext.getSystemService(Context.WINDOW_SERVICE);
LinearLayout root = new LinearLayout(displayContext);
WindowManager.LayoutParams params = createLayoutParams();
windowManager.addView(root, params);
View.inflate(root.getContext(), R.layout.overlay, root);
root.findViewById(R.id.minus).setOnClickListener(v -> decrementCounter());
root.findViewById(R.id.plus).setOnClickListener(v -> incrementCounter());
Я использую контекст приложения вместо действияконтекст, чтобы содержимое на дополнительном дисплее не зависело от времени жизни действия, которое его создает. Теоретически я мог бы перейти к другим действиям, и этот контент оставался бы на дополнительном дисплее и оставался бы интерактивным.
Создание объекта LayoutParams
:
private WindowManager.LayoutParams createLayoutParams() {
return new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
0, 0,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
0,
PixelFormat.OPAQUE
);
}