第一次写,写的不好请见谅

物理键盘映射过程:

手机/system/usr/keylayout/*.kl :内核将keyCode映射成有含义的字符串
KeycodeLabels.h : framework 将字符串映射成keyEvent的keyCode
frameworks/…/res/values/attrs.xml

主要部分:android.jar

一、问题描述:
当平板连接上蓝牙扫描枪(外接物理键盘)时候,不能弹出软键盘输入,需要打开系统的输入法选择界面关闭硬件物理键盘后才能调用弹出系统软键盘;

理想效果:
在平板连接上蓝牙扫描枪后仍可以调用系统软键盘输入,将系统的物理键盘默认设置为关闭状态,或不需要开启关闭物理键盘,

二、思路

1.首先:你要知道AndroidManifest.xml文件。这里这里有的信息对于理解程序又很大的意义。
2.学会使用grep命令。修改系统的源代码时候这个很重要,
3.当想修改一个程序时,先找到这个程序的位置,大部分只要修改framework 和package 两个文件夹下的内容
4.关键字,例如要修改statuBars。先使用hierarchyviewer查看statuBar属于那个部分。
5.根据图标,使用grep在framework中查找对应的位置。
6.然后就是修改程序了。

三、部分代码

android版本源码

frameworks/base/services/Java/com/android/server/wm/WindowManagerService.java
关键代码:行6618 computeScreenConfigurationLocked()方法中
[java] view plaincopy在CODE上查看代码片派生到我的代码片

boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;  if (hardKeyboardAvailable != mHardKeyboardAvailable) {  mHardKeyboardAvailable = hardKeyboardAvailable;  mHardKeyboardEnabled = !hardKeyboardAvailable;  mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);  mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);  }  if (!mHardKeyboardEnabled) {  config.keyboard = Configuration.KEYBOARD_NOKEYS;  }

将mHardKeyboardEnabled直接改成false
这样改软键盘是能用但是物理键盘是用不了的

最后研究代码frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
如果把updateShowImeWithHardKeyboard方法中的showImeWithHardKeyboard变量直接置为true,则可以实现软键盘与物理键盘的同时使用,
但此举修改影响范围很大,不推荐。

public void updateShowImeWithHardKeyboard() { //modified by Janning for enble the HardKeyboard start final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser( mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mCurrentUserId) == 1; //final boolean showImeWithHardKeyboard = true; //modified by Janning for enble the HardKeyboard end synchronized (mWindowMap) { if (mShowImeWithHardKeyboard != showImeWithHardKeyboard) { mShowImeWithHardKeyboard = showImeWithHardKeyboard; mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); } } }

后续继续研究代码发现在WindowManagerService.java的computeScreenConfigurationLocked方法中有通过判断当前物理键盘类型来控制是否同时启用软件盘的处理逻辑:

boolean computeScreenConfigurationLocked(Configuration config) { if (!mDisplayReady) { return false; }  // TODO(multidisplay): For now, apply Configuration to main screen only. final DisplayContent displayContent = getDefaultDisplayContentLocked();  // Use the effective "visual" dimensions based on current rotation final boolean rotated = (mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270); final int realdw = rotated ? displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; final int realdh = rotated ? displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; int dw = realdw; int dh = realdh;  if (mAltOrientation) { if (realdw > realdh) { // Turn landscape into portrait. int maxw = (int)(realdh/1.3f); if (maxw < realdw) { dw = maxw; } } else { // Turn portrait into landscape. int maxh = (int)(realdw/1.3f); if (maxh < realdh) { dh = maxh; } } }  if (config != null) { config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; }  // Update application display metrics. final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); final DisplayInfo displayInfo = displayContent.getDisplayInfo(); synchronized(displayContent.mDisplaySizeLock) { displayInfo.rotation = mRotation; displayInfo.logicalWidth = dw; displayInfo.logicalHeight = dh; displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; displayInfo.appWidth = appWidth; displayInfo.appHeight = appHeight; displayInfo.getLogicalMetrics(mRealDisplayMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); displayInfo.getAppMetrics(mDisplayMetrics); mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( displayContent.getDisplayId(), displayInfo); } if (false) { Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); }  final DisplayMetrics dm = mDisplayMetrics; mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, mCompatDisplayMetrics);  if (config != null) { config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) / dm.density); config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) / dm.density); computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);  config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); config.densityDpi = displayContent.mBaseDisplayDensity;  // Update the configuration based on available input devices, lid switch, // and platform configuration. config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; config.keyboard = Configuration.KEYBOARD_NOKEYS; config.navigation = Configuration.NAVIGATION_NONAV;  int keyboardPresence = 0; int navigationPresence = 0; final InputDevice[] devices = mInputManager.getInputDevices(); final int len = devices.length; for (int i = 0; i < len; i++) { InputDevice device = devices[i]; if (!device.isVirtual()) { final int sources = device.getSources(); final int presenceFlag = device.isExternal() ? WindowManagerPolicy.PRESENCE_EXTERNAL : WindowManagerPolicy.PRESENCE_INTERNAL;  if (mIsTouchDevice) { if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) { config.touchscreen = Configuration.TOUCHSCREEN_FINGER; } } else { config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; }  if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { config.navigation = Configuration.NAVIGATION_TRACKBALL; navigationPresence |= presenceFlag; } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD && config.navigation == Configuration.NAVIGATION_NONAV) { config.navigation = Configuration.NAVIGATION_DPAD; navigationPresence |= presenceFlag; } // 判断该物理设备的类型, InputDevice.KEYBOARD_TYPE_ALPHABETIC 是表示物理键盘设备 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { config.keyboard = Configuration.KEYBOARD_QWERTY; keyboardPresence |= presenceFlag; } // 获取物理设备名称,判断是否是指定的名称,如果是则把 config.keyboard // 的属性置为 Configuration.KEYBOARD_NOKEYS ,如此则可以同时兼容软键盘 // 物理键盘与软键盘可以同时启用 // Add by Janning start // for show IME with HardKeyboard if (device.getName().equals("XXX-vinput-keypad")) { Slog.w("SLCODE", "the hard device name is: " + device.getName()); config.keyboard = Configuration.KEYBOARD_NOKEYS; } // Add by Janning end } }  if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) { config.navigation = Configuration.NAVIGATION_DPAD; navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; }  // Determine whether a hard keyboard is available and enabled. boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; if (hardKeyboardAvailable != mHardKeyboardAvailable) { mHardKeyboardAvailable = hardKeyboardAvailable; mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); } if (mShowImeWithHardKeyboard) { config.keyboard = Configuration.KEYBOARD_NOKEYS; }  // Let the policy update hidden states. config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); }  return true; }  public boolean isHardKeyboardAvailable() { synchronized (mWindowMap) { return mHardKeyboardAvailable; } }  public void updateShowImeWithHardKeyboard() { // 此处修改也可以实现物理键盘与软键盘的同时启用,即把showImeWithHardKeyboard 直接置为 true, // 但此方法影响太大,不推荐该方案,建议根据设备名称判断 修改config.keyboard 属性值(代码见上文) //changed by Janning start //modified by Janning for enble the HardKeyboard start final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser( mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mCurrentUserId) == 1; //final boolean showImeWithHardKeyboard = true; //modified by Janning for enble the HardKeyboard end //changed by Janning end synchronized (mWindowMap) { if (mShowImeWithHardKeyboard != showImeWithHardKeyboard) { mShowImeWithHardKeyboard = showImeWithHardKeyboard; mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); } } }

当插入物理键盘后通知栏会弹出相应的选择键盘布局通知,对于该通知可以选择隐藏:
根据字符串查找到是在 frameworks\base\services\core\java\com\android\server\input\InputManagerService.java 中调用显示该通知的,
进一步分析代码发现是在 deliverInputDevicesChanged 方法中控制通知的显示。

InputManagerService.java

private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) {  。。。。。。。。。。。。。。。。  if (missingLayoutForExternalKeyboard) { if (missingLayoutForExternalKeyboardAdded) { if (multipleMissingLayoutsForExternalKeyboardsAdded) { // We have more than one keyboard missing a layout, so drop the // user at the generic input methods page so they can pick which // one to set. showMissingKeyboardLayoutNotification(null); } else { // 如果只插入了一个物理键盘则判断该物理键盘的名称是否是指定的,如果是则不让其显示键盘布局的通知 // Modify by Janning begin if (keyboardMissingLayout != null && !keyboardMissingLayout.getName().equals("XXXX-vinput-keypad")) { showMissingKeyboardLayoutNotification(keyboardMissingLayout); } // Modify by Janning end } } } else if (mKeyboardLayoutNotificationShown) { hideMissingKeyboardLayoutNotification(); } } mTempFullKeyboards.clear(); }

注意 注意 注意,重要的说三遍;

加入以上你都修改了,以为这样都OK了,那你就OUT了

系统软键盘">Android在外接物理键盘时,如何强制调用系统软键盘?的更多相关文章

  1. 代码实现将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出

    package com.looaderman.test; import java.io.FileNotFoundException; import java.io.FileOutputStream; ...

  2. 使用downloadmanager调用系统的下载

    /** * 文件名 UpdateDownload.java * 包含类名列表 com.issmobile.numlibrary.tool * 版本信息  版本号  * 创建日期 2014年7月14日  ...

  3. webView调用系统地图,电话,和跳转链接的方法

    webView.dataDetectorTypes = UIDataDetectorTypePhoneNumber | UIDataDetectorTypeLink | UIDataDetectorT ...

  4. APP调用系统相册,使用3DTouch重压,崩溃

    崩溃:app调用系统相册,使用3DTouch重压,崩溃 问题描述 app调用系统相册,使用3DTouch重压,一般的app都会崩溃. 解决方法 写个分类即可 @implementation UICol ...

  5. android制,点击EditText时刻,隐藏系统软键盘,显示光标

    由于项目中要用自己定义的随机键盘,所以必须得屏蔽系统软键盘,可是在4.0的測试系统来看,使用editText.setInputType(InputType.TYPE_NULL)方法固然能隐藏键盘,可是 ...

  6. 软键盘android:windowSoftInputMode属性详解

    android:windowSoftInputModeactivity主窗口与软键盘的交互模式,可以用来避免输入法面板遮挡问题,Android1.5后的一个新特性.这个属性能影响两件事情:[一]当有焦 ...

  7. Visual studio之C# 调用系统软键盘(外部"osk.exe")

    背景 App需要调用系统软键盘输入数据,自己去实现软键盘有些复杂,现在又是急需,没时间去研究实现软键盘,所以只能调用系统软键盘. 正文 需要添加命名空间, using System.Diagnosti ...

  8. Android常用的物理按键及其触发事件

    Activity和View都能接收触摸和按键,如果响应事件只需要在继承类里复写事件函数即可:当一个视图(如一个按钮)被触摸时,该对象上的 onTouchEvent() 方法会被调用.不过,为了侦听这个 ...

  9. SenchaTouch调用纯数字键盘

    items:[ { itemId:"phoneNumber", xtype: "textfield", component:{xtype:"input ...

随机推荐

  1. Android读书笔记三

    通过一章的学习体会到Git的重要性,因为想要获取开源的源代码,必须要使用Git,而且Linux内核完全是由Git管理的.Git是对源代码进行管理,在使用之前需要先安装,命令是 (1)apt-get i ...

  2. Codevs1081 线段树练习 2

    题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]的所有数都增加X 2:询问第i个数是什么? 输入描述 Input Description 第一行一个正整数n,接下来n行n ...

  3. 数据结构实用C语言基础

    大纲: 主要介绍了C语言中的指针,内存分配,两种传参方式,typedef的简单用法 关于C语言中的指针: 指针变量也称为指针(Pointer) 例如:int* p; 则p为一个指向int类型的指针. ...

  4. spdlog&rapidjson 使用记录

    项目中需要记录log以及读写json,对比后选择了spdlog以及rapidjson. SPDLog 对于log只是要求能够记录到文件中以及能够过滤,选择spdlog是因为这个只需要包含头文件即可使用 ...

  5. Spring boot接受json赋值给java对象

    Spring boot接受json赋值给java对象 新建 模板 小书匠 前言 写这个东西,一方面是我自己在做项目的时候,对json的使用还不是十分的熟悉,对spring boot的使用也不是很熟悉, ...

  6. VS自学日记整理

    vs渣渣自学之旅 一.vs实用插件 二.制作简历之旅 1.一堆错误示范示范 2.标签的使用 3.文件的文本的样式的保存 二.美化博客园之旅 1.第一天 学python有点多这个慢慢消化

  7. 优酷项目之 ORM(数据库对象关系映射)代码重写

    前言: 我们在操作数据库时候一般都是通过sql代码来操作mysql数据库中相关数据,这就需要懂得sql语句,那么怎么样才能在不懂sql语句的情况下通过我们所学的python代码来实现对mysql数据库 ...

  8. Linux 关于SELinux的命令及使用

    1. 模式的设置 : 修改/etc/selinux/config文件中的SELINUX=”" 的值 ,然后重启.enforcing:强制模式,只要selinux不允许,就无法执行 permi ...

  9. C指针问题

    <!DOCTYPE html> 多级c指针传值问题 /* GitHub stylesheet for MarkdownPad (http://markdownpad.com) / / Au ...

  10. Linux的档案权限与目录配置

    重点回顾:1.Linux的每个档案中,依据权限分为使用者.群组与其他人三种身份 2.群组最有用的功能之一,就是当你在团队开发资源的时候,且每个账号都可以有多个群组的支持 3.利用"ls -l ...