diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index b5dd3eed4..5db6e63d0 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -700,6 +700,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha mInputView.setOnKeyboardActionListener(mInputMethodService); mLayoutId = newLayout; } + // TODO: Not to post if this function was called from loadKeyboardView mInputMethodService.mHandler.post(new Runnable() { public void run() { if (mInputView != null) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 6554954ee..d069e00fb 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -632,8 +632,7 @@ public class LatinIME extends InputMethodService checkTutorial(attribute.privateImeOptions); inputView.setForeground(true); - // TODO: Not to show keyboard if IME starts in Voice One shot mode. - mVoiceConnector.onStartInputView(); + mVoiceConnector.onStartInputView(mKeyboardSwitcher.getInputView().getWindowToken()); if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java index 4fcfe01ba..ac68e3c39 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import com.android.inputmethod.latin.BaseKeyboard.Key; +import com.android.inputmethod.voice.VoiceIMEConnector; import android.content.Context; import android.graphics.Canvas; @@ -366,4 +367,10 @@ public class LatinKeyboardView extends BaseKeyboardView { c.drawLine(0, mLastY, getWidth(), mLastY, mPaint); } } + + @Override + protected void onAttachedToWindow() { + // Token is available from here. + VoiceIMEConnector.getInstance().onAttachedToWindow(); + } } diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index df123c9f4..7cf055672 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import com.android.inputmethod.voice.SettingsUtil; +import com.android.inputmethod.voice.VoiceIMEConnector; import com.android.inputmethod.voice.VoiceInput; import android.content.Context; @@ -189,7 +190,10 @@ public class SubtypeSwitcher { mService.onKeyboardLanguageChanged(); } } else if (isVoiceMode()) { - if (languageChanged || modeChanged) { + // If needsToShowWarningDialog is true, voice input need to show warning before + // show recognition view. + if (languageChanged || modeChanged + || VoiceIMEConnector.getInstance().needsToShowWarningDialog()) { if (mVoiceInput != null) { // TODO: Call proper function to trigger VoiceIME mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0); @@ -340,16 +344,15 @@ public class SubtypeSwitcher { /////////////////////////// public boolean setVoiceInput(VoiceInput vi) { - if (mVoiceInput == null) { + if (mVoiceInput == null && vi != null) { // TODO: Remove requirements to construct KeyboardSwitcher // when IME was enabled with Voice mode mService.onKeyboardLanguageChanged(); mVoiceInput = vi; - if (isVoiceMode() && mVoiceInput != null) { + if (isVoiceMode()) { if (DBG) { Log.d(TAG, "Set and call voice input."); } - // TODO: Call proper function to enable VoiceIME mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0); return true; } diff --git a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java index 629d4b45e..359760d3c 100644 --- a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java +++ b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java @@ -96,6 +96,10 @@ public class VoiceIMEConnector implements VoiceInput.UiListener { return sInstance; } + public static VoiceIMEConnector getInstance() { + return sInstance; + } + private void initInternal(LatinIME context, UIHandler h) { mContext = context; mHandler = h; @@ -150,18 +154,32 @@ public class VoiceIMEConnector implements VoiceInput.UiListener { private void showVoiceWarningDialog(final boolean swipe, IBinder token, final boolean configurationChanging) { + if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) { + return; + } AlertDialog.Builder builder = new AlertDialog.Builder(mContext); builder.setCancelable(true); builder.setIcon(R.drawable.ic_mic_dialog); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int whichButton) { mVoiceInput.logKeyboardWarningDialogOk(); reallyStartListening(swipe, configurationChanging); } }); builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int whichButton) { mVoiceInput.logKeyboardWarningDialogCancel(); + switchToLastInputMethod(); + } + }); + // When the dialog is dismissed by user's cancellation, swith back to the last input method. + builder.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface arg0) { + mVoiceInput.logKeyboardWarningDialogCancel(); + switchToLastInputMethod(); } }); @@ -245,6 +263,11 @@ public class VoiceIMEConnector implements VoiceInput.UiListener { return mRecognizing; } + public boolean needsToShowWarningDialog() { + return !mHasUsedVoiceInput + || (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale); + } + public boolean getAndResetIsShowingHint() { boolean ret = mIsShowingHint; mIsShowingHint = false; @@ -425,7 +448,15 @@ public class VoiceIMEConnector implements VoiceInput.UiListener { }}); } + private void switchToLastInputMethod() { + IBinder token = mContext.getWindow().getWindow().getAttributes().token; + mImm.switchToLastInputMethod(token); + } + private void reallyStartListening(boolean swipe, final boolean configurationChanging) { + if (!VOICE_INSTALLED) { + return; + } if (!mHasUsedVoiceInput) { // The user has started a voice input, so remember that in the // future (so we don't show the warning dialog after the first run). @@ -456,9 +487,9 @@ public class VoiceIMEConnector implements VoiceInput.UiListener { public void startListening(final boolean swipe, IBinder token, final boolean configurationChanging) { + // TODO: remove swipe which is no longer used. if (VOICE_INSTALLED) { - if (!mHasUsedVoiceInput || - (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale)) { + if (needsToShowWarningDialog()) { // Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel. showVoiceWarningDialog(swipe, token, configurationChanging); } else { @@ -504,7 +535,17 @@ public class VoiceIMEConnector implements VoiceInput.UiListener { } } - public void onStartInputView() { + public void onStartInputView(IBinder token) { + // If IME is in voice mode, but still needs to show the voice warning dialog, + // keep showing the warning. + if (mSubtypeSwitcher.isVoiceMode() && needsToShowWarningDialog() && token != null) { + showVoiceWarningDialog(false, token, false); + } + } + + public void onAttachedToWindow() { + // After onAttachedToWindow, we can show the voice warning dialog. See startListening() + // above. mSubtypeSwitcher.setVoiceInput(mVoiceInput); } @@ -513,6 +554,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener { switchToRecognitionStatusView(configurationChanging); } } + @Override public void onCancelVoice() { if (mRecognizing) { @@ -521,8 +563,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener { // cancellation etc.), onCancelVoice() will be called first. LatinIME thinks it's // still in voice mode. LatinIME needs to call switchToLastInputMethod(). // Note that onCancelVoice() will be called again from SubtypeSwitcher. - IBinder token = mContext.getWindow().getWindow().getAttributes().token; - mImm.switchToLastInputMethod(token); + switchToLastInputMethod(); } else if (mSubtypeSwitcher.isKeyboardMode()) { // If voice mode is being canceled out of LatinIME (i.e. by user's IME switching or // as a result of switchToLastInputMethod() etc.),