android4.0.4 外接物理键盘设置

需求:根据系统语言,确定外接物理键盘布局。

外接键盘的布局由以下文件决定:

1./system/usr/keylayout/Generic.kl

2./system/usr/keychars/Generic.kcm

首先,得准备好这两个文件,以德国为例:de_keylayout.kl , de_keylayout.kcm (命名根据自己的程序来定)

调用流程如下:

setting---->mWindowManager.forceScanDevices(language)--->mInputManager.forceScanDevices(language)---->nativeForceScanDevices(language)

------>android_server_InputManager_nativeForceScanDevices(JNIEnv* env, jclass clazz, jstring language)

------>gNativeInputManager->getInputManager()->forceScanDevices(languageStr)

------>mReader->forceScanDevices(language)

------>mEventHub->forceScanDevicesLocked(language)

从jni开始:

static void android_server_InputManager_nativeForceScanDevices(JNIEnv* env, jclass clazz, jstring language) {
	if (checkInputManagerUnitialized(env)) {
		return;
	}
	const char *languageStr = env->GetStringUTFChars(language, NULL);
	gNativeInputManager->getInputManager()->forceScanDevices(languageStr);
	env->ReleaseStringUTFChars(language, languageStr);
}
void InputManager::forceScanDevices(const char* language) {
	mReader->forceScanDevices(language);
}
void InputReader::forceScanDevices(const char* language) {
	mEventHub->forceScanDevicesLocked(language);
}
void EventHub::forceScanDevicesLocked(const char* lang) {
	language = lang;
	closeAllDevicesLocked();//必须先把设备关了
	status_t res = scanDirLocked(DEVICE_PATH);//重新扫描设备
	if(res < 0) {
		LOGE("force scan dir failed for %s\n", DEVICE_PATH);
	}
}
status_t EventHub::loadKeyMapLocked(Device* device, const char* language) {
    return device->keyMap.load(device->identifier, device->configuration, language);
}

Keyboard.cpp:

status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
		const PropertyMap* deviceConfiguration, const char* language) {
	.....

	// Try searching by device identifier.
    if (probeKeyMap(deviceIdenfifier, String8::empty())) {
        return OK;
    }

    char lan[PROPERTY_VALUE_MAX];
 property_get("persist.sys.sa.lan", lan, NULL);
 LOGD("----persist.sys.sa.lan: %s", lan);
 if (lan != NULL && strcmp(lan, "")) {
  if (probeKeyMap(deviceIdenfifier, String8(lan) + String8("_keyboard"))) {
   return OK;
  }
 } else {
  if (language == NULL || !strcmp(language, "unknow")) {
   char property[PROPERTY_VALUE_MAX];
   property_get("persist.sys.language", property, NULL);
   if (probeKeyMap(deviceIdenfifier, String8(property) + String8("_keyboard"))) {
    return OK;
   }
  } else {
   if (probeKeyMap(deviceIdenfifier, String8(language) + String8("_keyboard"))) {
    return OK;
   }
  }
 }
    // Fall back on the Generic key map.
    // TODO Apply some additional heuristics here to figure out what kind of
    //      generic key map to use (US English, etc.) for typical external keyboards.
    if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
        return OK;
    }

    ....

}

这样就能找到对应的kl文件了。如:de_keylayout.kl

设置中的UI:

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.inputmethod;

