14

我的last關於同一主題的問題還不夠清楚,並被社區擱置,隨後被自動刪除。所以,我正在詳細解釋這個問題,以便社區能夠更好地理解和幫助。如何閱讀窗口內容(使用accessibilityService)並使用Android中的其他應用程序權限繪製喚醒UI?

我想要的功能與Voodoo AppMySmartPrice相似。

現在他們做什麼

第1步:當我們打開巫毒應用程序,因爲他們顯示一個小教程中的第一次。在教程結尾處有一個「立即激活」按鈕,當按下該按鈕時,我們進入輔助功能設置屏幕。

第2步:在輔助功能屏幕中,它進一步指導如何查找和無法使用Voodoo服務。

第3步:當我們啓用它時,它進一步要求授予「觀察您的操作」和「檢索窗口內容」權限。

第4步:一旦我們完成授予無障礙屏幕上的權限,並通過瀏覽器移動到一些購物應用或訪問購物網站,並達到產品頁面巫術浮動按鈕會自動彈出。

第5步:一旦我們點擊它,它會顯示在其他應用程序或網站上提供的相同/相關/類似產品的價格,以便用戶可以檢查可用的最佳交易。

巫毒的參考截圖

Voodoo Screen 1

Accessibility screen

Accessibility screen 2

Permission Granting Screen

Voodoo Screen 2

Voodoo Floating Button on product page

Voodoo Results with the help of draw over other app

現在我想知道形式的社區是什麼:

  1. 我如何可以顯示在屏幕輔助和商品詳細頁我的幫助UI。
  2. 如何檢測產品頁面何時顯示在屏幕上並喚起我的浮動按鈕。
  3. 如何獲取屏幕上顯示的產品名稱。
  4. 如何限制某些應用程序的屏幕閱讀功能? (因爲我不想最終在一些版權問題)
  5. 有沒有任何教程可以幫助我?儘管我已經在谷歌上嘗試過任何直接教程,並沒有取得任何成功。

現在爲什麼我需要這樣的信息:

我打算爲學生,這將有助於他們獲得有希望的(或類似)一書(電子書),一個免費的應用程序(如果可用)我的服務器或在一些網站上可用的網站上。由於某些書籍的版權問題,我只想限制它在某些應用中的功能。

現在我從我關於這個話題的研究知道(但我不知道我是否在正確的軌道與否)

+0

我能夠從屏幕讀取文本,但如何獲得確切的產品名稱。 –

+0

問題解決了。如果有人需要解決方案。請留下評論。我會盡可能快地發佈完整的anwser。 –

+0

你能分享你如何解決問題嗎? – Mahesh

回答

17

我曾試圖總結我是如何通過博客文章解決問題的。任何需要幫助的人都可以看一看。

Accessibility Service to the next level

我以前的答覆被版主刪除,則可能是由於我剛剛發佈了一個鏈接到博客。所以我在這裏再次發佈我的答案和細節。

最簡單的方法是由android本身提供的。如果你正在自己的應用程序上構建一些東西,這是實現它的最好和最簡單的方法。您必須使用「findAccessibilityNodeInfosByViewId ()」,如下

@Override 
public void onAccessibilityEvent(AccessibilityEvent event) { 
    AccessibilityNodeInfo source = event.getSource(); 
    if (source == null) { 
     return; 
    } 
    List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId = source.findAccessibilityNodeInfosByViewId("YOUR PACKAGE NAME:id/RESOURCE ID FROM WHERE YOU WANT DATA"); 
    if (findAccessibilityNodeInfosByViewId.size() > 0) { 
     AccessibilityNodeInfo parent = (AccessibilityNodeInfo) findAccessibilityNodeInfosByViewId.get(0); 
     // You can also traverse the list if required data is deep in view hierarchy. 
     String requiredText = parent.getText().toString(); 
     Log.i("Required Text", requiredText); 
    } 
} 

解釋的。如果你正在構建的其他應用程式的東西,不知道資源ID。您必須使用父級,子級計數,找到您的數據的級別,事件類型的組合來構建邏輯。您必須查找事件或來源中的模式或上述數值的組合以獲得所需的數據。此外,您必須在代碼中進行一些調整才能根據您的任務獲取準確的數據。就像我們的任務一樣,我們有一些正則表達式來獲取寶貴的數據。

您必須注意,如果更改視圖或用戶界面或更改資源標識,您當前的邏輯可能會失敗。因此,您必須密切關注您正在構建服務的應用程序。以下是一些示例代碼,我們可以在其中獲取數據而無需使用res id,這可能對您瞭解其工作原理有用。

要打印源和事件

@Override 
public void onAccessibilityEvent(AccessibilityEvent event) { 
    AccessibilityNodeInfo source = event.getSource(); 
    if (source == null) { 
     return; 
    } 
    Log.i("Event", event.toString+」」); 
    Log.i("Source", source.toString+」」); 
} 

要獲得childcount

source.getChildCount(); 

如果孩子計數> 0,你可能不得不考慮它。

示例代碼1

