IWindowManager - вызвать setOverscan через отражение - PullRequest
1 голос
/ 12 марта 2019

Я использую устройство с пирогом Android и хочу программно изменить оверскан из моего приложения.Поэтому я сделал следующее:

  • предоставил мое приложение WRITE_SECURE_SETTINGS через adb

Проблема

Код здесь позвольте мне поверить, что внутри IWindowManager$Stub должен быть метод setOverscan, но его нет.Я делаю что-то не так или просто невозможно сделать то, что я хочу сделать так, как я пытаюсь это сделать?

Мой код показывает, что hasNavigationBar работает, но метод setOverscanMode не работаетt и происходит сбой с java.lang.NoSuchMethodException: android.view.IWindowManager$Stub$Proxy.setOverscan [int, int, int, int, int]

код

object WindowTool {

    // WindowManager source code: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/IWindowManager.aidl

    fun getWindowManagerService(): Any {
        val serviceManager = Class.forName("android.os.ServiceManager")
        val serviceBinder = serviceManager.getMethod("getService", String::class.java).invoke(serviceManager, Context.WINDOW_SERVICE) as IBinder
        val stub = Class.forName("android.view.IWindowManager\$Stub")
        return stub.getMethod("asInterface", IBinder::class.java).invoke(stub, serviceBinder)
    }

    fun setOverscanMode(v1: Int, v2: Int, v3: Int, v4: Int): Boolean {
        try {

            val windowManagerService = getWindowManagerService()
            for (m in windowManagerService.javaClass.methods) {
                L.d { "Method: $m" }
            }
            val setOverscan = windowManagerService.javaClass.getMethod("setOverscan", Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE)
            setOverscan.invoke(windowManagerService, 0, v1, v2, v3, v4)
            return true
        } catch (e: Exception) {
            L.e(e)
            return false
        }

    }

    fun hasNavigationBar(): Boolean? {
        try {
            val windowManagerService = getWindowManagerService()
            val hasNavigationBar = windowManagerService.javaClass.getMethod("hasNavigationBar")
            val res = hasNavigationBar.invoke(windowManagerService) as Boolean
            L.d { "hasNavigationBar: $res" }
            return res
        } catch (e: Exception) {
            L.e(e)
            return null
        }

    }
}

1 Ответ

1 голос
/ 15 марта 2019

Код здесь позволяет мне верить, что внутри IWindowManager $ Stub должен быть метод setOverscan, но его нет. Я делаю что-то не так или просто невозможно делать то, что я хочу делать так, как я пытаюсь это сделать?

В этом случае вызов getMethod не будет работать. Для получения и вызова метода setOverscan см. Следующий код:

object WindowManagerHackery {

    @SuppressLint("PrivateApi")
    @Throws(OverscanInvocationError::class)
    fun setOverscan(displayId: Int = Display.DEFAULT_DISPLAY, left: Int = 0, top: Int = 0, right: Int = 0, bottom: Int = 0) {
        try {
            val ServiceManager = Class.forName("android.os.ServiceManager")
            val service = ServiceManager.getMethod("getService", String::class.java)
            val binder = service.invoke(null, "window") as IBinder
            val windowManagerStub = Class.forName("android.view.IWindowManager").classes[0]
            val serviceObj = windowManagerStub.getMethod("asInterface", IBinder::class.java).invoke(null, binder)
            windowManagerStub.methods.first { it.name == "setOverscan" }
                    .invoke(serviceObj, displayId, left, top, right, bottom)
        } catch (e: Exception) {
            throw OverscanInvocationError(e)
        }
    }

    class OverscanInvocationError(e: Exception) : Exception(e)

}

Использование:

WindowManagerHackery.setOverscan(bottom = overscanOffset)

Вам понадобится android.permission.WRITE_SECURE_SETTINGS. Я также хотел бы проверить https://github.com/tiann/FreeReflection на поддержку API 28, но я не уверен, есть ли у Google Play политика против включения этой библиотеки в APK, если вы планируете публиковать на рынке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...