1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/didiopensource-DiDiPrism

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README.md 12 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 30.11.2024 05:48 f257596

小桔棱镜 Android SDK

  • Модуль prism-monitor отвечает за сбор данных о действиях пользователя.
  • Модуль prsim-playback отвечает за воспроизведение действий пользователя.
  • Модуль prism-behavior отвечает за обнаружение действий пользователя.

prism-monitor: использование

// Инициализация при создании приложения
PrismMonitor.getInstance().init(application);
// Запуск и настройка прослушивателя событий
PrismMonitor.getInstance().start();
PrismMonitor.getInstance().addOnPrismMonitorListener(new PrismMonitor.OnPrismMonitorListener() {
    @Override
    public void onEvent(EventData eventData) {
        // Получение информации о событии через метод, например, текстовое воспроизведение и т. д., подробности см. в демо.
        EventInfo eventInfo = PlaybackHelper.convertEventInfo(eventData);
    }
});

prsim-playback: использование

// Инициализация при создании приложения
PrismPlayback.getInstance().init(this);

// Сбор данных о событиях с помощью PrismMonitor
List<EventData> mPlaybackEvents = ...;
// Начало воспроизведения
PrismPlayback.getInstance().playback(mPlaybackEvents);

PrismBehavior: использование

// Инициализация при создании приложения
PrismBehavior.getInstance().init(this);

// Настройка правил поведения
// При выполнении действия в соответствии с правилом поведения отправляется широковещательное сообщение action=prism_behavior_detect_rule_hit.
PrismBehavior.getInstance().setRules(...);
// Начало обнаружения
PrismBehavior.getInstance().start();
// Остановка обнаружения
PrismBehavior.getInstance().stop();

Принцип работы

На платформе Android в основном собираются данные о действиях пользователей, таких как нажатия на экран и события, связанные с изменением интерфейса приложения (переключение между передним и задним планами, вход и выход из страниц, всплывающие окна и т.д.), но не включая более сложные жесты, такие как скольжение, поскольку текущая ценность бизнес-данных, которые можно извлечь, невелика.

Одной из наиболее сложных задач является сбор данных о нажатиях на экран, поскольку необходимо выполнить следующие шаги:

  1. Получить нажатый элемент View.
  2. Создать уникальный идентификатор на основе элемента View.

1. Получение нажатого элемента View

Вот несколько основных методов, используемых в настоящее время:

  • Перебор всех элементов View в Activity и установка AccessibilityDelegate для каждого из них.
  • Вставка кода в события щелчка с использованием ASM.
  • Наследование от baseActivity или baseDialog для получения события ACTION_DOWN в dispatchTouchEvent и объединение его с TouchTarget для получения результата.

Здесь мы не будем анализировать преимущества и недостатки каждого метода, а только представим метод, используемый в Prism Mirror.

Метод, используемый Prism Mirror, похож на последний метод, но вместо наследования от baseActivity или baseDialog используется прослушивание Window. Возможно, вы не очень хорошо знакомы с Window.Callback, но вы можете получить события dispatchTouchEvent и dispatchKeyEvent, установив Callback для Window.

  • dispatchTouchEvent — получение нажатого элемента View при событии ACTION_DOWN путём объединения с TouchTarget.
  • dispatchKeyEvent — получение событий, связанных с клавишами, такими как возврат.

Следующий вопрос заключается в том, как прослушивать Window?

Window связан с WindowManagerImpl, который управляет всеми экземплярами Window приложений. Экземпляр Window фактически является объектом типа View. Вы можете посмотреть исходный код WindowManagerImpl:

public final class WindowManagerImpl implements WindowManager {
    ...
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    ...
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }
    ...
}

Из исходного кода видно, что экземпляры Window добавляются в mGlobal, и далее мы можем посмотреть исходный код WindowManagerGlobal:

public final class WindowManagerGlobal {
    ...
    private final ArrayList<View> mViews = new ArrayList<View>();
    ...
    public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
        ...
        mViews.add(view);
        ...
    }
    ...
}

