# 介面監視器

監視器用來即時監聽介面的變化，並在滿足預設條件時，執行預設的動作，如點擊元素、按鍵，或是記錄發生次數。您可以將其理解為**李跳跳**或類似自動跳過廣告功能的底層實作。由於此功能會自動進行點擊或按鍵操作，當需要人工介入時可能會發生非預期的動作，所以請謹慎使用。

```{tip}
正常情況下，監視器以及事件註冊應該在腳本最開始的時候進行，執行過程中一般不會再進行。
```

## 啟用監視器

以下介面將會啟用介面監視器，預設情況下監視器處於禁用狀態。

```{attention}
在啟用監視器或啟用監視事件之前，介面上發生的任何匹配事件的操作均不會被處理！
```

```python
d.set_watcher_loop_enabled(True)
```

## 獲取監視器是否啟用

您可以使用以下介面得知目前介面監視器是否處於啟用狀態。

```python
d.get_watcher_loop_enabled()
```

## 關閉監視器

關閉監視器迴圈，將不會再自動處理已註冊的事件（如點擊等）。

```python
d.set_watcher_loop_enabled(False)
```

```{attention}
註冊過多的監視事件可能會影響系統效能或操作的即時性。
```

## 移除所有監視器

移除所有已應用的監視事件，這樣可以清除之前或異常中斷的腳本所應用的規則。建議每次啟動腳本前都執行一次，以防止先前任務註冊的事件影響目前的正常處理流程。

```python
d.remove_all_watchers()
```

## 註冊點擊事件

點擊事件將會在介面出現匹配的選擇器時自動進行點擊等操作，例如自動繞過軟體彈出視窗（如使用協議、更新提示等），或是對某些特定介面進行自動點擊。

```{attention}
在啟用監視器或啟用監視事件之前，介面上發生的任何匹配事件的操作均不會被處理！
```

```python
d.register_click_target_selector_watcher("ClickAcceptWhenShowAggrement", [Selector(textContains="使用者協議")], Selector(textContains="同意", clickable=True))
```

```{hint}
第二個參數支援多個 Selector，表示所有 Selector 條件都滿足時才會進行事件處理。
```

註冊如上事件後，當介面出現包含「使用者協議」文字時，將會自動點擊「同意」按鈕。

## 註冊按鍵事件

按鍵事件將會在介面出現匹配的選擇器時進行自動的按鍵操作（如自動返回等），可以自動避免進入某些介面。當然，使用點擊事件也可實現同樣的操作。

```{attention}
在啟用監視器或啟用監視事件之前，介面上發生的任何匹配事件的操作均不會被處理！
```

```python
d.register_press_key_watcher("PressBackWhenHomePageShows", [Selector(textContains="個人中心")], Keys.KEY_HOME)
```

```{hint}
第二個參數支援多個 Selector，表示所有 Selector 條件都滿足時才會進行事件處理。
```

註冊如上事件後，當介面出現包含「個人中心」文字時，將會自動按下手機的 HOME 鍵。

## 註冊計數事件

計數事件是在介面出現某些匹配選擇器的操作時，將計數器 + 1。當介面會出現一閃而過的重要資訊時，可以使用此功能來統計是否出現過某些介面或其出現的次數。

```{attention}
在啟用監視器或啟用監視事件之前，介面上發生的任何匹配事件的操作均不會被處理！
```

```python
d.register_none_op_watcher("RecordElementAppearTimes", [Selector(textContains="好的")])
```

```{hint}
第二個參數支援多個 Selector，表示所有 Selector 條件都滿足時才會進行事件處理。
```

以上事件會記錄包含「好的」的介面出現次數。使用以下介面來獲取計數事件的觸發次數。

```python
d.get_watcher_triggered_count("RecordElementAppearTimes")
```

## 啟用事件

事件註冊過後，需要啟用才會註冊到介面監視器迴圈中，否則將不會被應用。

```{attention}
在啟用監視器或啟用監視事件之前，介面上發生的任何匹配事件的操作均不會被處理！
```

```python
d.set_watcher_enabled("RecordElementAppearTimes", True)
```


## 關閉事件

您可以呼叫以下介面來讓介面監視器取消監視某個事件。

```{attention}
在啟用監視器或啟用監視事件之前，介面上發生的任何匹配事件的操作均不會被處理！
```

```python
d.set_watcher_enabled("RecordElementAppearTimes", False)
```

## 移除事件

從監視器中完全移除一個事件，同時該事件也將會從已註冊事件中刪除。

```python
d.remove_watcher(name)
```

## 獲取是否啟用事件

呼叫以下介面來檢查事件是否已正確啟用，以防止註冊了但未啟用的情況。

```python
d.get_watcher_enabled(name)
```

## 進階選擇器

除了支援簡單選擇器外，您也可以提供更複雜的選擇器來進行元素匹配。以下範例說明如何編寫一個複雜的選擇器。

```python
d.register_press_key_watcher("PressBackWhenHomePageShows", [Selector(resourceId="com.android.market:id/v_app_item").child(index=3).sibling(index=2).child(index=2).child()], Keys.KEY_HOME)
```

## 完整範例程式碼

以下是一個範例程式碼區塊，它啟用了監視器迴圈並註冊了三種監視器事件。當介面出現包含「使用者協議」的文字時，會自動點擊「同意」；當介面出現包含「個人中心」的文字時，會立即返回桌面；當介面出現包含「好的」的文字時，則記錄這個介面出現的次數。

```{attention}
在啟用監視器或啟用監視事件之前，介面上發生的任何匹配事件的操作均不會被處理！
```

```python
d.remove_all_watchers()
d.set_watcher_loop_enabled(True)

d.register_click_target_selector_watcher("ClickAcceptWhenShowAggrement", [Selector(textContains="使用者協議")],
                                         Selector(textContains="同意", clickable=True))
d.register_press_key_watcher("PressBackWhenHomePageShows", [Selector(textContains="個人中心")], Keys.KEY_HOME)
d.register_none_op_watcher("RecordElementAppearTimes", [Selector(textContains="好的")])

d.set_watcher_enabled("ClickAcceptWhenShowAggrement", True)
d.set_watcher_enabled("PressBackWhenHomePageShows", True)
d.set_watcher_enabled("RecordElementAppearTimes", True)
```