Почему постоянно переходит только в первую группу?

Рейтинг: 0Ответов: 0Опубликовано: 30.07.2025

Пытаюсь создать постер в фейсбуке, но столкнулся с проблемой что постоянно переходит в первую группу и публикует только в ней

package com.arturio.facebookautoposter;

import android.accessibilityservice.AccessibilityService;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import java.util.*;

/**
 * AccessibilityService для автоматизації дій у Facebook-групах:
 * пошук → вибір групи → відкриття поля посту → вставка тексту.
 */
public class AutomationService extends AccessibilityService {

    public static String queryText = "";
    public static String postText = "";

    private static final String TAG = "FBPoster";

    public static boolean searchIconClicked;
    public static boolean textInserted;
    private boolean groupsTabClicked = false;
    private boolean imageClicked = false;
    private boolean postFieldClicked = false;
    private int currentGroupIndex = 0;
    private List<AccessibilityNodeInfo> groupImages = new ArrayList<>();
    private boolean isPostingInProgress = false;

    private final Handler handler = new Handler(Looper.getMainLooper());
    private int postTextCheckAttempts = 0;
    private static final int MAX_ATTEMPTS = 10;

    private final Set<String> postFieldHints = new HashSet<>(Arrays.asList(
            "Напишите что-нибудь", "Напишіть щось",
            "Create a public post", "What's on your mind",
            "Опубликовать как Анонимный участник"
    ));

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        final AccessibilityNodeInfo root = getRootInActiveWindow();
        if (root == null) return;

        if (!searchIconClicked) {
            if (clickSearchIcon(root)) {
                searchIconClicked = true;
                Log.d(TAG, "🔍 Клік по іконці пошуку");
            }
            return;
        }

        if (searchIconClicked && !textInserted) {
            AccessibilityNodeInfo input = findFirstEditable(root);
            if (input != null) {
                pasteTextFromClipboard(input, queryText);
                textInserted = true;
                Log.d(TAG, "🔤 Вставлено текст: " + queryText);
            }
            return;
        }

        if (textInserted && !groupsTabClicked) {
            if (clickGroupsTab(root)) {
                groupsTabClicked = true;
                Log.d(TAG, "📁 Клік по вкладці 'Групи'");
            }
            return;
        }

        if (groupsTabClicked && groupImages.isEmpty()) {
            groupImages = findAllGroupImages(root);
            if (groupImages.isEmpty()) {
                showToast("⚠️ Не знайдено жодної групи");
                Log.d(TAG, "⚠️ Не знайдено жодної групи");
                return;
            }
            Log.d(TAG, "🔢 Знайдено груп: " + groupImages.size());
        }

        if (groupsTabClicked && !imageClicked && !isPostingInProgress && !groupImages.isEmpty()) {
            if (currentGroupIndex >= groupImages.size()) {
                showToast("✅ Усі групи пройдено");
                Log.d(TAG, "✅ Усі групи пройдено");
                return;
            }

            Log.d(TAG, "clickNextGroup currentGroupIndex = " + currentGroupIndex + ", total groups = " + groupImages.size());
            clickNextGroup();
            return;
        }


