Android 带有 SpeechRecognizer 的自定义键盘
Android Custom Keyboard with SpeechRecognizer
我有一个功能齐全的自定义 android 键盘,我必须在其中添加语音识别。这是我的实现的相关部分
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 键盘上发生类似的行为:
理想情况下,这可以通过以下方式实现:
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 我无法调用 startActivityForResult。
实现这一目标的理想方法是什么?我应该简单地开始一个没有布局的新 activity 并回调到 inputMethodService 吗?看起来很乱
您的屏幕截图显示 "Google voice typing",这是一个独立的 IME,在按下麦克风按钮时由 Google 键盘调用。因此,您的 IME 应该做同样的事情:用提供语音输入的 IME 替换自己,并希望在语音输入完成后有一个指向您的 IME 的反向链接。
最简单的实施方式是 Switching among IME Subtypes,但您可能希望拥有更多控制权,例如使用特定的输入参数等启动特定的 IME。我不确定 best/standard 实现这种额外控制的方法是什么。
有关语音输入 IME 的示例,您可以查看(我的应用程序)Kõnele。
解决方案的简单实现:
// 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,只需关闭它,它就会退回到之前的输入法
我有一个功能齐全的自定义 android 键盘,我必须在其中添加语音识别。这是我的实现的相关部分
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 键盘上发生类似的行为:
理想情况下,这可以通过以下方式实现:
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 我无法调用 startActivityForResult。 实现这一目标的理想方法是什么?我应该简单地开始一个没有布局的新 activity 并回调到 inputMethodService 吗?看起来很乱
您的屏幕截图显示 "Google voice typing",这是一个独立的 IME,在按下麦克风按钮时由 Google 键盘调用。因此,您的 IME 应该做同样的事情:用提供语音输入的 IME 替换自己,并希望在语音输入完成后有一个指向您的 IME 的反向链接。
最简单的实施方式是 Switching among IME Subtypes,但您可能希望拥有更多控制权,例如使用特定的输入参数等启动特定的 IME。我不确定 best/standard 实现这种额外控制的方法是什么。
有关语音输入 IME 的示例,您可以查看(我的应用程序)Kõnele。
解决方案的简单实现:
// 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,只需关闭它,它就会退回到之前的输入法