android.view.KeyEvent#KEYCODE_UNKNOWN源码实例Demo

下面列出了android.view.KeyEvent#KEYCODE_UNKNOWN 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。


@Override
public boolean onKeyOther(TextView widget, Spannable text, KeyEvent event) {
    final int movementMetaState = getMovementMetaState(text, event);
    final int keyCode = event.getKeyCode();
    if (keyCode != KeyEvent.KEYCODE_UNKNOWN
            && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
        final int repeat = event.getRepeatCount();
        boolean handled = false;
        for (int i = 0; i < repeat; i++) {
            if (!handleMovementKey(widget, text, keyCode, movementMetaState, event)) {
                break;
            }
            handled = true;
        }
        if (handled) {
            MetaKeyKeyListener.adjustMetaAfterKeypress(text);
            MetaKeyKeyListener.resetLockedMeta(text);
        }
        return handled;
    }
    return false;
}
 

/**
 * Base implementation handles ACTION_MULTIPLE KEYCODE_UNKNOWN by inserting
 * the event's text into the content.
 */
public boolean onKeyOther(View view, Editable content, KeyEvent event) {
    if (event.getAction() != KeyEvent.ACTION_MULTIPLE
            || event.getKeyCode() != KeyEvent.KEYCODE_UNKNOWN) {
        // Not something we are interested in.
        return false;
    }

    int selectionStart = Selection.getSelectionStart(content);
    int selectionEnd = Selection.getSelectionEnd(content);
    if (selectionEnd < selectionStart) {
        int temp = selectionEnd;
        selectionEnd = selectionStart;
        selectionStart = temp;
    }

    CharSequence text = event.getCharacters();
    if (text == null) {
        return false;
    }

    content.replace(selectionStart, selectionEnd, text);
    return true;
}
 

/**
 * Code taken from newer version of the support library located in PlaybackStateCompat.toKeyCode
 * Replace this to PlaybackStateCompat.toKeyCode when React Native updates the support library
 */
private int toKeyCode(long action) {
    if (action == PlaybackStateCompat.ACTION_PLAY) {
        return KeyEvent.KEYCODE_MEDIA_PLAY;
    } else if (action == PlaybackStateCompat.ACTION_PAUSE) {
        return KeyEvent.KEYCODE_MEDIA_PAUSE;
    } else if (action == PlaybackStateCompat.ACTION_SKIP_TO_NEXT) {
        return KeyEvent.KEYCODE_MEDIA_NEXT;
    } else if (action == PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) {
        return KeyEvent.KEYCODE_MEDIA_PREVIOUS;
    } else if (action == PlaybackStateCompat.ACTION_STOP) {
        return KeyEvent.KEYCODE_MEDIA_STOP;
    } else if (action == PlaybackStateCompat.ACTION_FAST_FORWARD) {
        return KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
    } else if (action == PlaybackStateCompat.ACTION_REWIND) {
        return KeyEvent.KEYCODE_MEDIA_REWIND;
    } else if (action == PlaybackStateCompat.ACTION_PLAY_PAUSE) {
        return KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
    }
    return KeyEvent.KEYCODE_UNKNOWN;
}
 
源代码4 项目: android_9.0.0_r45   文件: SearchDialog.java

/**
 * Constructs an intent from the given information and the search dialog state.
 * 
 * @param action Intent action.
 * @param data Intent data, or <code>null</code>.
 * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>.
 * @param query Intent query, or <code>null</code>.
 * @param actionKey The key code of the action key that was pressed,
 *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
 * @param actionMsg The message for the action key that was pressed,
 *        or <code>null</code> if none.
 * @param mode The search mode, one of the acceptable values for
 *             {@link SearchManager#SEARCH_MODE}, or {@code null}.
 * @return The intent.
 */