if (level == 0 && source.getClassName().equals("android.widget.TextView") && source.getText()!=null && !source.getText().toString().isEmpty()){ 
    // here level is iteration of for loop 
    String recivedText = source.getText().toString(); 
    if(source.getClassName().equals("android.widget.TextView") && source.getParent()!=null && source.getParent().getClassName().equals("android.widget.FrameLayout") && source.getParent().getParent()==null){ 
     return recivedText; 
    } 
} 

示例代碼2

if (source.getPackageName().equals("PACKAGE NAME OF APP FOR WHICH YOUR EXPECTING EVENT")) { 
    if(event.getEventType()==AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && "COMPLETE NAME OF ACTIVITY CLASS WITH PACKAGE NAME (if you want it for some specific screen)".equals(event.getClassName())){ 
     if(source.getText()!=null && source.getClassName().equals("android.widget.TextView") && source.getParent()!=null && source.getParent().getClassName().equals("android.widget.RelativeLayout")&& source.getParent().getParent()!=null && source.getParent().getParent().getClassName().equals("android.widget.ScrollView") && source.getParent().getParent().getParent()!=null && source.getParent().getParent().getParent().getClassName().equals("android.support.v4.view.ViewPager")&& source.getParent().getParent().getParent().getParent()!=null && source.getParent().getParent().getParent().getParent().getClassName().equals("android.widget.FrameLayout")&& source.getParent().getParent().getParent().getParent().getParent()==null){ 
     return source.getText().toString(); 
     } 
} 

這是有點笨拙,但得到它的工作,你必須仔細端詳日誌,以找到一個模式,其將帶你到你需要的數據。

更新20/11/2017 谷歌正在暫停所有使用無障礙服務的應用程序,用於輔助功能以外的其他應用程序。我收到了一封關於我的應用和其他開發者同樣的郵件,它們也收到了谷歌的同樣的電子郵件(Reddit)。所以,我認爲我們應該尋找其他方式來做事,並且請求你在這裏也更新它,如果有人想出其他的實現來實現同樣的行爲,那麼也會幫助別人。

感謝 Umesh製作肖漢

+0

感謝umesh你的回答+博客幫助我識別了幾乎所有的購物應用程序。我有一些小疑問,現在我正在註冊某些軟件包,我正在註冊這些事件,但是如何知道該應用程序是否已更改?(i:e;用戶按下home按鈕等),因爲那時我需要刪除聊天泡泡...任何想法? – Manikanta

+0

將啓動程序包添加到您的輔助功能服務中,並且當您從啓動程序收到事件時,只需在覆蓋窗口中關閉疊加層即可。 –

+0

謝謝。如果我可以通過電子郵件與您聯繫,我有幾個問題可以介紹嗎? – Manikanta

0

我已經成功地進行了這種類型的應用像voodoo.and的獲得Flipkart產品頁面標題,價格等成功。 以下用於獲取用戶打開產品屏幕的方法。

private boolean isOpenFlipkartProductScreen(AccessibilityNodeInfo nodeInfo){ 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
     if(nodeInfo.getViewIdResourceName()!=null){ 
      if(nodeInfo.getViewIdResourceName().equals("com.flipkart.android:id/callout_last_linearlayout")){ 
       Utils.sPrint("You just open product page : " + nodeInfo.getClass()); 
       isOpenProductPage = true; 
       return true; 
      } 
     } 
    } 
    return false; 
} 

以下代碼用於獲取產品標題名稱和價格。

private String getObtainTitle(AccessibilityNodeInfo sourceInfo){ 

    if(sourceInfo == null) 
     return ""; 

    AccessibilityNodeInfo nodeInfo = sourceInfo.getParent().getParent(); 
    if(nodeInfo!=null){ 
     int i = 0; 
     int i2 = 0; 
     for(int i3=0;i3<nodeInfo.getChildCount();i3++){ 

      try{ 
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
        if(nodeInfo.getChild(i3).getViewIdResourceName().equals("com.flipkart.android:id/title_layout")) { 
         i = 0; 
         // while (i < nodeInfo.getChild(i).getChildCount()){ 
         AccessibilityNodeInfo child = nodeInfo.getChild(i3).getChild(i); 
         String charSequence = child.getText().toString(); 
         // Utils.sPrint("Title is : " + charSequence); 
         if(charSequence!=null){ 
          return charSequence; 
         } 
         // } 

        } 
       } 
       /* 
       * 
       * Below code to used for getProduct prise in flipkart app product 
       * 
       * */ 
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
        if(nodeInfo.getChild(i3).getViewIdResourceName().equals("com.flipkart.android:id/price_layout")){ 
         AccessibilityNodeInfo child = nodeInfo.getChild(i3).getChild(i); 
         String charSequence = child.getText().toString(); 

         if (child.getText().toString().toUpperCase().startsWith("RS.") || 
           child.getText().toString().toUpperCase().startsWith("\u20b9")) { 
          String replace = charSequence.replace("Rs.", 
            "").replace("\u20b9", ""); 

          //return replace 
          // Utils.sPrint("Prise is : " + replace); 
         } 

        } 
       } 
      }catch (Exception ex){ 
       // Utils.sPrint("Ex : " + ex.getMessage()); 
       return ""; 
      } 

     } 
    } 
    return ""; 
} 
相關問題