2014-10-29 3 views
5

Ich möchte klicken Sie auf Schaltfläche in Android-Einstellungen mit AccessibilityService wie greenify tat, aber ich kann die spezifische Schaltfläche nicht finden. Bitte hilf mir.Wie klicken Sie in Einstellungen mit AccessibilityService Schaltfläche?

MyAccessibilityService .java-:

public class MyAccessibilityService extends AccessibilityService { 

    private static final String TAG = MyAccessibilityService.class 
      .getSimpleName(); 

    @Override 
    public void onAccessibilityEvent(AccessibilityEvent event) { 
     Log.i(TAG, "ACC::onAccessibilityEvent: " + event.getEventType()); 

     //TYPE_WINDOW_STATE_CHANGED = 32, 
     if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) { 
      AccessibilityNodeInfo nodeInfo = event.getSource(); 
      Log.i(TAG, "ACC::onAccessibilityEvent: nodeInfo=" + nodeInfo.getText()); 

      List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.android.settings:id/left_button"); 
      for (AccessibilityNodeInfo node : list) { 
       Log.i(TAG, "ACC::onAccessibilityEvent: " + event.getEventType() 
         + " " + node); 
      } 

EDIT:

Nur wenn Typ TYPE_WINDOW_STATE_CHANGED ist, kann ich das nodeinfo Objekt erhalten.

+1

Ist Ihr Service Ereignisse empfangen? Gibt getSource() Nicht-Null-Werte zurück? Warum versuchen Sie Click- und Scroll-Aktionen für die Quelle des geänderten Ereignisses im Fensterstatus auszuführen (was immer die Stammansicht des Fensters ist)? – alanv

+0

Ich entfernte etwas verwirrenden Code (führen Sie klicken und scrollen) :) – thecr0w

+1

Sind Sie sicher, dass es tatsächlich eine Ansicht mit dieser ID? Die Zeichenfolge "force_stop_button" wird nirgendwo im Android-Quellcode angezeigt. – alanv

Antwort

12

öffnen Sie eine App AppInfo mit enger Kraft Taste Test aktiviert:

public class MyAccessibilityService extends AccessibilityService { 
    private static final String TAG = MyAccessibilityService.class 
      .getSimpleName(); 

    @Override 
    public void onAccessibilityEvent(AccessibilityEvent event) { 
     Log.i(TAG, "ACC::onAccessibilityEvent: " + event.getEventType()); 

     //TYPE_WINDOW_STATE_CHANGED == 32 
     if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event 
       .getEventType()) { 
      AccessibilityNodeInfo nodeInfo = event.getSource(); 
      Log.i(TAG, "ACC::onAccessibilityEvent: nodeInfo=" + nodeInfo); 
      if (nodeInfo == null) { 
       return; 
      } 

      List<AccessibilityNodeInfo> list = nodeInfo 
        .findAccessibilityNodeInfosByViewId("com.android.settings:id/left_button"); 
      for (AccessibilityNodeInfo node : list) { 
       Log.i(TAG, "ACC::onAccessibilityEvent: left_button " + node); 
       node.performAction(AccessibilityNodeInfo.ACTION_CLICK); 
      } 

      list = nodeInfo 
        .findAccessibilityNodeInfosByViewId("android:id/button1"); 
      for (AccessibilityNodeInfo node : list) { 
       Log.i(TAG, "ACC::onAccessibilityEvent: button1 " + node); 
       node.performAction(AccessibilityNodeInfo.ACTION_CLICK); 
      } 
     } 

    } 

    @Override 
    public void onServiceConnected() { 
     Log.i(TAG, "ACC::onServiceConnected: "); 
    } 

    @Override 
    public void onInterrupt() { 
     // TODO Auto-generated method stub 

    } 
} 
+0

Es sollte beachtet werden, dass dies nur auf API-Level 14+ funktioniert. Und was ist mit Recycling? Gemäß der Dokumentation sollten Sie sowohl Ereignisse als auch Knotenobjekte recyceln. – Stan

