更改Android InputManagerService默認鍵盤映射值
在通常情況下我們使用android手機或者平板連接外接鍵盤,默認的外接鍵盤映射值都是美式鍵盤,或者說是標準鍵盤,然而全世界並非只是用這一種鍵盤,在意大利,日本等國還擁有自己獨特的鍵盤,因此就需要設置他們自己的鍵盤映射值
frameworks/base/packages/InputDevices/res/raw/keyboard_layout_turkish.kcm
比方說在土耳其鍵盤下的 shift + 2 的值爲 /,我們假設需要將這個值 改爲 “
key 2 {
label: '2'
base: '2'
shift: '"' //我們在這裏將默認值改爲"
ralt: '\u00a3'
}
當然在這個目錄下對三十多個國家的特殊鍵盤映射都做了設置,但是主要國家都聚集在西方,比如日本等國也是特殊的鍵盤映射這裏就不包括
keyboard_layout_arabic.kcm
keyboard_layout_azerbaijani.kcm
keyboard_layout_belgian.kcm
keyboard_layout_brazilian.kcm
keyboard_layout_bulgarian.kcm
keyboard_layout_croatian_and_slovenian.kcm
keyboard_layout_czech.kcm
keyboard_layout_danish.kcm
keyboard_layout_english_uk.kcm
keyboard_layout_english_us.kcm
keyboard_layout_english_us_colemak.kcm
keyboard_layout_english_us_dvorak.kcm
keyboard_layout_english_us_intl.kcm
keyboard_layout_english_us_workman.kcm
keyboard_layout_estonian.kcm
keyboard_layout_finnish.kcm
keyboard_layout_french.kcm
keyboard_layout_french_ca.kcm
keyboard_layout_german.kcm
keyboard_layout_greek.kcm
keyboard_layout_hebrew.kcm
keyboard_layout_hungarian.kcm
keyboard_layout_icelandic.kcm
keyboard_layout_italian.kcm
keyboard_layout_latvian_qwerty.kcm
keyboard_layout_lithuanian.kcm
keyboard_layout_norwegian.kcm
keyboard_layout_persian.kcm
keyboard_layout_polish.kcm
keyboard_layout_portuguese.kcm
keyboard_layout_russian.kcm
keyboard_layout_russian_mac.kcm
keyboard_layout_slovak.kcm
keyboard_layout_spanish.kcm
keyboard_layout_spanish_latin.kcm
keyboard_layout_swedish.kcm
keyboard_layout_swiss_french.kcm
keyboard_layout_swiss_german.kcm
keyboard_layout_turkish.kcm
keyboard_layout_ukrainian.kcm
我們可以參考這個方法制作我們特殊的鍵盤映射值,android爲我們提供了一個類似overrlay的地方
frameworks/base/data/keyboards/Generic.kcm
在這個地方就可以改默認全語言的默認值
那如果我們要動態的去更換剛連接鍵盤的映射值,應該如何入手
需要在InputManagerService中監聽連接鍵盤後返回的默認值
frameworks/base /services/core/java/com/android/server/input/InputManagerService.java
private String getDefaultKeyboardLayout(final InputDevice d) {
final Locale systemLocale = mContext.getResources().getConfiguration().locale;
// If our locale doesn't have a language for some reason, then we don't really have a
// reasonable default.
if (TextUtils.isEmpty(systemLocale.getLanguage())) {
return null;
}
final List<KeyboardLayout> layouts = new ArrayList<>();
visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
@Override
public void visitKeyboardLayout(Resources resources,
int keyboardLayoutResId, KeyboardLayout layout) {
// Only select a default when we know the layout is appropriate. For now, this
// means its a custom layout for a specific keyboard.
if (layout.getVendorId() != d.getVendorId()
|| layout.getProductId() != d.getProductId()) {
return;
}
final LocaleList locales = layout.getLocales();
final int numLocales = locales.size();
for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
if (isCompatibleLocale(systemLocale, locales.get(localeIndex))) {
layouts.add(layout);
break;
}
}
}
});
if (layouts.isEmpty()) {
//在此方法中,如果用戶未設置默認鍵盤將返回null
return null;
}
// First sort so that ones with higher priority are listed at the top
Collections.sort(layouts);
// Next we want to try to find an exact match of language, country and variant.
final int N = layouts.size();
for (int i = 0; i < N; i++) {
KeyboardLayout layout = layouts.get(i);
final LocaleList locales = layout.getLocales();
final int numLocales = locales.size();
for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
final Locale locale = locales.get(localeIndex);
if (locale.getCountry().equals(systemLocale.getCountry())
&& locale.getVariant().equals(systemLocale.getVariant())) {
return layout.getDescriptor();
}
}
}
// Then try an exact match of language and country
for (int i = 0; i < N; i++) {
KeyboardLayout layout = layouts.get(i);
final LocaleList locales = layout.getLocales();
final int numLocales = locales.size();
for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
final Locale locale = locales.get(localeIndex);
if (locale.getCountry().equals(systemLocale.getCountry())) {
return layout.getDescriptor();
}
}
}
// Give up and just use the highest priority layout with matching language
return layouts.get(0).getDescriptor();
}
我們可以在幾個renturn的地方去加log,看看在設置對應國家時返回的getDescriptor()究竟是什麼,這樣我們就可以在renturn null的地方去返回相應的值,這樣就改變了默認的鍵盤值