我对同一个主题的last问题不太清楚,被社区搁置,后来被自动删除。因此,我在详细解释该问题,以便社区可以更好地理解和帮助。
我想要类似于Voodoo App和MySmartPrice提供的功能。
现在他们做什么
步骤1:当我们第一次打开Voodoo App时,它们会显示一个小教程。在教程的最后,有一个“立即激活”按钮,按下该按钮会将我们带到“辅助功能设置”屏幕。
步骤2:在“辅助功能”屏幕中,它进一步指导如何查找和禁用Voodoo服务。
步骤3:当我们启用它时,它进一步要求授予“观察您的操作”和“检索窗口内容”权限。
步骤4:一旦完成授予辅助功能屏幕上的权限,然后移至某个购物应用程序或通过浏览器访问购物网站并到达产品页面,便会自动弹出一个voodoo float 按钮。
步骤5:单击我们后,它会显示其他应用程序或网站上可用的相同/相关/相似产品的价格,以便用户可以查看可用的最优惠价格。
Voodoo引用屏幕截图
现在我想了解社区形式:
现在为什么我需要此信息:
我正在为学生设计一个应用程序,如果该应用程序在我的服务器上或可在网上找到的某些网站上可用,则将免费帮助他们到达所需的(或类似的)书(电子书)。我仅出于某些书籍的版权问题,才希望将其功能限制为某些应用程序。
现在,我从研究中了解到的与此主题相关的信息(但我不确定自己是否步入正轨)
最佳答案
我试图在博客文章中总结如何解决这个问题。任何需要帮助的人都可以查看一下。
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);
}
}
如果您要在其他应用程序上构建内容,并且不知道res ID。您必须结合父级,子级计数,找到数据的级别,事件类型来构建逻辑。您必须寻找事件或源中的模式或上述值的组合,以宝贵地获取所需的数据。此外,您必须在代码中进行一些调整以根据您的任务获取准确的数据。就像在我们的任务中一样,我们有一些正则表达式来获取宝贵的数据。
您必须注意,如果更改了 View 或UI或更改了res 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() + "");
}
获得 child 数
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
Google将使用无障碍服务暂停所有应用程序,以解决无障碍功能。我收到了一封有关同一应用程序的电子邮件,其他开发人员也收到了来自Google(Reddit)的相同电子邮件。因此,我认为我们应该寻找其他的处理方式,并且请您在此处进行更新,如果某些人提出了其他实现相同行为的方法,也会对其他人有所帮助。
谢谢
乌梅什·乔汉(Umesh Chauhan)
关于java - 如何在Android中使用其他应用程序权限读取窗口内容(使用accessibilityService)并调用UI?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35842762/