我正在运行带有android pie的设备,并希望以编程方式从我的应用程序内更改过扫描。因此,我完成了以下操作:
WRITE_SECURE_SETTINGS
问题
代码here让我相信,setOverscan
内应该有一个IWindowManager$Stub
方法,但没有。我是在做错事还是只是无法按照自己想做的方式去做我想做的事?
我的代码显示hasNavigationBar
正常工作,但是setOverscanMode
方法无效,并因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
}
}
}
答案 0 :(得分:1)
这里的代码让我相信,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中的政策。