I am developing an Android accessibility app in Kotlin. I want to provide full-screen magnification for users with visual impairments.
I use AccessibilityService.MagnificationController to set the magnification scale to 1.5. It works initially, but when I swipe to the Android home screen, the magnification resets to 1.0. The accessibility service remains enabled and connected.
I tried restoring the magnification once after detecting the reset. The API returns true, and the screen briefly becomes magnified again, but then returns to normal size.
Relevant Kotlin code:
val config = MagnificationConfig.Builder()
.setMode(MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN)
.setScale(1.5f)
.setActivated(true)
.build()
val result = magnificationController
.setMagnificationConfig(config, true)
Log.d("Visionplus", "Result = $result")
The magnification change listener initially reports a scale of 1.5, but reports 1.0 after switching to the home screen.
Accessibility service XML configuration:
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:canRetrieveWindowContent="true"
android:description="@string/app_name"
android:notificationTimeout="100"
android:canControlMagnification="true" />
Environment:
Android 15
Pixel 7 emulator
Kotlin and Android Studio
Full-screen magnification mode
My question:
How can my AccessibilityService maintain full-screen magnification after switching to the Android home screen, if Android permits this? Is there a recommended way to use MagnificationController to handle magnification changes without repeatedly resetting the zoom?
Thank you for your help. I am new to Android development, so a simple explanation would be appreciated.
Android doesn't let you keep it. Every time the app in front changes, Android 15 zooms full-screen magnification back out FullScreenMagnificationController.onUserContextChanged(). It doesn't matter which service set the zoom, and there is no API to turn that off.
A workaround is to set it again once the switch is done. One switch can trigger the zoom-out more than once, so reapply after the last window change instead of right away
private val handler = Handler(Looper.getMainLooper())
private val reapplyZoom = Runnable {
magnificationController.setMagnificationConfig(config, true)
}
override fun onAccessibilityEvent(event: AccessibilityEvent) {
if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
handler.removeCallbacks(reapplyZoom) // only the last event in a burst re-applies
handler.postDelayed(reapplyZoom, 500)
}
}
Emmanuel Obiechina Ikenna