Мы видим, что экземпляр View наконец добавляется в mViews, и теперь мы можем изменить этот mViews в объект, который можно прослушивать, например:

public class WindowObserver extends ArrayList<View> {
    @Override
    public boolean add(View view) {
        // ...
        return super.add(view);
    }

    @Override
    public View remove(int index) {
        // ...
        return super.remove(index);
    }
}

Таким образом, каждый раз, когда отображается окно приложения, мы сразу получаем экземпляр View этого окна. Затем мы используем экземпляр View для обратного поиска экземпляра Window. Через точку останова мы обнаруживаем, что когда view является экземпляром окна Activity или Dialog, это DecorView. Вы должны быть хорошо знакомы с ним! Посмотрите его исходный код:

public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
    ...
    private PhoneWindow mWindow;
    ...
}

Вы видите, что он напрямую содержит экземпляр Window! Мы можем получить его через рефлексию!

После выполнения этих операций мы получаем экземпляр Window, можем установить Callback и получать все события пользовательских действий dispatchTouchEvent и dispatchKeyEvent, а также получать нажатые элементы View.

2. Создание уникального идентификатора на основе элемента View

В настоящее время некоторые основные методы объединяют некоторую ключевую информацию в соответствии с определённым форматом для создания уникального идентификатора. Эта ключевая информация включает в себя: имя класса Activity, идентификатор View или имя ресурса, класс View и путь View. Различные методы имеют разные соображения и оптимизированные способы. Далее мы рассмотрим три аспекта метода Prism Mirror:

2.1 Информация о окне, в котором находится нажатый элемент View Мы не используем имя класса Activity напрямую, потому что нажатый элемент View может находиться как в Activity, так и в Dialog, поэтому мы добавили слой логики окна, то есть тип окна, используя w для представления информации об окне в формате: w_&_{имя окна}_&_{тип окна}, где имя окна фактически является именем класса Activity, а тип окна равен 0 или 1, представляя Activity или Dialog, соединённые символом _&_. Например, w_&_com.prism.MainActivity_&_0.

2.2 Информация о пути элемента View в дереве View Мы не записываем уровень класса View или индекс каждого уровня, а записываем только ключевые уровни, используя vp для представления информации о пути View. Вот несколько примеров:

  • Когда уровень может получить идентификатор view, например: vp_&_titlebar_item_left_back/thanos_title_bar/content[01]/, где content[01] представляет собой системный контент android.R.id.content, различаемый [01]. Когда на уровне иерархии есть view-элементы типа AbsListView или RecyclerView, например: vp_&_*/listView/navigation_drawer/drawer_layout/content[01]/_^_vl_&_l:4,10, где * обозначает элемент ListView, который был нажат, vl используется для описания информации о повторно используемых элементах контейнера, а l:4, 10 означает четвёртый элемент в AbsListView и десятый в источнике данных.

2.3 Информация, которую можно извлечь из самого нажатого view

  • Если у view есть id, то используется обозначение vi для информации об id, например: vi_&_titlebar_item_left_back.
  • Если у view есть ресурсы, такие как drawable, используется обозначение vr для информации о ресурсах, например: vr_&_selector_btn_confirm.
  • Если из view можно извлечь текстовую информацию, используется обозначение vc для текстовой информации, например: vc_&_确定.

Наконец, информация, извлечённая по этим трём измерениям, объединяется через ^, чтобы создать уникальный идентификатор для нажатого view, например: w_&_com.prism.MainActivity_&_0_^_vp_&_titlebar_item_left_back/thanos_title_bar/content[01]/_^_vi_&_titlebar_item_left_back_^_vc_&_确定 .

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/didiopensource-DiDiPrism.git
git@api.gitlife.ru:oschina-mirror/didiopensource-DiDiPrism.git
oschina-mirror
didiopensource-DiDiPrism
didiopensource-DiDiPrism
master