private Intent createIntent(String action, Uri data, String extraData, String query,
        int actionKey, String actionMsg) {
    // Now build the Intent
    Intent intent = new Intent(action);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // We need CLEAR_TOP to avoid reusing an old task that has other activities
    // on top of the one we want. We don't want to do this in in-app search though,
    // as it can be destructive to the activity stack.
    if (data != null) {
        intent.setData(data);
    }
    intent.putExtra(SearchManager.USER_QUERY, mUserQuery);
    if (query != null) {
        intent.putExtra(SearchManager.QUERY, query);
    }
    if (extraData != null) {
        intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
    }
    if (mAppSearchData != null) {
        intent.putExtra(SearchManager.APP_DATA, mAppSearchData);
    }
    if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
        intent.putExtra(SearchManager.ACTION_KEY, actionKey);
        intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
    }
    intent.setComponent(mSearchable.getSearchActivity());
    return intent;
}
 
源代码5 项目: zhangshangwuda   文件: SearchView.java

/**
 * Constructs an intent from the given information and the search dialog state.
 *
 * @param action Intent action.
 * @param data Intent data, or <code>null</code>.
 * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>.
 * @param query Intent query, or <code>null</code>.
 * @param actionKey The key code of the action key that was pressed,
 *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
 * @param actionMsg The message for the action key that was pressed,
 *        or <code>null</code> if none.
 * @return The intent.
 */
private Intent createIntent(String action, Uri data, String extraData, String query,
                                                        int actionKey, String actionMsg) {
    // Now build the Intent
    Intent intent = new Intent(action);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // We need CLEAR_TOP to avoid reusing an old task that has other activities
    // on top of the one we want. We don't want to do this in in-app search though,
    // as it can be destructive to the activity stack.
    if (data != null) {
        intent.setData(data);
    }
    intent.putExtra(SearchManager.USER_QUERY, mUserQuery);
    if (query != null) {
        intent.putExtra(SearchManager.QUERY, query);
    }
    if (extraData != null) {
        intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
    }
    if (mAppSearchData != null) {
        intent.putExtra(SearchManager.APP_DATA, mAppSearchData);
    }
    if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
        intent.putExtra(SearchManager.ACTION_KEY, actionKey);
        intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
    }
    intent.setComponent(mSearchable.getSearchActivity());
    return intent;
}
 

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (mPopup.onKeyDown(keyCode, event)) {
        return true;
    }

    if (!isPopupShowing()) {
        switch(keyCode) {
        case KeyEvent.KEYCODE_DPAD_DOWN:
            if (event.hasNoModifiers()) {
                performValidation();
            }
        }
    }

    if (isPopupShowing() && keyCode == KeyEvent.KEYCODE_TAB && event.hasNoModifiers()) {
        return true;
    }

    mLastKeyCode = keyCode;
    boolean handled = super.onKeyDown(keyCode, event);
    mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN;

    if (handled && isPopupShowing()) {
        clearListSelection();
    }

    return handled;
}
 

public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
    int code = event.getKeyCode();
    if (code != KeyEvent.KEYCODE_UNKNOWN
            && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
        int repeat = event.getRepeatCount();
        boolean handled = false;
        while ((--repeat) > 0) {
            handled |= executeDown(view, text, code,event);
        }
        return handled;
    }
    return false;
}
 
源代码8 项目: CSipSimple   文件: SearchView.java

/**
 * Constructs an intent from the given information and the search dialog state.
 *
 * @param action Intent action.
 * @param data Intent data, or <code>null</code>.
 * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>.
 * @param query Intent query, or <code>null</code>.
 * @param actionKey The key code of the action key that was pressed,
 *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
 * @param actionMsg The message for the action key that was pressed,
 *        or <code>null</code> if none.
 * @return The intent.
 */
