小米全面屏键盘优化
这个功能还是不错的。我的左边放的是剪切板,右边方的是小爱语音输入。
但是它只针对了三款输入法有优化。
今天就去看看它里面是怎么搞的。
adb pull /system/framework/framework.jar c:/fw
把源代码拉出来,解压出来可以看到四个 .dex 文件
d2j-dex2jar.bat classes2.dex --force
把这个 .dex 文件反编译,转化成 classes2-dex2jar.jar 文件
使用 Luyten 查看这个 classes2-dex2jar.jar
可以找到这样一个文件 android.inputmethodservice.InputMethodServiceInjector
package android.inputmethodservice;
import java.util.*;
import android.os.*;
import android.view.inputmethod.*;
import android.content.*;
import android.util.*;
import android.content.pm.*;
import android.view.*;
import java.lang.reflect.*;
class InputMethodServiceInjector
{
public static final String TAG = "InputMethodService";
private static ClassLoader sClassLoader;
private static HashMap<String, Integer> sImeMinVersionSupport;
private static boolean sIsCanLoadPlugin;
private static int sIsImeSupport;
private static boolean sIsMiuiBottomSupport;
private static int sVersionCode;
static {
InputMethodServiceInjector.sIsImeSupport = -1;
InputMethodServiceInjector.sVersionCode = -1;
InputMethodServiceInjector.sImeMinVersionSupport = new HashMap<String, Integer>();
boolean sIsMiuiBottomSupport = false;
if (SystemProperties.getInt("ro.miui.support_miui_ime_bottom", 0) == 1) {
sIsMiuiBottomSupport = true;
}
InputMethodServiceInjector.sIsMiuiBottomSupport = sIsMiuiBottomSupport;
InputMethodServiceInjector.sImeMinVersionSupport.put("com.iflytek.inputmethod.miui", 7912);
InputMethodServiceInjector.sImeMinVersionSupport.put("com.sohu.inputmethod.sogou.xiaomi", 624);
InputMethodServiceInjector.sImeMinVersionSupport.put("com.baidu.input_mi", 477);
// 三个写死的输入法包名
}
public static void addMiuiBottomView(final LayoutInflater layoutInflater, final ViewGroup viewGroup, final ViewGroup viewGroup2, final View view, final ViewGroup viewGroup3, final InputMethodManager inputMethodManager, final InputMethodService inputMethodService) {
final Context applicationContext = inputMethodService.getApplicationContext();
if (InputMethodServiceInjector.sIsCanLoadPlugin = isCanLoadPlugin(applicationContext)) {
final String apkPath = InputMethodModuleManager.getApkPath(applicationContext, "com.miui.phrase");
try {
final Context moduleContext = getModuleContext((Context)inputMethodService);
if (moduleContext != null) {
InputMethodModuleManager.loadDex(moduleContext.getClassLoader(), apkPath);
InputMethodServiceInjector.sClassLoader = moduleContext.getClassLoader();
reflectModule("addMiuiBottomView", new Class[] { Context.class, LayoutInflater.class, ViewGroup.class, ViewGroup.class, View.class, ViewGroup.class, InputMethodManager.class, InputMethodService.class }, moduleContext, layoutInflater, viewGroup, viewGroup2, view, viewGroup3, inputMethodManager, inputMethodService);
}
}
catch (Exception ex) {
Log.e("InputMethodService", "load dex error!", (Throwable)ex);
}
}
}
public static void afterComputeInsets(final InputMethodService.Insets insets, final InputMethodService inputMethodService) {
if (InputMethodServiceInjector.sIsCanLoadPlugin) {
reflectModule("afterComputeInsets", new Class[] { InputMethodService.Insets.class }, insets);
}
}
private static void customizeBottomViewColor(final boolean b, final int n, final int n2, final int n3) {
final StringBuilder sb = new StringBuilder();
sb.append("customizeBottomViewColor, isCustom : ");
sb.append(b);
Log.i("InputMethodService", sb.toString());
if (InputMethodServiceInjector.sIsCanLoadPlugin) {
reflectModule("customizeBottomViewColor", new Class[] { Boolean.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE }, b, n, n2, n3);
}
}
private static int getImeVersionCode(final Context context) {
final String packageName = context.getPackageName();
try {
if (InputMethodServiceInjector.sVersionCode == -1) {
final PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
if (packageInfo != null) {
InputMethodServiceInjector.sVersionCode = packageInfo.versionCode;
}
}
}
catch (PackageManager$NameNotFoundException ex) {
final StringBuilder sb = new StringBuilder();
sb.append("check ");
sb.append(packageName);
sb.append(" Version failed");
Log.e("InputMethodService", sb.toString(), (Throwable)ex);
}
return InputMethodServiceInjector.sVersionCode;
}
private static Context getModuleContext(Context packageContext) {
try {
packageContext = packageContext.createPackageContext("com.miui.phrase", 0);
return packageContext;
}
catch (PackageManager$NameNotFoundException ex) {
Log.e("InputMethodService", "getModuleContext", (Throwable)ex);
return null;
}
}
private static boolean isCanLoadPlugin(final Context context) {
return isImeSupport(context) && InputMethodServiceInjector.sIsMiuiBottomSupport;
}
private static boolean isImeSupport(final Context context) {
final int sIsImeSupport = InputMethodServiceInjector.sIsImeSupport;
boolean b = false;
if (sIsImeSupport != -1) {
if (sIsImeSupport == 1) {
b = true;
}
return b;
}
final Integer n = InputMethodServiceInjector.sImeMinVersionSupport.get(context.getPackageName());
if (n != null && getImeVersionCode(context) >= n) {// 判断包名和版本号
InputMethodServiceInjector.sIsImeSupport = 1;
return true;
}
InputMethodServiceInjector.sIsImeSupport = 0;
return false;
}
static void onBadTokenException(final InputMethodService inputMethodService, final WindowManager$BadTokenException ex) {
final StringBuilder sb = new StringBuilder();
sb.append("Catch a BadTokeException: ");
sb.append(ex.getMessage());
Log.i("InputMethodService", sb.toString());
inputMethodService.mWindow = new SoftInputWindow((Context)inputMethodService, "InputMethod", inputMethodService.mTheme, null, null, inputMethodService.mDispatcherState, 2011, 80, false);
inputMethodService.initViews();
inputMethodService.mWindow.getWindow().setLayout(-1, -2);
}
public static void onDestroy(final Context context) {
if (InputMethodServiceInjector.sIsCanLoadPlugin) {
reflectModule("onDestroy", new Class[0], new Object[0]);
}
}
public static void onWindowHidden(final InputMethodService inputMethodService) {
if (InputMethodServiceInjector.sIsCanLoadPlugin) {
reflectModule("onWindowHidden", new Class[0], new Object[0]);
}
}
public static void onWindowShown(final InputMethodService inputMethodService) {
if (InputMethodServiceInjector.sIsCanLoadPlugin) {
reflectModule("onWindowShown", new Class[0], new Object[0]);
}
}
private static void reflectModule(final String s, final Class<?>[] array, final Object... array2) {
try {
final Method declaredMethod = Class.forName("com.miui.inputmethod.InputMethodBottomManager", true, InputMethodServiceInjector.sClassLoader).getDeclaredMethod(s, array);
declaredMethod.setAccessible(true);
declaredMethod.invoke(null, array2);
}
catch (Exception ex) {
Log.e("InputMethodService", s, (Throwable)ex);
}
}
}
可以看出来,这里面写死了三个包名,而且开启优化也会去判断版本号。
但是,自己经常使用的是谷歌拼音输入法,但是还想用这个优化,怎么破。
第一步,下载谷歌拼音输入法的apk包
第二步,使用 apktool,反编译apk包
第三步,修改 AndroidManifest.xml 中,第一行 package="" 引号中改为三个写死包名中的一个
第四步,使用 apktool,重新打包出 apk
第五步,对 apk 进行签名,然后就可以安装了