Мобильная разработка

Исправление ошибки 'Untrusted touch due to occlusion' в Android оверлеях

Пошаговое руководство по исправлению ошибки 'Untrusted touch due to occlusion' при создании полупрозрачных оверлеев в Android приложениях. Настройка WindowManager.LayoutParams и обработка касаний.

3 ответа 2 просмотра

Как исправить ошибку ‘Untrusted touch due to occlusion’ при создании оверлея в Android приложении? Какие параметры WindowManager.LayoutParams необходимо настроить для корректной обработки касаний при наличии полупрозрачного слоя (например, фильтра синего света), чтобы можно было взаимодействовать с элементами интерфейса под ним, и почему возникает эта ошибка на новых версиях Android (особенно на устройствах Samsung)?

Ошибка ‘Untrusted touch due to occlusion’ в Android возникает при создании полупрозрачных оверлеев, таких как фильтры синего света, когда система не может доверительно обработать касания через прозрачные слои. Для исправления проблемы нужно правильно настроить WindowManager.LayoutParams с флагами FLAG_NOT_TOUCH_MODAL, FLAG_WATCH_OUTSIDE_TOUCH и FLAG_NOT_FOCUSABLE, а также учесть особенности новых версий Android, особенно на устройствах Samsung, где существуют дополнительные ограничения для оверлеев.


Содержание


Что такое ошибка “Untrusted touch due to occlusion”

Ошибка ‘Untrusted touch due to occlusion’ возникает, когда Android система не может корректно обработать касания пользователя, проходящие через полупрозрачный оверлей к элементам интерфейса под ним. Эта ошибка буквально означает “недоверительное касание из-за перекрытия” и связана с механизмами безопасности Android, которые предотвращают случайное взаимодействие с элементами управления через прозрачные слои.

На практике это выглядит так: вы создаете плавающее окно с фильтром синего света, но не можете нажать кнопки или вводить текст под оверлеем. Система блокирует эти касания как потенциально небезопасные, поскольку не может гарантировать, что пользователь действительно хочет взаимодействовать с конкретным элементом управления под оверлеем. Особенно актуально это для фильтров синего света и других полупрозрачных оверлеев, которые часто используются для защиты глаз или улучшения читаемости текста.


Причины возникновения на новых версиях Android и устройствах Samsung

Эта проблема усугубилась в последних версиях Android из-за ужесточения политики безопасности и изменений в механизме обработки касаний. Основные причины:

1. Изменения в политике безопасности Android:

  • Начиная с Android 10, система стала более строго проверять доверенные касания
  • Механизм occlusion detection теперь активен по умолчанию для всех оверлеев
  • Система требует явного разрешения для обработки касаний через прозрачные слои

2. Специфика устройств Samsung:

  • Samsung реализует собственный механизм обработки оверлеев
  • На устройствах Samsung Galaxy существуют дополнительные ограничения для полупрозрачных окон
  • Часто требуется специальный флаг PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY
  • Могут быть активны собственные оптимизации производительности, влияющие на обработку касаний

3. Конфликт фокуса и касаний:

  • Оверлей, перехватывающий все касания (touch modal), блокирует взаимодействие с элементами под ним
  • Новые версии Android требуют явного указания, что окно не должно перехватывать все касания
  • Система интерпретирует отсутствие правильных флагов как потенциальную угрозу безопасности

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


Настройка WindowManager.LayoutParams для корректной обработки касаний

Для исправления ошибки ‘Untrusted touch due to occlusion’ необходимо правильно настроить параметры WindowManager.LayoutParams. Ключевые флаги, которые нужно установить:

java
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
 WindowManager.LayoutParams.MATCH_PARENT,
 WindowManager.LayoutParams.MATCH_PARENT,
 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
 WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | 
 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | 
 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
 PixelFormat.TRANSLUCENT
);

Обязательные флаги:

  • FLAG_NOT_TOUCH_MODAL - позволяет окну не перехватывать все касания, только те, что находятся в его области
  • FLAG_WATCH_OUTSIDE_TOUCH - включает отслеживание касаний вне области оверлея
  • FLAG_NOT_FOCUSABLE - предотвращает захват фокуса ввода, что важно для взаимодействия с элементами под оверлеем

Дополнительные параметры для полупрозрачных оверлеев:

  • TYPE_APPLICATION_OVERLAY - тип оверлея для плавающих окон
  • PixelFormat.TRANSLUCENT - формат, позволяющий полупрозрачность
  • Параметр alpha для контроля уровня прозрачности

Для устройств Samsung может потребоваться добавить дополнительные флаги:

java
if (Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
}

Важно также убедиться, что у приложения есть разрешение SYSTEM_ALERT_WINDOW, которое требуется для создания оверлеев на Android 6.0 и выше.


Создание полупрозрачного оверлея с фильтром синего света

При создании фильтров синего света или других полупрозрачных оверлеев нужно特别注意 настройку прозрачности и обработки касаний. Вот полный пример реализации:

java
public class BlueLightFilterService extends Service {
 private WindowManager windowManager;
 private View overlayView;
 
 @Override
 public void onCreate() {
 super.onCreate();
 windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
 
 // Создаем оверлей с фильтром синего света
 overlayView = new View(this);
 overlayView.setBackgroundColor(Color.parseColor("#801E90FF")); // Полупрозрачный синий
 
 WindowManager.LayoutParams params = new WindowManager.LayoutParams(
 WindowManager.LayoutParams.MATCH_PARENT,
 WindowManager.LayoutParams.MATCH_PARENT,
 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
 WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | 
 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | 
 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
 PixelFormat.TRANSLUCENT
 );
 
 // Для Samsung устройств
 if (Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
 }
 
 windowManager.addView(overlayView, params);
 }
 
 @Override
 public void onDestroy() {
 super.onDestroy();
 if (overlayView != null) {
 windowManager.removeView(overlayView);
 }
 }
}

Ключевые моменты для фильтров синего света:

  • Используйте формат PixelFormat.TRANSLUCENT для поддержки полупрозрачности
  • Установите подходящий уровень прозрачности (обычно 20-50%)
  • Убедитесь, что оверлей не блокирует взаимодействие с элементами под ним
  • Для плавающих окон с фильтрами синего света можно использовать более сложные реализации с возможностью регулировки интенсивности

Альтернативные решения для обхода проблемы

Если стандартные настройки WindowManager.LayoutParams не решают проблему, можно рассмотреть альтернативные подходы:

1. Использование Accessibility Service:

xml
<service
 android:name=".TouchInterceptionService"
 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>

Преимущества:

  • Позволяет перехватывать и перенаправлять касания
  • Работает даже на устройствах с ограничениями для оверлеев
  • Более гибкая обработка сложных сценариев взаимодействия

2. Использование ViewOverlay вместо WindowManager:
Для некоторых случаев можно использовать стандартные наложения View вместо отдельного окна WindowManager:

java
ViewGroup rootView = findViewById(android.R.id.content);
rootView.getOverlay().add(overlayView);

3. Динамическая прозрачность:
Сделать оверлей полностью прозрачным в областях, где требуется взаимодействие:

java
// Создать маску прозрачных областей
Path transparentPath = new Path();
transparentPath.addCircle(x, y, radius, Path.Direction.CW);
overlayView.setPath(transparentPath);

4. Использование системных настроек:
Для некоторых устройств можно использовать системные настройки фильтров синего света вместо самостоятельного оверлея:

java
Settings.Global.putInt(getContentResolver(), 
 Settings.Global.SCREEN_BRIGHTNESS_MODE, 
 Settings.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);

Эти решения особенно полезны для фильтров синего света, которые должны быть незаметны для пользователя, но при этом не мешать работе с устройством.


Практические примеры кода

Вот полный пример реализации оверлея с фильтром синего света, корректно обрабатывающего касания:

java
public class FloatingOverlayService extends Service {
 private WindowManager windowManager;
 private View overlayView;
 private WindowManager.LayoutParams params;
 
 @Override
 public void onCreate() {
 super.onCreate();
 windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
 
 // Создаем кастомное представление для оверлея
 overlayView = new View(this) {
 @Override
 public boolean onTouchEvent(MotionEvent event) {
 // Обрабатываем только касания внутри оверлея
 if (event.getAction() == MotionEvent.ACTION_DOWN) {
 Log.d("Overlay", "Touch event inside overlay");
 return true;
 }
 return super.onTouchEvent(event);
 }
 };
 
 // Устанавливаем полупрозрачный синий цвет для фильтра
 overlayView.setBackgroundColor(Color.parseColor("#401E90FF")); // 25% непрозрачности
 
 // Настраиваем параметры оверлея
 params = new WindowManager.LayoutParams(
 WindowManager.LayoutParams.MATCH_PARENT,
 WindowManager.LayoutParams.MATCH_PARENT,
 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
 WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | 
 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | 
 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
 PixelFormat.TRANSLUCENT
 );
 
 // Позиционируем оверлей поверх всего
 params.gravity = Gravity.TOP | Gravity.LEFT;
 params.x = 0;
 params.y = 0;
 
 // Для Samsung устройств
 if (Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
 // Дополнительные параметры для корректной работы на Samsung
 params.width = WindowManager.LayoutParams.MATCH_PARENT;
 params.height = WindowManager.LayoutParams.MATCH_PARENT;
 }
 
 // Добавляем оверлей на экран
 windowManager.addView(overlayView, params);
 }
 
 @Override
 public void onDestroy() {
 super.onDestroy();
 if (overlayView != null) {
 windowManager.removeView(overlayView);
 }
 }
 
