public static boolean isNavigationBarShow(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { Display display = activity.getWindowManager().getDefaultDisplay(); Point size = new Point(); Point realSize = new Point(); display.getSize(size); display.getRealSize(realSize); return realSize.y != size.y; } else { boolean menu = ViewConfiguration.get(activity).hasPermanentMenuKey(); boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if (menu || back) { return false; } else { return true; } } }
/** * Send a dtmf signal to a call * * @param callId the call to send the signal * @param keyCode the keyCode to send (android style) * @return */ public int sendDtmf(int callId, int keyCode) throws SameThreadException { if (!created) { return -1; } String keyPressed = ""; // Since some device (xoom...) are apparently buggy with key character // map loading... // we have to do crappy thing here if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) { keyPressed = Integer.toString(keyCode - KeyEvent.KEYCODE_0); } else if (keyCode == KeyEvent.KEYCODE_POUND) { keyPressed = "#"; } else if (keyCode == KeyEvent.KEYCODE_STAR) { keyPressed = "*"; } else { // Fallback... should never be there if using visible dialpad, but // possible using keyboard KeyCharacterMap km = KeyCharacterMap.load(KeyCharacterMap.NUMERIC); keyPressed = Integer.toString(km.getNumber(keyCode)); } return sendDtmf(callId, keyPressed); }
public static boolean isNavigationBarShow(Activity activity){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { Display display = activity.getWindowManager().getDefaultDisplay(); Point size = new Point(); Point realSize = new Point(); display.getSize(size); display.getRealSize(realSize); return realSize.y!=size.y; }else { boolean menu = ViewConfiguration.get(activity).hasPermanentMenuKey(); boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if(menu || back) { return false; }else { return true; } } }
static int getNavBarHeight(Context c) { int result = 0; boolean hasMenuKey = ViewConfiguration.get(c).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if (!hasMenuKey && !hasBackKey) { // The device has a navigation bar Resources res = c.getResources(); int orientation = res.getConfiguration().orientation; int resourceId; if (isTablet(c)) { resourceId = res.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); } else { resourceId = res.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "android"); } if (resourceId > 0) { return res.getDimensionPixelSize(resourceId); } } return result; }
public static int getNavBarHeight(Context context) { int result = 0; boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if(!hasMenuKey && !hasBackKey) { //The device has a navigation bar Resources resources = context.getResources(); int orientation = context.getResources().getConfiguration().orientation; int resourceId; if (isTablet(context)){ resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); } else { resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "android"); } if (resourceId > 0) { return context.getResources().getDimensionPixelSize(resourceId); } } return result; }
public void handleMessage(Message m) { switch (m.what) { case MSG_INJECT_KEY: final long eventTime = SystemClock.uptimeMillis(); final InputManager inputManager = (InputManager) XposedHelpers.callStaticMethod(InputManager.class, "getInstance"); int flags = KeyEvent.FLAG_FROM_SYSTEM; XposedHelpers.callMethod(inputManager, "injectInputEvent", new KeyEvent(eventTime - 50, eventTime - 50, KeyEvent.ACTION_DOWN, m.arg1, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags, InputDevice.SOURCE_UNKNOWN), 0); XposedHelpers.callMethod(inputManager, "injectInputEvent", new KeyEvent(eventTime - 50, eventTime - 25, KeyEvent.ACTION_UP, m.arg1, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags, InputDevice.SOURCE_UNKNOWN), 0); break; } }
public static void injectKey(final int keyCode) { Handler handler = (Handler) XposedHelpers.getObjectField(mPhoneWindowManager, "mHandler"); if (handler == null) return; handler.post(new Runnable() { @Override public void run() { try { final long eventTime = SystemClock.uptimeMillis(); final InputManager inputManager = (InputManager) mContext.getSystemService(Context.INPUT_SERVICE); int flags = KeyEvent.FLAG_FROM_SYSTEM; XposedHelpers.callMethod(inputManager, "injectInputEvent", new KeyEvent(eventTime - 50, eventTime - 50, KeyEvent.ACTION_DOWN, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags, InputDevice.SOURCE_UNKNOWN), 0); XposedHelpers.callMethod(inputManager, "injectInputEvent", new KeyEvent(eventTime - 50, eventTime - 25, KeyEvent.ACTION_UP, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags, InputDevice.SOURCE_UNKNOWN), 0); } catch (Throwable t) { XposedBridge.log(t); } } }); }
public static int getNavigationBarHeight(Context context) { boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME); if (hasBackKey && hasHomeKey) { return 0; } else { // Resources resources = context.getResources(); int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId); } return 0; } }
/** * 取得NavigationBar的高度 * * @param c * @return */ public static int getNavigationBarHeight(Context c) { int result = 0; boolean hasMenuKey = ViewConfiguration.get(c).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if (!hasMenuKey && !hasBackKey) { //The device has a navigation bar Resources resources = c.getResources(); int orientation = resources.getConfiguration().orientation; int resourceId; if (isTablet(c)) { resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); } else { resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "android"); } if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId); } } return result; }
private static int getNavBarHeight(Context context) { boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); boolean hasNavBar = !hasMenuKey && !hasBackKey; if (hasNavBar) { boolean isPortrait = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; boolean isTablet = (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; String key = isPortrait ? "navigation_bar_height" : (isTablet ? "navigation_bar_height_landscape" : null); return key == null ? 0 : getDimenSize(context, key); } else { return 0; } }
/** * Send keys and blocks until the first specified accessibility event. * * Most key presses will cause some UI change to occur. If the device is busy, this will * block until the device begins to process the key press at which point the call returns * and normal wait for idle processing may begin. If no events are detected for the * timeout period specified, the call will return anyway with false. * * @param keyCode * @param metaState * @param eventType * @param timeout * @return true if events is received, otherwise false. */ public boolean sendKeyAndWaitForEvent(final int keyCode, final int metaState, final int eventType, long timeout) { Runnable command = new Runnable() { @Override public void run() { final long eventTime = SystemClock.uptimeMillis(); KeyEvent downEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD); if (injectEventSync(downEvent)) { KeyEvent upEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyCode, 0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD); injectEventSync(upEvent); } } }; return runAndWaitForEvents(command, new WaitForAnyEventPredicate(eventType), timeout) != null; }
public static boolean hasNavBar(Context context) { boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME); if (hasBackKey && hasHomeKey) { if (Build.MANUFACTURER.toLowerCase().contains("samsung") && !Build.MODEL.toLowerCase().contains("nexus")) { return false; } Resources resources = context.getResources(); int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); if (id > 0) { return resources.getBoolean(id); } else { return false; } } else { return true; } }
/** * 底部虚拟导航是否显示 * @param activity activity * @return boolean */ public static boolean isNavigationBarShow(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { Display display = activity.getWindowManager().getDefaultDisplay(); Point size = new Point(); Point realSize = new Point(); display.getSize(size); display.getRealSize(realSize); return realSize.y != size.y; } else { boolean menu = ViewConfiguration.get(activity).hasPermanentMenuKey(); boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if (menu || back) { return false; } else { return true; } } }
public static int getNavBarHeight(Context context) { int result = 0; boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if(!hasMenuKey && !hasBackKey) { //The device has a navigation bar Resources resources = context.getResources(); int orientation = resources.getConfiguration().orientation; int resourceId; if (isTablet(context)){ resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); } else { resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "android"); } if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId); } } return result; }
public final boolean onKeyShortcut(int paramInt, KeyEvent paramKeyEvent) { Menu localMenu = getMenu(); int i; if (localMenu != null) { if (paramKeyEvent == null) { break label54; } i = paramKeyEvent.getDeviceId(); if (KeyCharacterMap.load(i).getKeyboardType() == 1) { break label60; } } label54: label60: for (boolean bool = true;; bool = false) { localMenu.setQwertyMode(bool); localMenu.performShortcut(paramInt, paramKeyEvent, 0); return true; i = -1; break; } }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (!m_started) return false; m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event); int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState)); int lc=c; m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState); if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) { c = c & KeyCharacterMap.COMBINING_ACCENT_MASK; int composed = KeyEvent.getDeadChar(m_lastChar, c); c = composed; } m_lastChar = lc; // if (keyCode != KeyEvent.KEYCODE_BACK) QtApplication.keyDown(keyCode, c, event.getMetaState()); return true; }
private static boolean areSonyXperiaGamepadKeysSwapped() { // The cross and circle buttons on Sony Xperia phones are swapped // in different regions // http://developer.sonymobile.com/2011/02/13/xperia-play-game-keys/ final char DEFAULT_O_BUTTON_LABEL = 0x25CB; boolean swapped = false; int[] deviceIds = InputDevice.getDeviceIds(); for (int i= 0; deviceIds != null && i < deviceIds.length; i++) { KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(deviceIds[i]); if (keyCharacterMap != null && DEFAULT_O_BUTTON_LABEL == keyCharacterMap.getDisplayLabel(KeyEvent.KEYCODE_DPAD_CENTER)) { swapped = true; break; } } return swapped; }
private KeyEvent [] synthesizeKeyEvents(CharSequence cs) { try { if (mKeyMap == null) { mKeyMap = KeyCharacterMap.load( Versions.preHC ? KeyCharacterMap.ALPHA : KeyCharacterMap.VIRTUAL_KEYBOARD); } } catch (Exception e) { // KeyCharacterMap.UnavailableException is not found on Gingerbread; // besides, it seems like HC and ICS will throw something other than // KeyCharacterMap.UnavailableException; so use a generic Exception here return null; } KeyEvent [] keyEvents = mKeyMap.getEvents(cs.toString().toCharArray()); if (keyEvents == null || keyEvents.length == 0) { return null; } return keyEvents; }
/** * Tries to convert a unicode character to a KeyEvent and if successful sends with keyEvent(). * @param unicodeChar * @param metaState */ public boolean sendUnicode (char unicodeChar, int additionalMetaState) { KeyCharacterMap fullKmap = KeyCharacterMap.load(KeyCharacterMap.FULL); KeyCharacterMap virtualKmap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); char[] s = new char[1]; s[0] = unicodeChar; KeyEvent[] events = fullKmap.getEvents(s); // Failing with the FULL keymap, try the VIRTUAL_KEYBOARD one. if (events == null) { events = virtualKmap.getEvents(s); } if (events != null) { for (int i = 0; i < events.length; i++) { KeyEvent evt = events[i]; processLocalKeyEvent(evt.getKeyCode(), evt, additionalMetaState); KeyEvent upEvt = new KeyEvent(KeyEvent.ACTION_UP, evt.getKeyCode()); processLocalKeyEvent(upEvt.getKeyCode(), upEvt, additionalMetaState); return true; } } else { android.util.Log.e("RemoteKeyboard", "Could not use any keymap to generate KeyEvent for unicode: " + unicodeChar); } return false; }
public static boolean hasNavBar(Context context) { boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME); if (hasBackKey && hasHomeKey) { if (Build.MANUFACTURER.toLowerCase(Locale.ENGLISH).contains("samsung") && !Build.MODEL.toLowerCase(Locale.ENGLISH).contains("nexus")) { return false; } Resources resources = context.getResources(); int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); if (id > 0) { return resources.getBoolean(id); } else { return false; } } else { return true; } }
public boolean onKeyShortcut(int i, KeyEvent keyevent) { Menu menu = getMenu(); if (menu != null) { int j; boolean flag; if (keyevent != null) { j = keyevent.getDeviceId(); } else { j = -1; } if (KeyCharacterMap.load(j).getKeyboardType() != 1) { flag = true; } else { flag = false; } menu.setQwertyMode(flag); menu.performShortcut(i, keyevent, 0); } return true; }
private int getNavBarHeight(Context context) { int result = 0; boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if(!hasMenuKey && !hasBackKey) { //The device has a navigation bar Resources resources = context.getResources(); int orientation = resources.getConfiguration().orientation; int resourceId; if (isTablet){ resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); } else { resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "android"); } if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId); } } return result; }
/** * Sends the key events corresponding to the text to the app being * instrumented. * * @param text The text to be sent. */ public void sendStringSync(String text) { if (text == null) { return; } KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray()); if (events != null) { for (int i = 0; i < events.length; i++) { // We have to change the time of an event before injecting it because // all KeyEvents returned by KeyCharacterMap.getEvents() have the same // time stamp and the system rejects too old events. Hence, it is // possible for an event to become stale before it is injected if it // takes too long to inject the preceding ones. sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0)); } } }
private void sendKeyEventsToTarget(int character) { if (viewRootImpl == null && canGetViewRootImpl) { getViewRootImpl(); } KeyEvent[] events = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD).getEvents(new char[]{(char) character}); try { Method method = viewRootImpl.getClass().getDeclaredMethod("dispatchKeyFromIme", KeyEvent.class); method.setAccessible(true); if (events != null) { final int N = events.length; for (int i = 0; i < N; i++) { KeyEvent event = events[i]; event = KeyEvent.changeFlags(event, event.getFlags() | KeyEvent .FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE); method.invoke(viewRootImpl, event); } } } catch (Exception e) { e.printStackTrace(); LogUtil.e(TAG, "can not dispatch input event"); } }
public void sendDownUpKeyEvents(int keyEventCode) { if (viewRootImpl == null && canGetViewRootImpl) { getViewRootImpl(); } long eventTime = SystemClock.uptimeMillis(); try { Method method = viewRootImpl.getClass().getDeclaredMethod("dispatchKeyFromIme", KeyEvent.class); method.setAccessible(true); method.invoke(viewRootImpl, new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE)); method.invoke(viewRootImpl, new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE)); } catch (Exception e) { e.printStackTrace(); LogUtil.e(TAG, "can not dispatch key from ime"); } }
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public boolean hasSoftwareKeys(Context context) { int sdkVersion = Build.VERSION.SDK_INT; // Gingerbread and below are considered to have physical buttons. if (sdkVersion <= Build.VERSION_CODES.GINGERBREAD_MR1) return false; // Honeycomb is dedicated to the tablets having no physical buttons. if (sdkVersion >= Build.VERSION_CODES.GINGERBREAD_MR1 && sdkVersion <= Build.VERSION_CODES.HONEYCOMB_MR2) return true; // ICS and above provide convenient function able to determine if the // device has // physical buttons or not. // This function is not available below ICS boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); return !hasMenuKey && !hasBackKey; }
@LargeTest public void testInjectKeyEvent() throws InterruptedException { sendActivity = getActivity(); getInstrumentation().waitForIdleSync(); getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { try { KeyCharacterMap keyCharacterMap = UiControllerImpl.getKeyCharacterMap(); KeyEvent[] events = keyCharacterMap.getEvents("a".toCharArray()); injectEventWorked.set(uiController.injectKeyEvent(events[0])); latch.countDown(); } catch (InjectEventSecurityException e) { injectEventThrewSecurityException.set(true); } } }); assertFalse("injectEvent threw a SecurityException", injectEventThrewSecurityException.get()); assertTrue("Timed out!", latch.await(10, TimeUnit.SECONDS)); assertTrue(injectEventWorked.get()); }
protected void injectKey(int keycode) { InputManager inputManager = (InputManager) XposedHelpers .callStaticMethod(InputManager.class, "getInstance"); long now = SystemClock.uptimeMillis(); final KeyEvent downEvent = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, InputDevice.SOURCE_KEYBOARD); final KeyEvent upEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_UP); Integer INJECT_INPUT_EVENT_MODE_ASYNC = XposedHelpers .getStaticIntField(InputManager.class, "INJECT_INPUT_EVENT_MODE_ASYNC"); XposedHelpers.callMethod(inputManager, "injectInputEvent", downEvent, INJECT_INPUT_EVENT_MODE_ASYNC); XposedHelpers.callMethod(inputManager, "injectInputEvent", upEvent, INJECT_INPUT_EVENT_MODE_ASYNC); }
/** * Tries to convert a unicode character to a KeyEvent and if successful sends with keyEvent(). * @param unicodeChar */ private void sendUnicode(char unicodeChar) { KeyCharacterMap fullKmap = KeyCharacterMap.load(KeyCharacterMap.FULL); KeyCharacterMap virtualKmap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); char[] s = new char[1]; s[0] = unicodeChar; KeyEvent[] events = fullKmap.getEvents(s); // Failing with the FULL keymap, try the VIRTUAL_KEYBOARD one. if (events == null) { events = virtualKmap.getEvents(s); } if (events != null) { for (int i = 0; i < events.length; i++) { KeyEvent evt = events[i]; processLocalKeyEvent(evt); } } else { android.util.Log.w(TAG, "Could not use any keymap to generate KeyEvent for unicode: " + unicodeChar); } }
/** * Get the keycode value for AM and PM in the current language. */ private int getAmOrPmKeyCode(int amOrPm) { // Cache the codes. if (mAmKeyCode == -1 || mPmKeyCode == -1) { // Find the first character in the AM/PM text that is unique. KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); char amChar; char pmChar; for (int i = 0; i < Math.max(mAmText.length(), mPmText.length()); i++) { amChar = mAmText.toLowerCase(Locale.getDefault()).charAt(i); pmChar = mPmText.toLowerCase(Locale.getDefault()).charAt(i); if (amChar != pmChar) { KeyEvent[] events = kcm.getEvents(new char[]{amChar, pmChar}); // There should be 4 events: a down and up for both AM and PM. if (events != null && events.length == 4) { mAmKeyCode = events[0].getKeyCode(); mPmKeyCode = events[2].getKeyCode(); } else { Log.e(TAG, "Unable to find keycodes for AM and PM."); } break; } } } if (amOrPm == AM) { return mAmKeyCode; } else if (amOrPm == PM) { return mPmKeyCode; } return -1; }
/** * 判断手机是否含有虚拟按键 99% * * @return */ public static boolean hasVirtualNavigationBar(Context context) { boolean hasSoftwareKeys = true; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { Display d = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); DisplayMetrics realDisplayMetrics = new DisplayMetrics(); d.getRealMetrics(realDisplayMetrics); int realHeight = realDisplayMetrics.heightPixels; int realWidth = realDisplayMetrics.widthPixels; DisplayMetrics displayMetrics = new DisplayMetrics(); d.getMetrics(displayMetrics); int displayHeight = displayMetrics.heightPixels; int displayWidth = displayMetrics.widthPixels; hasSoftwareKeys = (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0; } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); hasSoftwareKeys = !hasMenuKey && !hasBackKey; } return hasSoftwareKeys; }
@SuppressWarnings("deprecation") void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) { final boolean qwerty = isQwertyMode(); final int metaState = event.getMetaState(); final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); // Get the chars associated with the keyCode (i.e using any chording combo) final boolean isKeyCodeMapped = event.getKeyData(possibleChars); // The delete key is not mapped to '\b' so we treat it specially if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) { return; } // Look for an item whose shortcut is this key. final int N = mItems.size(); for (int i = 0; i < N; i++) { MenuItemImpl item = mItems.get(i); if (item.hasSubMenu()) { ((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event); } final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut(); if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) && (shortcutChar != 0) && (shortcutChar == possibleChars.meta[0] || shortcutChar == possibleChars.meta[2] || (qwerty && shortcutChar == '\b' && keyCode == KeyEvent.KEYCODE_DEL)) && item.isEnabled()) { items.add(item); } } }
@SuppressWarnings("deprecation") MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) { // Get all items that can be associated directly or indirectly with the keyCode ArrayList<MenuItemImpl> items = mTempShortcutItemList; items.clear(); findItemsWithShortcutForKey(items, keyCode, event); if (items.isEmpty()) { return null; } final int metaState = event.getMetaState(); final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); // Get the chars associated with the keyCode (i.e using any chording combo) event.getKeyData(possibleChars); // If we have only one element, we can safely returns it final int size = items.size(); if (size == 1) { return items.get(0); } final boolean qwerty = isQwertyMode(); // If we found more than one item associated with the key, // we have to return the exact match for (int i = 0; i < size; i++) { final MenuItemImpl item = items.get(i); final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut(); if ((shortcutChar == possibleChars.meta[0] && (metaState & KeyEvent.META_ALT_ON) == 0) || (shortcutChar == possibleChars.meta[2] && (metaState & KeyEvent.META_ALT_ON) != 0) || (qwerty && shortcutChar == '\b' && keyCode == KeyEvent.KEYCODE_DEL)) { return item; } } return null; }
/** * Sends a DOWN key event followed by an UP key event to the editor. * * If possible at all, avoid using this method. It causes all sorts of race conditions with * the text view because it goes through a different, asynchronous binder. Also, batch edits * are ignored for key events. Use the normal software input methods instead. * * @param keyCode the key code to send inside the key event. */ private void sendDownUpKeyEvent(final int keyCode) { final long eventTime = SystemClock.uptimeMillis(); mConnection.sendKeyEvent(new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE)); mConnection.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, KeyEvent.ACTION_UP, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE)); }
/** * This translates incoming hard key events in to edit operations on an * InputConnection. It is only needed when using the * PROCESS_HARD_KEYS option. */ private boolean translateKeyDown(int keyCode, KeyEvent event) { mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState, keyCode, event); int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(mMetaState)); mMetaState = MetaKeyKeyListener.adjustMetaAfterKeypress(mMetaState); InputConnection ic = getCurrentInputConnection(); if (c == 0 || ic == null) { return false; } boolean dead = false; if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) { dead = true; c = c & KeyCharacterMap.COMBINING_ACCENT_MASK; } if (mComposing.length() > 0) { char accent = mComposing.charAt(mComposing.length() -1 ); int composed = KeyEvent.getDeadChar(accent, c); if (composed != 0) { c = composed; mComposing.setLength(mComposing.length()-1); } } onKey(c, null); return true; }