1

У меня есть полностью функциональная пользовательская клавиатура для Android, в которой я должен добавить распознавание речи. Вот соответствующие части реализации у меня естьПользовательская клавиатура Android с SpeechRecognizer

public class CustomInputMethodService 
    extends InputMethodService 
    implements <random stuff> { 

    private SpeechRecognizer mSpeechRecognizer; 
    private RecognitionListener mSpeechlistener; 

    public void onCreate() { 
     super.onCreate(); 
     mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this); 
     mSpeechlistener = new CustomRecognitionListener(); 
     mSpeechRecognizer.setRecognitionListener(mSpeechlistener); 
    } 

    @Override 
    public void onPress(int primaryCode) { 
     if (primaryCode == KeyCodes.VOICE_INPUT) { 
      mSpeechRecognizer.startListening(getSpeechIntent()); 
     }else if(..){ 
      ... 
     } 
    } 

    private Intent getSpeechIntent() { 
     Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 
     speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); 
     speechIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName()); 
     speechIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, false); 
     return speechIntent; 
    } 

} 

Соответствующий метод CustomRecognitionListener просто:

 @Override 
     public void onResults(Bundle results) { 
      ArrayList<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); 
      Log.d(TAG, "onResults: ----> " + matches.get(0)); 
      if(matches != null && matches.size() > 0) { 
       writeText(matches.get(0)); 
      } 
     } 

Этот код работает нормально. Поворот в том, что я хочу, подобное поведение к тому, что происходит на Google клавиатуре, когда УСЭТ вводит ключ микрофона:

enter image description here

Это в идеале достигнуто что-то вроде:

Intent voiceIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 
voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); 
try { 
    startActivityForResult(voiceIntent, Constants.RESULT_SPEECH); 
} catch (ActivityNotFoundException ex) { 
    DebugLog.e(TAG, "Not found excpetion onKeyDown: " + ex); 
} 

Однако , так как прослушиватель клавиш включен, а InputMethodService im не может вызвать startActivityForResult. Каков идеальный способ достичь этого? Должен ли я просто запускать новое действие без макета и иметь обратный вызов для inputMethodService? кажется беспорядочным

+0

Вы смотрели на LatinIME клавиатуре Google, чтобы посмотрите, как это происходит? Мне было слишком много лет, чтобы я помнил, как, но мы просто скопировали это, когда мы сделали это для Swype. –

+0

Спасибо. Я проверил LatinIME и im фактически использовал неправильный подход. Я отправлю ответ через секунду. – Adr3nl

ответ

2

Ваш скриншот показывает «Google voice typing», который является независимым IME, который вызывается Google Keyboard при нажатии на кнопку микрофона. Итак, ваш IME должен сделать то же самое: замените себя IME, который обеспечивает голосовую печать, и надеемся, что после того, как будет выполнена запись голоса, будет обратная ссылка на ваш IME.

Простейшей реализацией будет Switching among IME Subtypes, но вам может потребоваться больше контроля, например. запустите конкретный IME с определенными входными параметрами и т. д. Я не уверен, что является лучшим/стандартным способом достижения этого дополнительного контроля.

Для примера набора символов IME вы можете посмотреть (мое приложение) Kõnele.

+0

Я как раз собирался опубликовать тот же ответ! Да, подход - это именно то, чтобы вызвать текущий IME для голоса Google. как только я нашел, что это сформулировано безупречно – Adr3nl

1

Простая реализация решения:

// on mic tap we call 
public void startVoiceListening() { 
    InputMethodManager imeManager = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE); 
    String voiceExists = voiceExists(imeManager); 
    if (voiceExists != null) { 
     final IBinder token = getWindow().getWindow().getAttributes().token; 
     imeManager.setInputMethod(token,voiceExists); 
    } 
} 

private String voiceExists(InputMethodManager imeManager) { 
    List<InputMethodInfo> list = imeManager.getInputMethodList(); 
    for (InputMethodInfo el : list) { 
     // do something to check whatever IME we want. 
     // in this case "com.google.android.googlequicksearchbox" 
    } 
    return null; 
} 

После того, как мы больше не хотим использовать текущий IME просто закрыть его, и он будет падать обратно на предыдущую

Смежные вопросы