3

我已經部署到三星注4安卓AccessibilityService運行Android 5.0.1。Android輔助服務 - 屏幕更新不相符

我使用WhatsApp的作爲測試平臺,但是這適用於任何應用程序,並且圍繞輔助服務,如何觸發關閉事件的更多的問題。

事件2048 (TYPE_WINDOW_CONTENT_CHANGED)是不相符的由Android解僱。如果我將消息發送給我的WhatsApp並將其重點放在了焦點上,並且在75%的時間內這個事件被觸發了,並且有時根本不會。

這是有原因嗎?輔助功能事件不可依賴..?

此外,當用戶滾動時或當WhatsApps的聊天窗口中出現新的對應關係時,似乎事件4096 (TYPE_VIEW_SCROLLED)會一直被解僱,但似乎無法確定設備當前的滾動位置是什麼? AccessibilityEvent.getSource()提供訪問一些元數據的列表(在這種情況下,機器人:ID /列表),但是沒有可用來此列表或其子元素的滾動位置的信息。子列表與屏幕上顯示的內容有關,無論您是查看列表底部還是中間還是頂部,值都是相同的。有沒有什麼線索可以幫助我確定我提交的AccessibilityEventNodeInfo實例的滾動位置?

最後,當2048 (TYPE_WINDOW_CONTENT_CHANGED)事件不火,有些時候,新的元素實際上不是可以從AccessibiltyEvent.getSource()(甚至當你使用getParent()遍歷到根元素六while循環,然後再向下掃描)。在更改應用到UI之前,看起來事件正在拍攝屏幕快照。 A thread.sleep沒有幫助 - 因爲看起來AccessibilityEventNodeInfo比實時訪問UI更像快照嗎?任何方式在這個?

回答

2

是否有什麼原因呢?可訪問性事件不是 dependendable ..?

我發現它更可能是你誤解了一個TYPE_WINDOW_CONTENT_CHANGED事件被觸發,而不是一致地被解僱或被捕獲。例如,此特定事件不會在屏幕刷新上觸發,而僅在新窗口內容上觸發。應用程序開發人員可以選擇而不是啓動新的活動來重新繪製其活動內容。在這種情況下,從用戶的角度來看,窗口內容已經改變了,但是,在應用程序的後端,他所發生的一切都是繪製了新的視圖。

thread.sleep並沒有幫助 - 因爲它看起來AccessibilityEventNodeInfo更像是一個快照而不是實時訪問UI?任何方式在這個?

這也是爲什麼元素從事件源丟失的解釋。在動態元素繪製之前,您正在獲取事件。因此,啓動一個新的活動並使用新內容進行初始化,但是,應用程序可能會進入某種類型的網絡/ REST資源的等待模式。在這些資源進入事件之前,不久之後會繪製新的內容。因此,您的眼睛看起來會獲得不完整的內容,但真正發生的是您在事件觸發時獲取完整內容。你是thread.sleep方法工作得很好。然而,在你睡覺之後,你不能檢查event.getSource()的值,睡眠不會改變傳遞給這個函數的東西。相反,你想睡覺,然後爬過整個視圖heirarchy找到你想要的信息。睡覺,然後用

getRootInActiveWindow(); 

代替

event.getSource(); 

是否有任何線索,以幫助我確定從AccessibilityEventNodeInfo情況下,我帶有滾動條的位置?

是和否。不,從無障礙服務無法檢測滾動條的位置。但是,您可以通過執行以下操作來檢測滾動事件的大概位置:

private float getScrollPosition(AccessibilityEvent event) { 
    final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event); 
    final int itemCount = event.getItemCount(); 
    final int fromIndex = event.getFromIndex(); 

    // First, attempt to use (fromIndex/itemCount). 
    if ((fromIndex >= 0) && (itemCount > 0)) { 
     return (fromIndex/(float) itemCount); 
    } 

    final int scrollY = record.getScrollY(); 
    final int maxScrollY = record.getMaxScrollY(); 

    // Next, attempt to use (scrollY/maxScrollY). This will fail if the 
    // getMaxScrollX() method is not available. 
    if ((scrollY >= 0) && (maxScrollY > 0)) { 
     return (scrollY/(float) maxScrollY); 
    } 

    // Finally, attempt to use (scrollY/itemCount). 
    // TODO(alanv): Hack from previous versions -- is it still needed? 
    if ((scrollY >= 0) && (itemCount > 0) && (scrollY <= itemCount)) { 
     return (scrollY/(float) itemCount); 
    } 

    return 0.5f; 
} 

這是直接來自Google的TalkBack代碼。您可以在EyesFree項目的ScrollFormatter.java中找到它。這不是一個理想的解決方案。如果事件恰好來自大型佈局(就像在Chrome瀏覽器中經常出現的那樣),那麼對於很大一部分滾動,您可能會得到相同的結果。但是,這些API不支持比此更精確的任何事情,所以如果您想知道您的近似滾動位置,這是一個必要的攻擊。我認爲,即使使用可用的API,也可以對此方法進行重大改進,儘管這需要一些工作。