@Chesterfield25

Почему неправильно работает сервис?

У меня приложение которое работает с accessibilityservice. Задача его такая, вводится имя и нажимается поиск, далее открывается тикток и происходит поиск по имени. Проблема в том что если старт свайпа происходит
в
@Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
            // Проверяем содержимое окна
            AccessibilityNodeInfo rootNode = getRootInActiveWindow();
            if (rootNode != null) {
                // Сканируем содержимое для поиска имени и скроллинга
                scanForTargetName(rootNode);
            }

            // Запускаем свайп только при изменении содержимого окна
            startSwiping();
        }
    }

то происходит очень быстрое перелистывание видео но имя находит корректно. А если старт свайпа
в
@Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Log.d(TAG, "AccessibilityService активен");
        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED | AccessibilityEvent.TYPE_VIEW_SCROLLED;
        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
        info.packageNames = new String[]{"com.ss.android.ugc.trill", "com.zhiliaoapp.musically"};  // TikTok пакеты
        info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS | AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
        setServiceInfo(info);

        // Читаем имя для поиска из SharedPreferences
        SharedPreferences sharedPreferences = getSharedPreferences("TikTokSearchPrefs", MODE_PRIVATE);
        targetName = sharedPreferences.getString("TARGET_NAME", "");
        Log.d(TAG, "Сервис подключен. Ищем имя: " + targetName);
        // Запускаем свайп только при изменении содержимого окна
        startSwiping();
    }

то свайпы происходят корректно по времени но имя не находит.
Как исправить что бы всё работало корректно?

Полный код
public class MyAccessibilityService extends AccessibilityService {

    private static final String TAG = "MyAccessibilityService";
    private String targetName;

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
            // Проверяем содержимое окна
            AccessibilityNodeInfo rootNode = getRootInActiveWindow();
            if (rootNode != null) {
                // Сканируем содержимое для поиска имени и скроллинга
                scanForTargetName(rootNode);
            }

            // Запускаем свайп только при изменении содержимого окна
            startSwiping();
        }
    }

    private void performSwipeGesture() {
        Path path = new Path();

        // Получаем размеры экрана
        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        if (windowManager != null) {
            windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        }
        int screenWidth = displayMetrics.widthPixels;
        int screenHeight = displayMetrics.heightPixels;

        // Определяем начальные и конечные точки свайпа
        path.moveTo(screenWidth / 2, screenHeight * 0.9f);  // Начальная точка свайпа (внизу экрана)
        path.lineTo(screenWidth / 2, screenHeight * 0.1f);  // Конечная точка свайпа (вверху экрана)

        GestureDescription.StrokeDescription strokeDescription = new GestureDescription.StrokeDescription(path, 0, 3000);

        GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
        gestureBuilder.addStroke(strokeDescription);

        dispatchGesture(gestureBuilder.build(), new GestureResultCallback() {
            @Override
            public void onCompleted(GestureDescription gestureDescription) {
                super.onCompleted(gestureDescription);
                Log.d(TAG, "Свайп выполнен успешно");
            }

            @Override
            public void onCancelled(GestureDescription gestureDescription) {
                super.onCancelled(gestureDescription);
                Log.d(TAG, "Свайп отменён");
            }
        }, null);
    }

    // Запускаем свайп с задержкой (например, каждые 5 секунд)
    private void startSwiping() {
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                performSwipeGesture();
                handler.postDelayed(this, 10000);  // Повторяем каждые 5 секунд
            }
        }, 10000);
    }

    // Поиск целевого имени в содержимом окна
    private void scanForTargetName(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo == null) return;

        // Получаем текст из элемента
        CharSequence text = nodeInfo.getText();
        if (text != null && text.toString().toLowerCase().contains(targetName.toLowerCase())) {
            Log.d(TAG, "Имя найдено: " + text.toString());
            sendNotification("Найдено видео с именем: " + targetName);
        }

        // Рекурсивно обходим дочерние элементы
        for (int i = 0; i < nodeInfo.getChildCount(); i++) {
            scanForTargetName(nodeInfo.getChild(i));
        }
    }

    private void sendNotification(String message) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "channel_id")
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setContentTitle("TikTok Search")
                .setContentText(message)
                .setPriority(NotificationCompat.PRIORITY_HIGH);

        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        notificationManager.notify(1, builder.build());
    }

    @Override
    public void onInterrupt() {
        // Обработчик прерываний сервиса
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Log.d(TAG, "AccessibilityService активен");
        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED | AccessibilityEvent.TYPE_VIEW_SCROLLED;
        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
        info.packageNames = new String[]{"com.ss.android.ugc.trill", "com.zhiliaoapp.musically"};  // TikTok пакеты
        info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS | AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
        setServiceInfo(info);

        // Читаем имя для поиска из SharedPreferences
        SharedPreferences sharedPreferences = getSharedPreferences("TikTokSearchPrefs", MODE_PRIVATE);
        targetName = sharedPreferences.getString("TARGET_NAME", "");
        Log.d(TAG, "Сервис подключен. Ищем имя: " + targetName);
    }
}
  • Вопрос задан
  • 106 просмотров
Пригласить эксперта
Ответы на вопрос 1
grantur5707
@grantur5707
Full Stack Web Developer
Разделите логику запуска свайпа и поиск имени, чтобы они синхронизировались правильно. Попробуйте запускать свайп только после того, как будет выполнен поиск имени и произойдёт событие изменения содержимого окна.

Вот пример:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        if (rootNode != null) {
            if (scanForTargetName(rootNode)) {
                stopSwiping();
                return;
            }
        }

        startSwiping();
    }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы