Фон
Я создаю приложение Android, которое обеспечивает обратную связь в реальном времени по вопросам доступности, выделяя и маркируя их с помощью Canvas
, прикрепленного к окну, с помощью TYPE_APPLICATION_OVERLAY
или TYPE_SYSTEM_ERROR
в зависимости от версия ОС. Это работало нормально, когда я просто использовал AccessibilityService
для получения событий специальных возможностей, поскольку я мог предотвратить обнаружение моих представлений во время анализа.
Проблема
Я недавно пытался добавить поддержку для обнаружения новых типов проблем. например, контраст текста или фона или размер текста путем записи экрана и использования оптического распознавания текста для определения текста и его свойств. Оптическое распознавание текста работает хорошо, и я могу обнаружить любой текст на экране (включая текст, вставленный в изображение), но теперь моя система выделения и маркировки воспринимается записью экрана в обратной связи l oop, вызывая чтобы выделить метки над текстовым блоком как проблемы, что приводит к пузырьковому эффекту, который оживляет что-то вроде
+-----+
|Issue|
+-----+ +-----+
|Issue| | |
+-----+ +-----+ +-----+
|Issue| | |
=> +-----+ => +-----+ => +-----+ => +-----+
|Issue| |Issue| |Issue| |Issue|
+-------------+ +-------------+ +-------------+ +-------------+
Some text | Some text | | Some text | | Some text | | Some text |
+-------------+ +-------------+ +-------------+ +-------------+
Вопрос
Есть ли способ скрыть свое наложение от записи ?
Что я пробовал
Я добавил WindowManager.LayoutParams.FLAG_SECURE
в список флагов и, несмотря на то, что ничего не записывалось, он все равно записывал как исходный текст, так и оверлейный текст
Я изучил альтернативы VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
, чтобы посмотреть, покажутся ли какие-либо альтернативные флаги уместными, но они не выглядят многообещающими, если я не хочу сообщать об ошибках на экран второго устройства, что не является хорошим вариантом.
Код экрана записи
В активности
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val mediaProjectionManager =
ContextCompat.getSystemService(this, MediaProjectionManager::class.java)
val intent = mediaProjectionManager?.createScreenCaptureIntent()
startActivityForResult(intent, REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Skip error handling for brevity
notifyServiceOfScreenRecording(resultCode, data)
finish()
}
Расход записи
// Again, safety checks removed for brevity
val mediaProjectionManager = ContextCompat.getSystemService(mContext, MediaProjectionManager::class.java)
val projection: MediaProjection =
mediaProjectionManager.getMediaProjection(screenRecordingCode, screenRecordingIntent)
val imageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1)
imageReader.setOnImageAvailableListener({ reader ->
if (mIsProcessing) {
reader.acquireLatestImage().close()
} else {
mIsProcessing = true
reader.acquireLatestImage()?.use(this::processImage)
}
}, null)
projection.createVirtualDisplay(
"Virtual Display",
// These are computed with Context.getDisplayMetrics()
mScreenWidth, mScreenHeight,
mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
imageReader.surface,
null /*Callbacks*/,
null /*Handler*/)
projection.registerCallback(object: MediaProjection.Callback() {
override fun onStop() {
super.onStop()
pauseProcessing();
}
}, null)
Наложение кода
val overlayType: Int =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR
} else {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
}
val overlayFlags =
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
windowLayoutParams = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
overlayType,
overlayFlags,
PixelFormat.TRANSLUCENT) }
mWindowLayoutParams.verticalMargin = 0f
val windowManager = context.getSystemService(AccessibilityService.WINDOW_SERVICE) as WindowManager
windowManager.addView(buildCustomRootView(), windowLayoutParams)