2017-07-04 107 views
8

我很好奇,前几天我看到这个应用程序允许它打开其他应用程序并自动为您设置某些功能。我已经意识到它必须使用某种屏幕上的点击功能,但我似乎无法找到任何像这样的文档。例如,如果我们知道从其他应用程序屏幕上的文字是“就绪”,有没有办法来阅读这些文字,也许这样做:Android可点击屏幕上的文字

protected void processText(String text) 
{ 
    if (text.contains("Ready")) 
     // click the ready text 
} 
+0

你想点击文字或使文字的一部分可点击,或获得屏幕点击坐标吗?有关前者的信息可以在此处获得:https://www.google.com.ng/url?url=https://stackoverflow.com/questions/10696986/how-to-set-the-part-of-the -text - 视图 - 是 - 点击&RCT = J&SA = U&VED = 0ahUKEwilotjX6-7UAhXIYlAKHfF8BwgQFggbMAA&q =的Android +让+ +文字+的一部分+点击与USG = AFQjCNEVpYcyHrHbO5NKt5jBPVqAjpNiFg –

+0

@财经部,hendyEjegi我想点击的文本,而无需自己做的用户。但由于它在另一个应用程序上,我无法点击它,这正是我想要解决的问题。 – Jayce

+0

检查辅助功能api,所有我可以帮助更多的信息阅读https://stackoverflow.com/questions/35842762/how-to-read-window-content-using-accessibilityservice-and-evoking-ui-using-dra – ingsaurabh

回答

3

我已经使用AccessibilityService完成了这项工作。它只会在API级别> = 16时正常工作。您需要延长AccessibilityService。例如,这个类将获得USSD响应文本并关闭对话框。

// .... 
public class UssdAccessibilityService extends AccessibilityService { 
    public UssdAccessibilityService() { 
    } 

    @TargetApi(16) 
    @Override 
    public void onAccessibilityEvent(AccessibilityEvent event) { 
     if (!"com.android.phone".equalsIgnoreCase((String)event.getPackageName())){ 
      // In this example we are only interested in events comming 
      // from "com.android.phone" package 
      event.recycle(); 
      return; 
     } 

     String className = (String)event.getClassName(); 
     if (className == null || (!className.contains("AlertDialog") && !className.contains("AlertDialog"))){ 
      // Class is not an USSD dialog 
      event.recycle(); 
      return; 
     } 

     AccessibilityNodeInfo source = event.getSource(); 
     if (source == null) { 
      // getSource() is annotated @Nullable, so we do this to be 
      // safe just in case 
      event.recycle(); 
      return; 
     } 

     AccessibilityNodeInfo acceptButton = null; 
     String ussdText = null; 

     int childCount = source.getChildCount(); 
     for (int i = 0; i < childCount; i++){ 
      AccessibilityNodeInfo current = source.getChild(i); 
      if (current == null) 
       continue; 

      String currentText = (String)current.getText(); 
      if (current.isClickable()){ 
       // In the case of USSD dialogs, there is only one clickable. 
       // May be necessary to do more robust search in other scenarios 
       acceptButton = current; 
       continue; 
      } 

      ussdText = currentText; 

      current.recycle(); 
     } 

     if (ussdText!= null) { 
      if (acceptButton != null) 
       acceptButton.performAction(AccessibilityNodeInfo.ACTION_CLICK); 

     } 

     source.recycle(); 
     event.recycle(); 
    } 

    // .... 
} 

您必须<application>

<service 
     android:name=".UssdAccessibilityService" 
     android:enabled="true" 
     android:label="Read USSD codes and dismiss" 
     android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> 
     <intent-filter> 
      <action android:name="android.accessibilityservice.AccessibilityService" /> 
     </intent-filter> 

     <meta-data 
      android:name="android.accessibilityservice" 
      android:resource="@xml/accessibility_service_config" /> 
</service> 

下申报清单中的辅助服务在res/xml创建accessibility_service_config.xml

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" 
    android:description="@string/accessibility_service_description" 
    android:packageNames="com.android.phone,com.ats.android.activationcodebot" 
    android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged" 
    android:accessibilityFlags="flagDefault" 
    android:accessibilityFeedbackType="feedbackSpoken" 
    android:notificationTimeout="100" 
    android:canRetrieveWindowContent="true" 
    /> 

当然你有这个代码适应自己的需要。

最后,您必须在Android上手动启用无障碍服务设置>辅助功能(或要求用户这样做)。

阅读全文...Developing an Accessibility Service

+0

我会尽快尝试,只要我今天回家,并让你知道它是否适合我。它与我已有的代码类似,但由于某些原因,我的代码并不总是“点击”屏幕。 – Jayce

+0

我还没有看到你的代码,但一定要遍历整个树,寻找你想要的可点击的视图。 –

+0

此外,请确保不要在'onAccessibilityEvent()'内部使用任何实例或类字段进行临时存储,因为这会使线程不安全。如果您确实需要使用实例字段,请使用'synchronized(lockObject){}'以确保对'onAccessibilityEvent()'的所有调用都能够严格执行。 –

3

为了能够做到这一点从其他应用程序,你需要捕获屏幕并使用文本识别服务确定文本位置。

当另一个应用程序处于活动状态时,则应用程序应处于活动状态才能捕获屏幕。所以你只能使用总是起作用背景的android服务。

但是捕捉截图为您的活动,你必须需要你activity的视图,哪一个是不存在于你的service,所以你必须做出TimerTask将打电话给你的活动在每一个小时,你的activity响应它以当前出现的视图,您可以从中捕获ScreenShot。

,或者如果你想利用你的当前设备屏幕的截图(任何应用程序),那么你有root权限,读framebuffer对于这将给当前画面的原始数据,然后将其转换为位图或任何图片文件,你可以在你的服务中做到这一点。

简而言之,它可能有根电话。否则,如果您没有植根,则无法截取其他应用程序的屏幕截图。只允许截取你的应用程序的屏幕截图。

为了能够分析屏幕是否存在任何“就绪”文本。您的应用程序应该是生活/活动的,以便能够捕捉屏幕。

+0

我正在使用AccessibilityNodeInfo,我相信现在可以使用它了,无需root。只需要搞清楚一些调整,我应该走在正确的轨道上。 – Jayce

0

而不是尝试阅读文本使用广播接收器,并在每次广播检查textviews长度设置时,启动应用程序或做任何你想做的事情。

+0

你有一个例子吗? – Jayce