如何阅读窗口内容(使用accessibilityService)并使用绘制来激活UI而不是Android中的其他应用程序权限? [英] How to read window content (using accessibilityService) and evoking UI using draw over other app permission in Android?

查看:320
本文介绍了如何阅读窗口内容(使用accessibilityService)并使用绘制来激活UI而不是Android中的其他应用程序权限?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于同一主题的我的















现在我想知道的形式社区:


  1. 如何在辅助功能屏幕和产品详细信息页面上显示我的帮助UI。

  2. 如何检测产品页面何时出现在屏幕上唤起我的浮动按钮。

  3. 如何获取屏幕上显示的产品名称。

  4. 如何限制某些应用的屏幕阅读功能? (因为我不想最终出现一些版权问题)

  5. 有没有可以帮助我的教程?虽然我已经尝试过谷歌任何直接教程,但没有取得任何成功。

现在为什么我需要这些信息:



我正在计划一个应用程序如果学生可以在我的服务器上或在可用网站的某个网站上免费获得所需(或类似)书籍(电子书)的学生。我想限制某些应用程序的功能仅由于某些书籍的版权问题。



现在我从我的研究中了解到这个主题(但我不确定)我是否在正确的轨道上)




解决方案

我曾试图总结一下我是如何在博客文章中解决问题的。任何需要帮助的人都可以查看。



无障碍服务更上一层楼



我以前的回答被主持人删除可能是因为我刚刚发布了一个指向博客的链接。所以我也在这里再次发布我的答案。



最简单的方法是由android本身提供。如果您在自己的应用程序上构建一些东西,这是最好和最简单的方法。您必须使用findAccessibilityNodeInfosByViewId
(),如下所述

  @Override 
public void onAccessibilityEvent( AccessibilityEvent事件){
AccessibilityNodeInfo source = event.getSource();
if(source == null){
return;
}
列表< AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId = source.findAccessibilityNodeInfosByViewId(你的包名称:从你想要数据的地方的id / RESOURCE ID);
if(findAccessibilityNodeInfosByViewId.size()> 0){
AccessibilityNodeInfo parent =(AccessibilityNodeInfo)findAccessibilityNodeInfosByViewId.get(0);
//如果所需数据在视图层次结构中很深,您也可以遍历列表。
String requiredText = parent.getText()。toString();
Log.i(必填文本,requiredText);
}
}

如果您正在其他应用上构建内容并且不知道知道res id。您必须使用父,子计数,找到数据的级别,事件类型的组合来构建逻辑。您必须在事件或来源中查找模式或上述所述值的组合以获得所需的数据。此外,您必须在代码中设置一些调整,以根据您的任务获得准确的数据。就像在我们的任务中一样,我们有一些正则表达式来获取宝贵的数据。



你必须注意如果视图或UI被更改或者res更改了你当前的逻辑可能失败。因此,您必须密切关注构建服务的应用程序。下面是一些示例代码,我们在其中获取没有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 +);
}

获取子计数

  source.getChildCount(); 

如果子计数> 0,您可能需要查看它。



示例代码1

  if(level == 0& & source.getClassName()。equals(android.widget.TextView)&& source.getText()!= null&&!source.getText()。toString()。isEmpty()){ 
//这里的级别是for循环的迭代
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(对于您预期的事件包的应用程序名称)){
if(event.getEventType()== AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED&&使用包名称完成活动类的名称(如果你想要某个特定的屏幕)。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()。g etParent()。getParent()!= null&& 。source.getParent()的getParent()的getParent()的getParent()getClassName()等于( android.widget.FrameLayout)&安培;。&安培; source.getParent()。getParent()。getParent()。getParent()。getParent()== null){
return source.getText()。toString();
}
}

这有点笨拙但要让它运转你有深入了解日志,找到一种模式,可以将您带到所需的数据。



更新20/11/2017
谷歌正在暂停使用辅助功能服务的所有应用程序,以用于辅助功能之外我收到了一封关于我的应用程序的电子邮件,其他开发者也收到了来自谷歌的同一封电子邮件(书签交易)。所以,我认为我们应该寻找其他一些做事方式,我也请你在这里更新它,如果有人提出其他实现来实现相同的行为,它也会帮助其他人。



谢谢
Umesh Chauhan


My last question about the same topic was not clear enough and was put on hold by community and later it was automatically deleted. So, I am explaining that Question in detailed manner so that community can understand and help in a better manner.

I want functionality similar to Voodoo App and MySmartPrice offers.

Now what they do

Step 1: When we open the Voodoo App for the first time they show a small tutorial. At the end of tutorial there is a "Activate Now" button which when pressed take us to Accessibility settings screen.

Step 2: In Accessibility Screen it further guides how to find and unable the Voodoo Service.

Step 3: When we enable it, it further ask to grant "Observe Your Action" and "Retrieve Window Content" permissions.

Step 4: Once we are done granting permissions on accessibility screen, and move to some shopping app or access shopping site via browser and reach product page a voodoo floating button pops up automatically.

Step 5: Once we click on it, it shows the price of same/related/similar products available on other apps or website so that user can check for best deal available.

Reference Screenshot of Voodoo

Now what I want to know form community:

  1. How I can show my help UI over Accessibility screen and product detail page.
  2. How to detect when a product page is there on screen and to evoke my floating button.
  3. How to fetch name of product shown on screen.
  4. How to restrict this screen reading functionality for some apps only? (as I don't want to end up in some copyright issue)
  5. Is there any tutorial which can help me out? Although I had already tried on Google for any direct tutorial and didn't got any success.

Now why I need this information:

I am planning a app for students which will help them to get there desired (or similar) book (ebook) for free if it is available on my server or on some web location which is available web. I want to restrict it the functionality to some apps only due to copyright issues on some books.

Now what I know from my study regarding this topic (but I am not sure whether I am on right track or not)

解决方案

I had tried to summarize how i was able to get thru the problem in a blog post. Anyone who needs some help can take a look into it.

Accessibility Service to the next level

My Previous answer was deleted by moderators may due to i just posted a link to blog. So i am posting my answer again with details here too.

The easiest way is provided by android itself. If you are building something on your own app this is the best and easiest possible way of doing it. You have to use "findAccessibilityNodeInfosByViewId ()" as explained below

@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);
    }
}  

If you are building something on other apps and don’t know the res id. You have to build a logic with the combination of parent, child count, level on which your data is found, type of event. You have to look for a pattern in event or source or the combination of above said values to get the required data preciously. Further, you have to setup some tweak in your code to get the accurate data according to your task. Like in our task we have some regex to get precious data.

You have to take care that if the view or UI is changed or res ids are changed your current logic might fail. So, you have to keep a close look at the app on which you are building your service. Following are some example code in which we are getting data without res id that might be useful for you to understand how it will work.

To print source and event

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

To get the childcount

source.getChildCount();

If child count is >0 you might have to look into it.

Example Code 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;
    }
}

Example Code 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();
        }
}

It is bit clumsy but to get it working you have to look deep into logs to find a pattern which will take you to your required data.

Update 20/11/2017 Google is suspending all apps using accessibility services for things other than accessibility. I had received a email regarding the same for one of my app and other developers are also receiving same email from google (Reddit). So, I think we should look for some other way of doing things and I request you to please update it here also, if some one comes up with other implementation to achieve same behavior it would help others also.

Thanks Umesh Chauhan

这篇关于如何阅读窗口内容(使用accessibilityService)并使用绘制来激活UI而不是Android中的其他应用程序权限?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