        if (imageClicked && !postFieldClicked && !isPostingInProgress) {
            postFieldClicked = true;
            isPostingInProgress = true;
            checkForPostField();
        }
    }

    private boolean clickSearchIcon(AccessibilityNodeInfo root) {
        List<AccessibilityNodeInfo> icons = new ArrayList<>();
        icons.addAll(root.findAccessibilityNodeInfosByText("Поиск"));
        icons.addAll(root.findAccessibilityNodeInfosByText("Search"));
        for (AccessibilityNodeInfo node : icons) {
            if (node.isClickable()) {
                node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                return true;
            }
        }
        return false;
    }

    private boolean clickGroupsTab(AccessibilityNodeInfo root) {
        List<AccessibilityNodeInfo> tabs = new ArrayList<>();
        tabs.addAll(root.findAccessibilityNodeInfosByText("Группы"));
        tabs.addAll(root.findAccessibilityNodeInfosByText("Групи"));
        tabs.addAll(root.findAccessibilityNodeInfosByText("Groups"));
        for (AccessibilityNodeInfo tab : tabs) {
            if (tab.isClickable()) {
                tab.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                return true;
            }
        }
        return false;
    }

    private AccessibilityNodeInfo findFirstEditable(AccessibilityNodeInfo root) {
        if (root == null) return null;
        if ("android.widget.EditText".contentEquals(root.getClassName())) return root;

        for (int i = 0; i < root.getChildCount(); i++) {
            AccessibilityNodeInfo res = findFirstEditable(root.getChild(i));
            if (res != null) return res;
        }
        return null;
    }

    private void pasteTextFromClipboard(AccessibilityNodeInfo node, String text) {
        ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
        ClipData clip = ClipData.newPlainText("label", text);
        clipboard.setPrimaryClip(clip);

        if (node == null) return;

        node.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
        node.performAction(AccessibilityNodeInfo.ACTION_PASTE);

        showToast("📋 Вставлено через буфер обміну");
    }

    private List<AccessibilityNodeInfo> findAllGroupImages(AccessibilityNodeInfo root) {
        List<AccessibilityNodeInfo> results = new ArrayList<>();
        findAllImagesRecursive(root, results);
        return results;
    }

    private void findAllImagesRecursive(AccessibilityNodeInfo node, List<AccessibilityNodeInfo> list) {
        if (node == null) return;

        if ("android.widget.ImageView".contentEquals(node.getClassName()) && node.isVisibleToUser()) {
            if (isInsideTargetContainer(node, "android.view.ViewGroup")) {
                list.add(node);
            }
        }

        for (int i = 0; i < node.getChildCount(); i++) {
            findAllImagesRecursive(node.getChild(i), list);
        }
    }

    private boolean clickGroupContainer(AccessibilityNodeInfo node) {
        if (node == null) return false;

        AccessibilityNodeInfo current = node;
        while (current != null) {
            if (current.isClickable()) {
                Log.d(TAG, "Клікаємо по клікабельному вузлу: " + current.getClassName() +
                        ", desc=" + current.getContentDescription());
                boolean clicked = current.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                if (clicked) return true;
                else Log.w(TAG, "Спроба клікнути не вдалася");
            }
            current = current.getParent();
        }

        Log.w(TAG, "Не знайдено клікабельний батьківський вузол для кліку");
        return false;
    }

    private boolean isInsideTargetContainer(AccessibilityNodeInfo node, String containerClassName) {
        AccessibilityNodeInfo parent = node.getParent();
        while (parent != null) {
            if (containerClassName.equals(parent.getClassName())) {
                return true;
            }
            parent = parent.getParent();
        }
        return false;
    }

    private void clickNextGroup() {
        if (currentGroupIndex >= groupImages.size()) {
            showToast("✅ Усі групи пройдено");
            Log.d(TAG, "✅ Усі групи пройдено");
            return;
        }

        AccessibilityNodeInfo groupImage = groupImages.get(currentGroupIndex);
        boolean clicked = clickGroupContainer(groupImage);

        if (clicked) {
            imageClicked = true;
            showToast("✅ Клік по групі #" + (currentGroupIndex + 1));
            Log.d(TAG, "✅ Клік по групі #" + (currentGroupIndex + 1));

            // Збільшуємо індекс після успішного кліку
            currentGroupIndex++;
        } else {
            Log.w(TAG, "Не вдалося клікнути по групі #" + (currentGroupIndex + 1));
            currentGroupIndex++;
            clickNextGroup();
        }
    }

    private void checkForPostField() {
        postTextCheckAttempts++;
        Log.d(TAG, "🔁 Спроба #" + postTextCheckAttempts);
        showToast("🔁 Спроба #" + postTextCheckAttempts);

        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        if (rootNode == null) return;

        AccessibilityNodeInfo postFieldNode = findNodeWithTextHintRecursive(rootNode, postFieldHints);
        if (postFieldNode != null) {
            clickNodeOrParent(postFieldNode);
            Log.d(TAG, "✅ Знайдено поле для публікації!");
            showToast("✅ Знайдено поле для публікації!");

            handler.postDelayed(this::waitForEditorAndInsertPostText, 1500);
            postTextCheckAttempts = 0;
        } else {
            if (postTextCheckAttempts >= MAX_ATTEMPTS) {
                Log.d(TAG, "⛔ Не знайдено поле для публікації після " + MAX_ATTEMPTS + " спроб");
                showToast("⛔ Не знайдено поле для публікації після " + MAX_ATTEMPTS + " спроб");
                postTextCheckAttempts = 0;
            } else {
                handler.postDelayed(this::checkForPostField, 1500);
            }
        }
    }

    private void waitForEditorAndInsertPostText() {
        AccessibilityNodeInfo root = getRootInActiveWindow();
        if (root == null) {
            handler.postDelayed(this::waitForEditorAndInsertPostText, 1000);
            return;
        }

        AccessibilityNodeInfo editTextNode = findFirstEditable(root);
        if (editTextNode != null) {
            if (editTextNode.isClickable()) {
                editTextNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            } else {
                AccessibilityNodeInfo parent = editTextNode.getParent();
                while (parent != null && !parent.isClickable()) {
                    parent = parent.getParent();
                }
                if (parent != null) {
                    parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                }
            }

            handler.postDelayed(() -> {
                pasteTextFromClipboard(editTextNode, postText);
                Log.d(TAG, "✅ Вставлено postText: " + postText);
                showToast("✅ Вставлено текст для публікації");

                handler.postDelayed(this::clickPublishButton, 1500);
            }, 1000);

        } else {
            handler.postDelayed(this::waitForEditorAndInsertPostText, 1000);
        }
    }

    private AccessibilityNodeInfo findNodeWithTextHintRecursive(AccessibilityNodeInfo node, Set<String> targets) {
        if (node == null) return null;

        List<CharSequence> fields = Arrays.asList(
                node.getText(),
                node.getContentDescription(),
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? node.getHintText() : null
        );

        for (CharSequence field : fields) {
            if (field != null) {
                for (String target : targets) {
                    if (field.toString().contains(target)) return node;
                }
            }
        }

        for (int i = 0; i < node.getChildCount(); i++) {
            AccessibilityNodeInfo result = findNodeWithTextHintRecursive(node.getChild(i), targets);
            if (result != null) return result;
        }

        return null;
    }

    private void clickNodeOrParent(AccessibilityNodeInfo node) {
        AccessibilityNodeInfo clickableNode = node;
        while (clickableNode != null && !clickableNode.isClickable()) {
            clickableNode = clickableNode.getParent();
        }

        if (clickableNode != null) {
            clickableNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        } else {
            Log.d(TAG, "⚠️ Не знайдено клікабельний батьківський вузол");
            showToast("⚠️ Не знайдено клікабельний батьківський вузол");
        }
    }

    private void clickPublishButton() {
        AccessibilityNodeInfo root = getRootInActiveWindow();
        if (root == null) return;

        List<String> publishTexts = Arrays.asList("ОПУБЛИКОВАТЬ", "Опублікувати", "Post");
        List<AccessibilityNodeInfo> candidates = new ArrayList<>();

        for (String text : publishTexts) {
            candidates.addAll(root.findAccessibilityNodeInfosByText(text));
        }

        for (AccessibilityNodeInfo node : candidates) {
            if (node != null && node.isVisibleToUser()) {
                AccessibilityNodeInfo clickable = node;
                while (clickable != null && !clickable.isClickable()) {
                    clickable = clickable.getParent();
                }

                if (clickable != null && clickable.performAction(AccessibilityNodeInfo.ACTION_CLICK)) {
                    Log.d(TAG, "✅ Натиснуто кнопку: " + (node.getText() != null ? node.getText() : "без тексту"));
                    showToast("✅ Натиснуто кнопку: " + (node.getText() != null ? node.getText() : "без тексту"));

                    handler.postDelayed(this::returnToGroupList, 3000);
                    return;
                }
            }
        }

        Log.w(TAG, "⛔ Кнопку 'ОПУБЛИКОВАТЬ' не знайдено");
        showToast("⛔ Кнопку 'ОПУБЛИКОВАТЬ' не знайдено");
    }

    private void returnToGroupList() {
        handler.postDelayed(() -> {
            performGlobalAction(GLOBAL_ACTION_BACK);
            resetStateAndContinue();
        }, 2000);
    }

    private void resetStateAndContinue() {
        handler.postDelayed(() -> {
            AccessibilityNodeInfo root = getRootInActiveWindow();
            if (root == null) {
                showToast("⚠️ Не вдалося оновити інтерфейс");
                return;
            }

            imageClicked = false;
            postFieldClicked = false;
            isPostingInProgress = false;
            postTextCheckAttempts = 0;

            // НЕ оновлюємо groupImages тут!
            Log.d(TAG, "Поточний індекс групи: " + currentGroupIndex + " з " + groupImages.size());

            if (currentGroupIndex >= groupImages.size()) {
                showToast("✅ Усі групи пройдено");
                Log.d(TAG, "✅ Усі групи пройдено");
                return;
            }

            clickNextGroup();
        }, 3000);
    }


    private void showToast(String text) {
        handler.post(() -> Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onInterrupt() {
        Log.d(TAG, "⛔ Сервіс перервано");
    }
}

Ответы

Ответов пока нет.