import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.IWindowManager;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class InputMethodAndSubtypeEnablerForExternalKeyboard extends SettingsPreferenceFragment implements
                    Preference.OnPreferenceChangeListener {
    private static final String TAG =InputMethodAndSubtypeEnablerForExternalKeyboard.class.getSimpleName();
    
    final private HashMap<String, CheckBoxPreference> mSubtypeAutoSelectionCBMap =
            new HashMap<String, CheckBoxPreference>();
    final private HashMap<String, String> mKeyboardEntryMap = new HashMap<String, String>();
    private String mInputMethodId;
    private String mTitle;
    private String mSystemLanguage = "";
    private ListPreference mLanguageList;
    private static final String default_language_value = "en";
    private static final String keyboard_name = " Keyboard";
    private static final String default_language_keyboard = "English";
    private boolean isSystemLanguage;
    private boolean isSelectKeyboard;
    private String valLanguage;
    
    private IWindowManager mWindowManager;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        final Configuration config = getResources().getConfiguration();

        final Bundle arguments = getArguments();
        // Input method id should be available from an Intent when this preference is launched as a
        // single Activity (see InputMethodAndSubtypeEnablerActivity). It should be available
        // from a preference argument when the preference is launched as a part of the other
        // Activity (like a right pane of 2-pane Settings app)
        mInputMethodId = getActivity().getIntent().getStringExtra(
                android.provider.Settings.EXTRA_INPUT_METHOD_ID);
        if (mInputMethodId == null && (arguments != null)) {
            final String inputMethodId =
                    arguments.getString(android.provider.Settings.EXTRA_INPUT_METHOD_ID);
            if (inputMethodId != null) {
                mInputMethodId = inputMethodId;
            }
        }
        mTitle = getActivity().getIntent().getStringExtra(Intent.EXTRA_TITLE);
        if (mTitle == null && (arguments != null)) {
            final String title = arguments.getString(Intent.EXTRA_TITLE);
            if (title != null) {
                mTitle = title;
            }
        }
        
        mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
        mSystemLanguage = config.locale.getLanguage();
        
        setPreferenceScreen(createPreferenceHierarchy());
    }

    @Override
    public void onActivityCreated(Bundle icicle) {
        super.onActivityCreated(icicle);
        if (!TextUtils.isEmpty(mTitle)) {
            getActivity().setTitle(mTitle);
        }
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        Settings.System.putInt(getContentResolver(), Settings.System.USING_SYSTEM_LANGUAGE, 0);
        String value = String.valueOf(newValue);
        Settings.System.putString(getContentResolver(), Settings.System.EXTERNAL_KEYBOARD_VALUE, value);
        SystemProperties.set("persist.sys.sa.lan", value);
        try {
            mWindowManager.forceScanDevices(value);
        } catch (RemoteException e) {
            e.printStackTrace();
            return false;
        }
        setLanguageListTitle(value);
        isSelectKeyboard = true;
        return true;
    }

    @Override
    public boolean onPreferenceTreeClick(
            PreferenceScreen preferenceScreen, Preference preference) {

        if (preference instanceof CheckBoxPreference) {
            final CheckBoxPreference chkPref = (CheckBoxPreference) preference;
            Settings.System.putInt(getContentResolver(), Settings.System.USING_SYSTEM_LANGUAGE, 1);
            isSelectKeyboard = false;
            if (chkPref.isChecked()) {
                try {
		  SystemProperties.set("persist.sys.sa.lan", mSystemLanguage);
                    mWindowManager.forceScanDevices(mSystemLanguage);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                Settings.System.putInt(getContentResolver(), Settings.System.USING_SYSTEM_LANGUAGE, 1);
                mLanguageList.setEnabled(false);
                setLanguageListTitle(mSystemLanguage);
            } else {
                Settings.System.putInt(getContentResolver(), Settings.System.USING_SYSTEM_LANGUAGE, 0);
                mLanguageList.setEnabled(true);
            }
        }
        return super.onPreferenceTreeClick(preferenceScreen, preference);
    }

    private PreferenceScreen createPreferenceHierarchy() {
        // Root
        final PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
        final Context context = getActivity();

        final PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(context);
        root.addPreference(keyboardSettingsCategory);

        keyboardSettingsCategory.setTitle("");
        final CheckBoxPreference autoCB = new CheckBoxPreference(context);
        mSubtypeAutoSelectionCBMap.put("autoCB", autoCB);
        keyboardSettingsCategory.addPreference(autoCB);
        autoCB.setTitle(R.string.use_system_language_to_select_input_method_subtypes);

        final PreferenceCategory activeInputMethodsCategory = new PreferenceCategory(context);
        activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes);
        root.addPreference(activeInputMethodsCategory);
        
        valLanguage = Settings.System.getString(getContentResolver(), Settings.System.EXTERNAL_KEYBOARD_VALUE);
        mLanguageList = new ListPreference(context);
        mLanguageList.setEntries(R.array.Keyboard_entries);
        mLanguageList.setEntryValues(R.array.Keyboard_values);
        
        CharSequence[] charLanguageKey = mLanguageList.getEntryValues();
        CharSequence[] charLanguageEntries = mLanguageList.getEntries();
        if (mKeyboardEntryMap.size() == 0) {
            mKeyboardEntryMap.put("EnglishKey", default_language_keyboard);
            for (int j=0; j<charLanguageEntries.length; j++) {
                mKeyboardEntryMap.put((String)charLanguageKey[j], (String)charLanguageEntries[j]);
            }
        }
        if (valLanguage == null) {
            for (CharSequence c : charLanguageKey) {
                if (mSystemLanguage.equals(c)) {
                    isSystemLanguage = true;
                    break;
                }
                isSystemLanguage = false;
            }
            mLanguageList.setValue(isSystemLanguage ? mSystemLanguage : default_language_value);
            Settings.System.putInt(getContentResolver(), Settings.System.USING_SYSTEM_LANGUAGE, 1);
        } else {
            for (CharSequence c : charLanguageKey) {
                if (valLanguage.equals(c)) {
                    isSystemLanguage = true;
                    break;
                }
                isSystemLanguage = false;
            }
            mLanguageList.setValue(isSystemLanguage ? valLanguage : default_language_value);
            isSelectKeyboard = true;
        }
        
        mLanguageList.setOnPreferenceChangeListener(this);
        activeInputMethodsCategory.addPreference(mLanguageList);
        
        int isCBCheck = Settings.System.getInt(getContentResolver(), Settings.System.USING_SYSTEM_LANGUAGE, 1);
        if (isCBCheck == 1) {
            autoCB.setChecked(true);
        } else {
            autoCB.setChecked(false);
        }
        if (autoCB.isChecked()) {
            mLanguageList.setEnabled(false);
        } else {
            mLanguageList.setEnabled(true);
        }
        return root;
    }
    
    @Override
    public void onResume() {
        super.onResume();
        updateAutoSelectionCB();
    }
    
    private void updateAutoSelectionCB() {
        int isCBCheck = Settings.System.getInt(getContentResolver(), Settings.System.USING_SYSTEM_LANGUAGE, 1);
        if (isCBCheck == 1) {
            setLanguageListTitle(mSystemLanguage);
            mLanguageList.setValue(mSystemLanguage);
        } else {
            if (isSelectKeyboard) {
                setLanguageListTitle(valLanguage);
            }
        }
    }
    
    private void setLanguageListTitle(String language) {
        String v = mKeyboardEntryMap.get(language);
        mLanguageList.setTitle((v == null ? mKeyboardEntryMap.get("EnglishKey") : v) + keyboard_name);
    }
    
}



InputMethodAndSubtypeEnablerForExternalKeyboard
InputMethodAndSubtypeEnablerForExternalKeyboard
InputMethodAndSubtypeEnablerForExternalKeyboard
EXTERNAL_KEYBOARD_VALUE
EXTERNAL_KEYBOARD_VALUE
chkPref.isChecked()
f (language == NULL) {
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值