private Intent createIntent(String action, Uri data, String extraData, String query,
                                                        int actionKey, String actionMsg) {
    // Now build the Intent
    Intent intent = new Intent(action);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // We need CLEAR_TOP to avoid reusing an old task that has other activities
    // on top of the one we want. We don't want to do this in in-app search though,
    // as it can be destructive to the activity stack.
    if (data != null) {
        intent.setData(data);
    }
    intent.putExtra(SearchManager.USER_QUERY, mUserQuery);
    if (query != null) {
        intent.putExtra(SearchManager.QUERY, query);
    }
    if (extraData != null) {
        intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
    }
    if (mAppSearchData != null) {
        intent.putExtra(SearchManager.APP_DATA, mAppSearchData);
    }
    if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
        intent.putExtra(SearchManager.ACTION_KEY, actionKey);
        intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
    }
    intent.setComponent(mSearchable.getSearchActivity());
    return intent;
}
 

/**
 * Not undoable
 *
 * @param symbolicName key code's symbolic name
 * @return op that sends the given code
 */
@Override
public Op keyCodeStr(String symbolicName) {
    int code = KeyEvent.keyCodeFromString("KEYCODE_" + symbolicName);
    if (code != KeyEvent.KEYCODE_UNKNOWN) {
        return keyCode(code);
    }
    return null;
}
 
源代码10 项目: talkback   文件: DefaultKeyComboModel.java

@Override
public boolean isEligibleKeyComboCode(long keyComboCode) {
  if (keyComboCode == KEY_COMBO_CODE_UNASSIGNED) {
    return true;
  }

  // Do not allow to set key combo which is consisted only with modifiers.
  int keyCode = KeyComboManager.getKeyCode(keyComboCode);
  if (KeyEvent.isModifierKey(keyCode) || keyCode == KeyEvent.KEYCODE_UNKNOWN) {
    return false;
  }

  // It's not allowed to use trigger modifier as part of key combo code.
  return (KeyComboManager.getModifier(keyComboCode) & getTriggerModifier()) == 0;
}
 
源代码11 项目: talkback   文件: TalkBackService.java

/**
 * Intended to mimic the behavior of onKeyEvent if this were the only service running. It will be
 * called from onKeyEvent, both from this service and from others in this apk (TalkBack). This
 * method must not block, since it will block onKeyEvent as well.
 *
 * @param keyEvent A key event
 * @return {@code true} if the event is handled, {@code false} otherwise.
 */
@Override
public boolean onKeyEventShared(KeyEvent keyEvent) {
  if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN) {
    // Tapping on fingerprint sensor somehow files KeyEvent with KEYCODE_UNKNOW, which will change
    // input mode to keyboard, and cancel pending accessibility hints. It is OK to just ignore
    // these KeyEvents since they're unused in TalkBack.
    return false;
  }
  Performance perf = Performance.getInstance();
  EventId eventId = perf.onEventReceived(keyEvent);

  if (isServiceActive()) {
    // Stop the TTS engine when any key (except for volume up/down key) is pressed on physical
    // keyboard.
    if (shouldInterruptByAnyKeyEvent()
        && keyEvent.getDeviceId() != 0
        && keyEvent.getAction() == KeyEvent.ACTION_DOWN
        && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_DOWN
        && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_UP) {
      interruptAllFeedback(false /* stopTtsSpeechCompletely */);
    }
  }

  for (ServiceKeyEventListener listener : keyEventListeners) {
    if (!isServiceActive() && !listener.processWhenServiceSuspended()) {
      continue;
    }

    if (listener.onKeyEvent(keyEvent, eventId)) {
      perf.onHandlerDone(eventId);
      return true;
    }
  }

  return false;
}
 

/**
 * Constructs an intent from the given information and the search dialog state.
 *
 * @param action Intent action.
 * @param data Intent data, or <code>null</code>.
 * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>.
 * @param query Intent query, or <code>null</code>.
 * @param actionKey The key code of the action key that was pressed,
 *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
 * @param actionMsg The message for the action key that was pressed,
 *        or <code>null</code> if none.
 * @return The intent.
 */
