Я узнал, что благодаря использованию accessibilitynodeinfo root node и определения пользовательского узла Функция Traversal, vicoibubibyNodeInfo Узел с Framelayout COMIT CLASS Inside Recyclerview Возвращает ContentScription при вызове. Но я получил null возвращен при использовании метода с помощью единственного пакета доступности .
Однако я должен знать, что после включения Talkback есть некоторые изменения в Содержимое от AcsagebilibyNodeInfo.getContentDescription () , который успешно вернул содержимое пузырьков чата сообщения. S Privilege разрешение делает возможным получить дополнительное содержимое от доступности nodeinfo.getContentDescription () ? Я обнаружил, что при включении Talkback , в настоящее время посещается Framelayout возвращает ContentDescription успешно, поэтому пузырь чата возвращает внутреннее неповрежденное содержимое (например, текст сообщения, динамик и марки времени)
Подробная информация, которую я сделал, похожи на последователи:
android manifest.xml:
Код: Выделить всё
Код: Выделить всё
Код: Выделить всё
package com.example.test1;
import android.accessibilityservice.AccessibilityService;
import android.os.Looper;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.util.Log;
import java.lang.String;
import java.util.List;
import java.util.logging.Handler;
public class MyAccessibilityService extends AccessibilityService {
private void extractChatBubbles(AccessibilityNodeInfo node) {
// base case
if (node == null) return;
CharSequence nodeClassName = node.getClassName();
// TextView
if (nodeClassName != null && nodeClassName.toString().contains("TextView")) {
CharSequence text = node.getText();
if(text == null) {
Log.i("ChatContent", "[Contents] " + node.getContentDescription());
}
if (text != null && text.length() > 0) {
Log.i("ChatContent", "[Name] " + text.toString());
}
}
// RecyclerView
if (node.getClassName().equals("androidx.recyclerview.widget.RecyclerView")) {
Log.d("RecyclerView", "RecyclerView Detected!");
for (int i = 0; i < node.getChildCount(); i++) {
AccessibilityNodeInfo child = node.getChild(i);
Log.d("RecyclerView", "DetectedItem: " + child.getContentDescription() + "/ " + child.toString());
extractChatBubbles(child);
}
}
// FrameLayout
if (node.getChildCount() > 0 && node.getClassName().toString().contains("FrameLayout")) {
Log.i("FrameLayout", "FrameLayout children");
for (int i = 0; i < node.getChildCount(); i++){
if(node.getChild(i) != null) {
Log.i("FrameLayout", node.getChild(i).toString());
} else {
Log.i("FrameLayout", i+"th child is null");
}
}
}
// ViewGroup
if (node.getChildCount() > 0 && node.getClassName().toString().contains("ViewGroup")) {
Log.i("ViewGroup", "ViewGroup children");
for (int i = 0; i < node.getChildCount(); i++){
AccessibilityNodeInfo currentClass = node.getChild(i);
if(node.getChild(i) != null) {
Log.i("ViewGroup", "Class: " + currentClass.getClassName() + ", " + currentClass.getText() + ", " +currentClass.getContentDescription());
if(currentClass.getClassName().toString().contains("ImageView")) {
Log.d("ImageView", currentClass.toString());
}
} else {
Log.i("ViewGroup", i+"th child is null");
}
}
}
// Recursively traverse child nodes
for (int i = 0; i < node.getChildCount(); i++) {
extractChatBubbles(node.getChild(i));
}
}
// For traversing other windows
private void traverseNode(AccessibilityNodeInfo node) {
if (node == null) return;
// print current node text
CharSequence text = node.getText();
if (text != null) {
Log.d("Other Windows", "Text: " + text.toString() + ", Description: " + node.getContentDescription());
}
// Recursively traverse child nodes
for (int i = 0; i < node.getChildCount(); i++) {
AccessibilityNodeInfo childNode = node.getChild(i);
traverseNode(childNode);
}
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
AccessibilityServiceInfo info = this.getServiceInfo();
info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
info.flags |= AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
info.flags |= AccessibilityServiceInfo.DEFAULT;
info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
this.setServiceInfo(info);
}
@Override
public void onInterrupt() {
Log.d("AccessibilityService", "Service Stopped.");
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED ||
event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED ||
event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED ||
event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED ||
event.getEventType() == AccessibilityEvent.TYPE_VIEW_SELECTED ||
event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY) {
// Find out current foreground app is the target chat app
if (event.getPackageName() != null && event.getPackageName().toString().equals("com.target.chat")) {
if(event.getSource() != null) {
Log.i("Accessibility", "Current Event name: " + event.getSource().getClassName());
}
Log.i("Accessibility", "Target Chat app detected! start extracting chat bubbles");
List windows = getWindows();
if(windows.isEmpty()) {
Log.d("WindowsDetect", "No windows found" );
} else {
Log.d("WindowsDetect", windows.size() + " windows detected" );
}
for (AccessibilityWindowInfo window : windows) {
Log.d("WindowsDetect", "current window: " + window.toString());
AccessibilityNodeInfo root = window.getRoot();
if(root == null) {
Log.d("WindowsDetect", "root is null" );
continue;
} else {
Log.d("WindowsDetect", "current root: " + root.toString());
}
traverseNode(root);
}
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
rootNode.performAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Log.i("Accessibility", "Root Node " + rootNode.getClassName() + "'s number of children: " + rootNode.getChildCount());
new android.os.Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
if (rootNode != null) {
extractChatBubbles(rootNode);
} else {
Log.e("RootNode", "rootNode is null");
}
}
}, 2000);
}
}
}
}
< /code>
И то, что я сделал, похоже на это: < /p>
[list]
[*] Пробовал все флаги, предоставленные AscessibilyServiceInfo < /code> ( Вы можете увидеть это на myaccepressibilityservice.onserviceConnected ()
[/list]
< P> P.S.>
Подробнее здесь: https://stackoverflow.com/questions/794 ... rom-access