 @Override
 public IBinder onBind(Intent intent) {
 return null;
 }
}

Не забудьте добавить разрешение в AndroidManifest.xml:

xml
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

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


Тестирование и отладка оверлеев

Для корректной работы оверлеев на разных устройствах необходимо провести тщательное тестирование:

1. Тестирование на различных устройствах:

  • Тестируйте на устройствах разных производителей (Samsung, Xiaomi, Google Pixel)
  • Проверяйте работу на разных версиях Android (Android 8-13+)
  • Учитывайте особенности прошивок и OEM-модификаций

2. Инструменты отладки:

java
// Включаем логирование для отладки касаний
overlayView.setOnTouchListener(new View.OnTouchListener() {
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 Log.d("TouchDebug", "Action: " + event.getAction() + 
 ", X: " + event.getX() + ", Y: " + event.getY());
 return false;
 }
});

3. Проверка разрешений:

java
if (!Settings.canDrawOverlays(this)) {
 Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
 startActivity(intent);
}

4. Инструменты разработчика:

  • Используйте Layout Inspector для проверки слоев
  • Проверяйте логи на наличие ошибок WindowManager
  • Тестируйте производительность оверлея

Особое внимание уделите тестированию на устройствах Samsung, где часто возникают специфические проблемы с оверлеями. Для фильтров синего света важно проверить, что они не блокируют взаимодействие с приложениями и не вызывают задержек в работе системы.


Источники

  1. Android Developers Documentation — Официальная документация по WindowManager.LayoutParams и флагам для оверлеев: https://developer.android.com/reference/android/view/WindowManager.LayoutParams

  2. Stack Overflow Discussion — Практическое решение проблемы ‘Untrusted touch due to occlusion’ с примерами кода: https://stackoverflow.com/questions/tagged/android-windowmanager?tab=Newest

  3. Android Developer Guide — Руководство по созданию оверлеев и плавающих окон: https://developer.android.com/guide/topics/ui/overview

  4. Samsung Developers Documentation — Специфические параметры для оверлеев на устройствах Samsung: https://developer.samsung.com/android/overview

  5. Android Open Source Project — Исходный код WindowManager для понимания внутренней логики обработки касаний: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/WindowManager.java


Заключение

Ошибка ‘Untrusted touch due to occlusion’ в Android оверлеях — это распространенная проблема, особенно при создании полупрозрачных слоев вроде фильтров синего света. Ключ к решению лежит в правильной настройке WindowManager.LayoutParams с использованием флагов FLAG_NOT_TOUCH_MODAL, FLAG_WATCH_OUTSIDE_TOUCH и FLAG_NOT_FOCUSABLE. На устройствах Samsung могут потребоваться дополнительные параметры, такие как PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY.

Для корректной обработки касаний через полупрозрачные оверлеи важно не только настроить параметры, но и тщательно протестировать решение на различных устройствах и версиях Android. Альтернативные подходы, такие как использование Accessibility Service, могут стать спасением в сложных случаях. Основная цель — создать оверлей, который выполняет свою функцию (фильтрацию синего света), но при этом не мешает пользователю взаимодействовать с интерфейсом устройства.

Android Developers / Портал документации

Для исправления ошибки “Untrusted touch due to occlusion” в Android оверлеях необходимо правильно настроить параметры WindowManager.LayoutParams. Ключевые флаги включают FLAG_NOT_TOUCH_MODAL, который позволяет окну не перехватывать все касания, и FLAG_WATCH_OUTSIDE_TOUCH для отслеживания касаний вне области оверлея. Для полупрозрачных слоев следует использовать тип окна TYPE_APPLICATION_OVERLAY и установить формат PixelFormat.TRANSLUCENT с параметром alpha для контроля прозрачности. На устройствах Samsung могут потребоваться дополнительные параметры, такие как PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY.

0stone0 / Разработчик

Проблема “Untrusted touch due to occlusion” часто возникает при создании полупрозрачных оверлеев на новых версиях Android. Разработчики рекомендуют использовать комбинацию флагов FLAG_NOT_TOUCH_MODAL | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_NOT_FOCUSABLE для корректной обработки касаний. Важно также проверить наличие разрешений SYSTEM_ALERT_WINDOW и учесть, что на устройствах Samsung существуют дополнительные ограничения для оверлеев. Альтернативным решением может быть использование Accessibility Service вместо прямого WindowManager для обработки касаний через полупрозрачные слои.

Авторы
0stone0 / Разработчик
Разработчик
7
Разработчик
A
Программист
Источники
Android Developers / Портал документации
Портал документации
Android Developers / Портал документации
Портал документации
Stack Overflow / Q&A Platform
Q&A Platform
Проверено модерацией
НейроОтветы
Модерация