Skip to content

Commit 9143255

Browse files
authored
Fix MethodNotFound getSupportIme & Add permission hook to fix IME list access issues (#28)
* Fix MethodNotFound getSupportIme * Add permission hook to fix IME list access issues
1 parent bfc2778 commit 9143255

File tree

1 file changed

+63
-7
lines changed

1 file changed

+63
-7
lines changed

app/src/main/java/com/xposed/miuiime/MainHook.kt

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package com.xposed.miuiime
22

3+
import android.content.IntentFilter
34
import android.view.inputmethod.InputMethodManager
45
import com.github.kyuubiran.ezxhelper.init.EzXHelperInit
56
import com.github.kyuubiran.ezxhelper.utils.Log
67
import com.github.kyuubiran.ezxhelper.utils.findMethod
78
import com.github.kyuubiran.ezxhelper.utils.getObjectAs
89
import com.github.kyuubiran.ezxhelper.utils.getStaticObject
910
import com.github.kyuubiran.ezxhelper.utils.hookAfter
11+
import com.github.kyuubiran.ezxhelper.utils.hookBefore
1012
import com.github.kyuubiran.ezxhelper.utils.hookReplace
1113
import com.github.kyuubiran.ezxhelper.utils.hookReturnConstant
14+
import com.github.kyuubiran.ezxhelper.utils.invokeMethodAs
1215
import com.github.kyuubiran.ezxhelper.utils.invokeStaticMethodAuto
1316
import com.github.kyuubiran.ezxhelper.utils.loadClassOrNull
1417
import com.github.kyuubiran.ezxhelper.utils.putStaticObject
@@ -28,16 +31,21 @@ class MainHook : IXposedHookLoadPackage {
2831
private var navBarColor: Int? = null
2932

3033
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
31-
//检查是否支持全面屏优化
34+
// 检查是否支持全面屏优化
3235
if (PropertyUtils["ro.miui.support_miui_ime_bottom", "0"] != "1") return
3336
EzXHelperInit.initHandleLoadPackage(lpparam)
3437
EzXHelperInit.setLogTag(TAG)
3538
Log.i("miuiime is supported")
36-
startHook(lpparam)
39+
40+
if (lpparam.packageName == "android") {
41+
startPermissionHook()
42+
} else {
43+
startHook(lpparam)
44+
}
3745
}
3846

3947
private fun startHook(lpparam: XC_LoadPackage.LoadPackageParam) {
40-
//检查是否为小米定制输入法
48+
// 检查是否为小米定制输入法
4149
val isNonCustomize = !miuiImeList.contains(lpparam.packageName)
4250
if (isNonCustomize) {
4351
val sInputMethodServiceInjector =
@@ -56,7 +64,7 @@ class MainHook : IXposedHookLoadPackage {
5664
lpparam.classLoader
5765
)
5866

59-
//获取常用语的ClassLoader
67+
// 获取常用语的ClassLoader
6068
findMethod("android.inputmethodservice.InputMethodModuleManager") {
6169
name == "loadDex" && parameterTypes.sameAs(ClassLoader::class.java, String::class.java)
6270
}.hookAfter { param ->
@@ -73,8 +81,8 @@ class MainHook : IXposedHookLoadPackage {
7381
hookIsXiaoAiEnable(it)
7482
}
7583

76-
//针对A11的修复切换输入法列表
77-
it.getMethod("getSupportIme").hookReplace { _ ->
84+
// 针对A11的修复切换输入法列表
85+
it.getDeclaredMethod("getSupportIme").hookReplace { _ ->
7886
it.getStaticObject("sBottomViewHelper")
7987
.getObjectAs<InputMethodManager>("mImm").enabledInputMethodList
8088
}
@@ -94,7 +102,7 @@ class MainHook : IXposedHookLoadPackage {
94102
clazz.putStaticObject("sIsImeSupport", 1)
95103
Log.i("Success:Hook field sIsImeSupport")
96104
}.onFailure {
97-
Log.i("Failed:Hook field sIsImeSupport ")
105+
Log.i("Failed:Hook field sIsImeSupport")
98106
Log.i(it)
99107
}
100108
}
@@ -169,4 +177,52 @@ class MainHook : IXposedHookLoadPackage {
169177
Log.i(it)
170178
}
171179
}
180+
181+
/**
182+
* Hook 获取应用列表权限,为所有输入法强制提供获取输入法列表的权限。
183+
* 用于修复部分输入法(搜狗输入法小米版等)缺少获取输入法列表权限,导致切换输入法功能不能显示其他输入法的问题。
184+
* 理论等效于在输入法的AndroidManifest.xml中添加:
185+
* ```xml
186+
* <manifest>
187+
* <queries>
188+
* <intent>
189+
* <action android:name="android.view.InputMethod" />
190+
* </intent>
191+
* </queries>
192+
* </manifest>
193+
* ```
194+
* 当前实现可能影响开机速度,如需此修复需手动设置系统框架作用域。
195+
*/
196+
private fun startPermissionHook() {
197+
runCatching {
198+
findMethod("com.android.server.pm.AppsFilterUtils") {
199+
name == "canQueryViaComponents"
200+
}.hookAfter { param ->
201+
if (param.result == true) return@hookAfter
202+
val querying = param.args[0]
203+
val potentialTarget = param.args[1]
204+
if (!isIme(querying)) return@hookAfter
205+
if (!isIme(potentialTarget)) return@hookAfter
206+
param.result = true
207+
}
208+
}.onFailure {
209+
Log.i("Failed: Hook method canQueryViaComponents")
210+
Log.i(it)
211+
}
212+
}
213+
214+
private fun isIme(androidPackage: Any): Boolean {
215+
val services = androidPackage.invokeMethodAs<List<Any>>("getServices")
216+
services?.forEach { service ->
217+
if (!service.invokeMethodAs<Boolean>("isExported")!!) return@forEach
218+
val intents = service.invokeMethodAs<List<Any>>("getIntents")
219+
intents?.forEach { intent ->
220+
val intentFilter = intent.invokeMethodAs<IntentFilter>("getIntentFilter")
221+
if (intentFilter?.matchAction("android.view.InputMethod") == true) {
222+
return true
223+
}
224+
}
225+
}
226+
return false
227+
}
172228
}

0 commit comments

Comments
 (0)