private Intent createIntent(String action, Uri data, String extraData, String query,
                                                        int actionKey, String actionMsg) {
    // Now build the Intent
    Intent intent = new Intent(action);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // We need CLEAR_TOP to avoid reusing an old task that has other activities
    // on top of the one we want. We don't want to do this in in-app search though,
    // as it can be destructive to the activity stack.
    if (data != null) {
        intent.setData(data);
    }
    intent.putExtra(SearchManager.USER_QUERY, mUserQuery);
    if (query != null) {
        intent.putExtra(SearchManager.QUERY, query);
    }
    if (extraData != null) {
        intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
    }
    if (mAppSearchData != null) {
        intent.putExtra(SearchManager.APP_DATA, mAppSearchData);
    }
    if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
        intent.putExtra(SearchManager.ACTION_KEY, actionKey);
        intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
    }
    intent.setComponent(mSearchable.getSearchActivity());
    return intent;
}
 
源代码13 项目: Noyze   文件: VolumeAccessibilityService.java

protected void updateDisabledButtons(SharedPreferences prefs) {
    String value = prefs.getString(
            Constants.PREF_DISABLED_BUTTONS, String.valueOf(disabledButtons));
    try {
        disabledButtons = Integer.parseInt(value, 10);
    } catch (NumberFormatException nfe) {
        LOGE(TAG, "Error with " + Constants.PREF_DISABLED_BUTTONS + " formatting: " + value);
        disabledButtons = KeyEvent.KEYCODE_UNKNOWN;
    }
}
 

public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
    int code = event.getKeyCode();
    if (code != KeyEvent.KEYCODE_UNKNOWN
            && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
        int repeat = event.getRepeatCount();
        boolean handled = false;
        while ((--repeat) > 0) {
            handled |= executeDown(view, text, code,event);
        }
        return handled;
    }
    return false;
}
 
源代码15 项目: Noyze   文件: VolumeAccessibilityService.java

protected void updateDisabledButtons(SharedPreferences prefs) {
    String value = prefs.getString(
            Constants.PREF_DISABLED_BUTTONS, String.valueOf(disabledButtons));
    try {
        disabledButtons = Integer.parseInt(value, 10);
    } catch (NumberFormatException nfe) {
        LOGE(TAG, "Error with " + Constants.PREF_DISABLED_BUTTONS + " formatting: " + value);
        disabledButtons = KeyEvent.KEYCODE_UNKNOWN;
    }
}
 
源代码16 项目: openboard   文件: RichInputConnection.java

public void sendKeyEvent(final KeyEvent keyEvent) {
    if (DEBUG_BATCH_NESTING) checkBatchEdit();
    if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        // This method is only called for enter or backspace when speaking to old applications
        // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits.
        // When talking to new applications we never use this method because it's inherently
        // racy and has unpredictable results, but for backward compatibility we continue
        // sending the key events for only Enter and Backspace because some applications
        // mistakenly catch them to do some stuff.
        switch (keyEvent.getKeyCode()) {
        case KeyEvent.KEYCODE_ENTER:
            mCommittedTextBeforeComposingText.append("\n");
            mExpectedSelStart += 1;
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_DEL:
            if (0 == mComposingText.length()) {
                if (mCommittedTextBeforeComposingText.length() > 0) {
                    mCommittedTextBeforeComposingText.delete(
                            mCommittedTextBeforeComposingText.length() - 1,
                            mCommittedTextBeforeComposingText.length());
                }
            } else {
                mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
            }
            if (mExpectedSelStart > 0 && mExpectedSelStart == mExpectedSelEnd) {
                // TODO: Handle surrogate pairs.
                mExpectedSelStart -= 1;
            }
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_UNKNOWN:
            if (null != keyEvent.getCharacters()) {
                mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
                mExpectedSelStart += keyEvent.getCharacters().length();
                mExpectedSelEnd = mExpectedSelStart;
            }
            break;
        default:
            final String text = StringUtils.newSingleCodePointString(keyEvent.getUnicodeChar());
            mCommittedTextBeforeComposingText.append(text);
            mExpectedSelStart += text.length();
            mExpectedSelEnd = mExpectedSelStart;
            break;
        }
    }
    if (isConnected()) {
        mIC.sendKeyEvent(keyEvent);
    }
}
 

