Android 4.3 源码下如何修改默认输入法

应项目(Android 4.3)需求需要修改默认输入法,本来想的是,这个应该很简单的撒。随google之~,发现网上主要罗列出以下这种方法:

在 frameworks\base\core\res\res\values\config.xml 添加一个属性:
        <!--leo add-->
      <string name="config_default_input_method">com.android.inputmethod.pinyin/.PinyinIME</string> 
  在frameworks\base\services\java\com\android\server\InputMethodManagerService.java
      的方法buildInputMethodListLocked()里添加:  
  String defaultIme = Settings.Secure.getString(mContext
                  .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
          if ( defaultIme == null )
          {
              final Resources res = mContext.getResources();
              try
              {
                  //frameworks\base\core\res\res\values\config.xml
                  String myIME = res.getString( com.android.internal.R.string.config_default_input_method );
                  if ( myIME != null && myIME.length() > 0 )
                  {
                      Settings.Secure.putString( mContext.getContentResolver(),
                              Settings.Secure.DEFAULT_INPUT_METHOD,
                              myIME );
                  }
              }
              catch ( Exception e )
              {
              }
          }

但是在自己的源码中修改后,刷机调试发现木有作用,而且这种直接修改源代码是不是不好呢?

后来发现这是4.2的源码,是不是4.3的不一样呢。好吧,木有办法 从源码开始分析吧!(前辈指导,google没有,就看源码

    通过log跟踪,发现系统第一次初始化的时候会调用以下的函数,并且以后的开机中该函数不会在被调用,而下面的函数功能是重置可用的输入法选现(在frameworks/base/core/java/com/android/internal/inputmethod/InputMethodUtils.java 中)

    private void resetDefaultImeLocked(Context context) {
          // Do not reset the default (current) IME when it is a 3rd-party IME
          if (mCurMethodId != null
                  && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
              return;
          }
  
          InputMethodInfo defIm = null;
          for (InputMethodInfo imi : mMethodList) {
              if (defIm == null) {
                  if (InputMethodUtils.isValidSystemDefaultIme(
                          mSystemReady, imi, context)) {
                      defIm = imi;
                      Slog.i(TAG, "Selected default: " + imi.getId());
                  }
              }
          }
          if (defIm == null && mMethodList.size() > 0) {
              defIm = InputMethodUtils.getMostApplicableDefaultIME(
                      mSettings.getEnabledInputMethodListLocked());

              Slog.i(TAG, "No default found, using " + defIm.getId());
          }

注意黄色加粗的部分,当系统暂无默认输入法时,选取适用性最广的输入法(卧草,还带这样的),并调用InputMethodUtils.getMostApplicableDefaultIME函数 ,好吧继续看下面的函数:

public static InputMethodInfo getMostApplicableDefaultIME(
              List<InputMethodInfo> enabledImes) {
  if (enabledImes != null && enabledImes.size() > 0) {
              // We‘d prefer to fall back on a system IME, since that is safer.
              int i = enabledImes.size();
              int firstFoundSystemIme = -1;
              while (i > 0) {
                  i--;
                  final InputMethodInfo imi = enabledImes.get(i);
                  if (InputMethodUtils.isSystemImeThatHasEnglishKeyboardSubtype(imi)
                          && !imi.isAuxiliaryIme()) {
                      Return imi;

                  }
                  if (firstFoundSystemIme < 0 && InputMethodUtils.isSystemIme(imi)
                          && !imi.isAuxiliaryIme()) {
                      firstFoundSystemIme = i;
                  }
              }
              return enabledImes.get(Math.max(firstFoundSystemIme, 0));


  同样的请注意黄色地方的代码(红色部分表明是否是一个合法的系统输入法,同时还含有英文亚键盘等特性,普通的输入法无特性,而AOSP键盘却有此特性,系统会直接return 该输入法)。好吧,就你了!既然你这么规定,那我就强制改呗,所以若要修改默认输入,可在此处修改,当系统检测到AOSP键盘时,不直接返回,而是继续检测系统的可用的键盘(当系统第一次启动时,一般只有系统键盘可用,所以应该将所有的输入法设置为可用,修改以下的函数:

public void enableAllIMEsIfThereIsNoEnabledIME() {
              if (!TextUtils.isEmpty(getEnabledInputMethodsStr())) {
                  StringBuilder sb = new StringBuilder();
                  final int N = mMethodList.size();
                  for (int i = 0; i < N; i++) {
                      InputMethodInfo imi = mMethodList.get(i);
                      Slog.i(TAG, "Adding: " + imi.getId());
                      if (i > 0) sb.append(‘:‘);
                      sb.append(imi.getId());
                  }
                  putEnabledInputMethodsStr(sb.toString());
              }
          }

把所有的输入法设置为可用的。则再上一个函数中就可以找你想要的输入法了,那么在上一个函数加一个判断条件,判断循环的输入法是否为你想要默认的输入法,是的话就设置:
  firstFoundSystemIme = i;

  判断条件如下:

               if (InputMethodUtils.isSystemImeThatHasEnglishKeyboardSubtype(imi)
                          && !imi.isAuxiliaryIme()) {
                      continue;

              }

           for(int m = 0; m < enabledImes.size(); m ++){
            if(enabledImes.get(m).getId()== "你想要设置的输入法包名")
                      firstFoundSystemIme = m;
            }
  
  此处可修改为其他的输入法。
  

  编译系统,烧写,启动可以看到默认的输入法从传统的android自带,变成了你想要输入法。


PS:新手,刚写这种分析流程文章

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。