+0

recycling? Danke für Ihre Erinnerung, ich werde mich darum kümmern. – thecr0w

+1

findAccessibilityNodeInfosByViewId ist für API 18+ verfügbar. Die Verwendung von findAccessibilityNodeInfosByText ist etwas kompliziert, da sich der Text je nach Gebietsschema ändern kann. Irgendeine Idee, wie man dieses Problem löst? –

2

Die gewählte Antwort arbeitet auf API 18 und oben, da sie auf findAccessibilityNodeInfosByViewId Relais, die in API hinzugefügt wurden 18. ich das Schreiben endete Klasse zur Unterstützung von API 17 und darunter.

ResourcesCompat Klasse findet die mit der angegebenen Aktivität identifizierten Ressourcen, die in unserem Fall die Einstellungsaktivität von Android sein sollten. Sie können die Aktivität Komponentenname der Einstellungen abrufen, indem Sie diese Funktion aufrufen, wenn Sie das Accessibility-Ereignis in Ihrem Eingabehilfedienst verarbeiten.

public static ComponentName getForegroundActivity(Context context) { 
     ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
     List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1); 
     ComponentName topActivity = taskInfo.get(0).topActivity; 
     return topActivity; 
    } 

Ein guter Platz init(...) zu nennen, ist in onAccessibilityEvent wenn Sie zuerst das TYPE_WINDOW_STATE_CHANGED Ereignisse als thecr0w beschriebene Handhabung sind.

public class ResourcesCompat { 
    private final static String RESOURCE_TYPE = "string"; 

    private String mResourcesPackageName; 
    private Resources mResources; 

    /** 
    * Find the resource file for a specific activity 
    * 
    * @param context 
    * @param settingsPackageName 
    * @param settingsClassName 
    */ 
    public void init(Context context, String settingsPackageName, String settingsClassName) { 
     try { 
      mResourcesPackageName = settingsPackageName; 
      ComponentName settingsComponentName = new ComponentName(settingsPackageName, settingsPackageName + settingsClassName); 
      mResources = context.getPackageManager().getResourcesForActivity(settingsComponentName); 
     } catch (PackageManager.NameNotFoundException e) { 
     } 
    } 

    /** 
    * Return the localised string for the given resource name. 
    * @param resourceName The name of the resource definition in strings.xml 
    */ 
    public String getString(String resourceName) { 
     int resourceId = getIdentifier(resourceName); 
     return resourceId > 0 ? mResources.getString(resourceId) : null; 
    } 

    /** 
    * Return a resource identifier for the given resource name. 
    * @param resourceName The name of the desired resource. 
    * @return int The associated resource identifier. Returns 0 if no such resource was found. (0 is not a valid resource ID.) 
    */ 
    private int getIdentifier(String resourceName) { 
     return mResources.getIdentifier(resourceName, RESOURCE_TYPE, mResourcesPackageName); 
    } 
} 

Einige Hersteller wie um Klassen zu bewegen und Standard-Strings (Husten Samsung Husten Xiomi Husten) So stellen Sie sicher, dass Sie decken alle Fälle und behandeln Fehler und Ausnahmen umbenennen.

Schließlich finden Sie Ihre Ansicht mit Namen. Hier kann id 'force_stop' zum Beispiel

private List<AccessibilityNodeInfo> findAccessibilityNodeInfosByName(AccessibilityNodeInfo source, String id) { 
     String nodeText = mResourcesCompat.getString(id); 
     if (nodeText != null) { 
      return source.findAccessibilityNodeInfosByText(nodeText); 
     } 

     return null; 
} 
+0

'findAccessibilityNodeInfosByViewId' kann durch' AccessibilityNodeInfoCompat.wrap (getRootInActiveWindow()). FindAccessibilityNodeInfosByViewId' für ältere Ziele ersetzt werden –

Verwandte Themen