public void sendKeyEvent(final KeyEvent keyEvent) {
    if (DEBUG_BATCH_NESTING) checkBatchEdit();
    if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        // This method is only called for enter or backspace when speaking to old applications
        // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits.
        // When talking to new applications we never use this method because it's inherently
        // racy and has unpredictable results, but for backward compatibility we continue
        // sending the key events for only Enter and Backspace because some applications
        // mistakenly catch them to do some stuff.
        switch (keyEvent.getKeyCode()) {
        case KeyEvent.KEYCODE_ENTER:
            mCommittedTextBeforeComposingText.append("\n");
            mExpectedSelStart += 1;
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_DEL:
            if (0 == mComposingText.length()) {
                if (mCommittedTextBeforeComposingText.length() > 0) {
                    mCommittedTextBeforeComposingText.delete(
                            mCommittedTextBeforeComposingText.length() - 1,
                            mCommittedTextBeforeComposingText.length());
                }
            } else {
                mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
            }

            if (mExpectedSelStart > 0 && mExpectedSelStart == mExpectedSelEnd) {
                // TODO: Handle surrogate pairs.
                mExpectedSelStart -= 1;
            }
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_UNKNOWN:
            if (null != keyEvent.getCharacters()) {
                mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
                mExpectedSelStart += keyEvent.getCharacters().length();
                mExpectedSelEnd = mExpectedSelStart;
            }
            break;
        default:
            final String text = StringUtils.newSingleCodePointString(keyEvent.getUnicodeChar());
            mCommittedTextBeforeComposingText.append(text);
            mExpectedSelStart += text.length();
            mExpectedSelEnd = mExpectedSelStart;
            break;
        }
    }
    if (isConnected()) {
        mIC.sendKeyEvent(keyEvent);
    }
}
 

public void sendKeyEvent(final KeyEvent keyEvent) {
    if (DEBUG_BATCH_NESTING) checkBatchEdit();
    if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        // This method is only called for enter or backspace when speaking to old applications
        // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits.
        // When talking to new applications we never use this method because it's inherently
        // racy and has unpredictable results, but for backward compatibility we continue
        // sending the key events for only Enter and Backspace because some applications
        // mistakenly catch them to do some stuff.
        switch (keyEvent.getKeyCode()) {
        case KeyEvent.KEYCODE_ENTER:
            mCommittedTextBeforeComposingText.append("\n");
            if (hasCursorPosition()) {
                mExpectedSelStart += 1;
                mExpectedSelEnd = mExpectedSelStart;
            }
            break;
        case KeyEvent.KEYCODE_DEL:
            if (0 == mComposingText.length()) {
                if (mCommittedTextBeforeComposingText.length() > 0) {
                    mCommittedTextBeforeComposingText.delete(
                            mCommittedTextBeforeComposingText.length() - 1,
                            mCommittedTextBeforeComposingText.length());
                }
            } else {
                mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
            }

            if (mExpectedSelStart > 0 && mExpectedSelStart == mExpectedSelEnd) {
                // TODO: Handle surrogate pairs.
                mExpectedSelStart -= 1;
            }
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_UNKNOWN:
            if (null != keyEvent.getCharacters()) {
                mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
                if (hasCursorPosition()) {
                    mExpectedSelStart += keyEvent.getCharacters().length();
                    mExpectedSelEnd = mExpectedSelStart;
                }
            }
            break;
        default:
            final String text = StringUtils.newSingleCodePointString(keyEvent.getUnicodeChar());
            mCommittedTextBeforeComposingText.append(text);
            if (hasCursorPosition()) {
                mExpectedSelStart += text.length();
                mExpectedSelEnd = mExpectedSelStart;
            }
            break;
        }
    }
    if (isConnected()) {
        mIC.sendKeyEvent(keyEvent);
    }
}
 

public void sendKeyEvent(final KeyEvent keyEvent) {
    if (DEBUG_BATCH_NESTING) checkBatchEdit();
    if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        // This method is only called for enter or backspace when speaking to old applications
        // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits.
        // When talking to new applications we never use this method because it's inherently
        // racy and has unpredictable results, but for backward compatibility we continue
        // sending the key events for only Enter and Backspace because some applications
        // mistakenly catch them to do some stuff.
        switch (keyEvent.getKeyCode()) {
        case KeyEvent.KEYCODE_ENTER:
            mCommittedTextBeforeComposingText.append("\n");
            mExpectedSelStart += 1;
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_DEL:
            if (0 == mComposingText.length()) {
                if (mCommittedTextBeforeComposingText.length() > 0) {
                    mCommittedTextBeforeComposingText.delete(
                            mCommittedTextBeforeComposingText.length() - 1,
                            mCommittedTextBeforeComposingText.length());
                }
            } else {
                mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
            }
            if (mExpectedSelStart > 0 && mExpectedSelStart == mExpectedSelEnd) {
                // TODO: Handle surrogate pairs.
                mExpectedSelStart -= 1;
            }
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_UNKNOWN:
            if (null != keyEvent.getCharacters()) {
                mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
                mExpectedSelStart += keyEvent.getCharacters().length();
                mExpectedSelEnd = mExpectedSelStart;
            }
            break;
        default:
            final String text = StringUtils.newSingleCodePointString(keyEvent.getUnicodeChar());
            mCommittedTextBeforeComposingText.append(text);
            mExpectedSelStart += text.length();
            mExpectedSelEnd = mExpectedSelStart;
            break;
        }
    }
    if (isConnected()) {
        mIC.sendKeyEvent(keyEvent);
    }
}
 

public void sendKeyEvent(final KeyEvent keyEvent) {
    if (DEBUG_BATCH_NESTING) checkBatchEdit();
    if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        // This method is only called for enter or backspace when speaking to old applications
        // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits.
        // When talking to new applications we never use this method because it's inherently
        // racy and has unpredictable results, but for backward compatibility we continue
        // sending the key events for only Enter and Backspace because some applications
        // mistakenly catch them to do some stuff.
        switch (keyEvent.getKeyCode()) {
        case KeyEvent.KEYCODE_ENTER:
            mCommittedTextBeforeComposingText.append("\n");
            mExpectedSelStart += 1;
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_DEL:
            if (0 == mComposingText.length()) {
                if (mCommittedTextBeforeComposingText.length() > 0) {
                    mCommittedTextBeforeComposingText.delete(
                            mCommittedTextBeforeComposingText.length() - 1,
                            mCommittedTextBeforeComposingText.length());
                }
            } else {
                mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
            }
            if (mExpectedSelStart > 0 && mExpectedSelStart == mExpectedSelEnd) {
                // TODO: Handle surrogate pairs.
                mExpectedSelStart -= 1;
            }
            mExpectedSelEnd = mExpectedSelStart;
            break;
        case KeyEvent.KEYCODE_UNKNOWN:
            if (null != keyEvent.getCharacters()) {
                mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
                mExpectedSelStart += keyEvent.getCharacters().length();
                mExpectedSelEnd = mExpectedSelStart;
            }
            break;
        default:
            final String text = StringUtils.newSingleCodePointString(keyEvent.getUnicodeChar());
            mCommittedTextBeforeComposingText.append(text);
            mExpectedSelStart += text.length();
            mExpectedSelEnd = mExpectedSelStart;
            break;
        }
    }
    if (isConnected()) {
        mIC.sendKeyEvent(keyEvent);
    }
}
 
 方法所在类
 同类方法