Retain voice input across orientation changes. Fixes 2428545
If an configuration change happens when voice is being captured or
processed, it keeps the voice input state intact and reattaches the
recognition view to the input method.
diff --git a/res/layout/recognition_status.xml b/res/layout/recognition_status.xml
index ea23824..1ec06ba 100644
--- a/res/layout/recognition_status.xml
+++ b/res/layout/recognition_status.xml
@@ -67,6 +67,7 @@
android:layout_gravity="center_horizontal"
android:visibility="gone"
android:indeterminate="true"
+ android:indeterminateOnly="false"
/>
diff --git a/src/com/android/inputmethod/latin/LatinIME.java b/src/com/android/inputmethod/latin/LatinIME.java
index cb3711c..43972d9 100644
--- a/src/com/android/inputmethod/latin/LatinIME.java
+++ b/src/com/android/inputmethod/latin/LatinIME.java
@@ -50,6 +50,8 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewParent;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
@@ -221,6 +223,7 @@
private VoiceInput mVoiceInput;
private VoiceResults mVoiceResults = new VoiceResults();
private long mSwipeTriggerTimeMillis;
+ private boolean mConfigurationChanging;
// For each word, a list of potential replacements, usually from voice.
private Map<String, List<CharSequence>> mWordToSuggestions =
@@ -371,7 +374,12 @@
mOrientation = conf.orientation;
reloadKeyboards();
}
+ mConfigurationChanging = true;
super.onConfigurationChanged(conf);
+ if (mRecognizing) {
+ switchToRecognitionStatusView();
+ }
+ mConfigurationChanging = false;
}
@Override
@@ -388,21 +396,6 @@
}
@Override
- public void onInitializeInterface() {
- // Create a new view associated with voice input if the old
- // view is stuck in another layout (e.g. if switching from
- // portrait to landscape while speaking)
- // NOTE: This must be done here because for some reason
- // onCreateInputView isn't called after an orientation change while
- // speech rec is in progress.
- if (mVoiceInput != null && mVoiceInput.getView().getParent() != null) {
- mVoiceInput.newView();
- }
-
- super.onInitializeInterface();
- }
-
- @Override
public View onCreateCandidatesView() {
mKeyboardSwitcher.makeKeyboards(true);
mCandidateViewContainer = (CandidateViewContainer) getLayoutInflater().inflate(
@@ -554,20 +547,16 @@
public void onFinishInput() {
super.onFinishInput();
- if (VOICE_INSTALLED && mAfterVoiceInput) {
- mVoiceInput.logInputEnded();
- }
-
- if (VOICE_INSTALLED) {
+ if (VOICE_INSTALLED && !mConfigurationChanging) {
+ if (mAfterVoiceInput) {
+ mVoiceInput.logInputEnded();
+ }
mVoiceInput.flushLogs();
+ mVoiceInput.cancel();
}
-
if (mInputView != null) {
mInputView.closing();
}
- if (VOICE_INSTALLED && mRecognizing) {
- mVoiceInput.cancel();
- }
}
@Override
@@ -654,23 +643,21 @@
@Override
public void hideWindow() {
- if (mAfterVoiceInput) mVoiceInput.logInputEnded();
if (TRACE) Debug.stopMethodTracing();
if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
mOptionsDialog.dismiss();
mOptionsDialog = null;
}
- if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
- mVoiceInput.logKeyboardWarningDialogDismissed();
- mVoiceWarningDialog.dismiss();
- mVoiceWarningDialog = null;
- }
- if (mTutorial != null) {
- mTutorial.close();
- mTutorial = null;
- }
- if (VOICE_INSTALLED & mRecognizing) {
- mVoiceInput.cancel();
+ if (!mConfigurationChanging) {
+ if (mAfterVoiceInput) mVoiceInput.logInputEnded();
+ if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
+ mVoiceInput.logKeyboardWarningDialogDismissed();
+ mVoiceWarningDialog.dismiss();
+ mVoiceWarningDialog = null;
+ }
+ if (VOICE_INSTALLED & mRecognizing) {
+ mVoiceInput.cancel();
+ }
}
super.hideWindow();
TextEntryState.endSession();
@@ -1211,12 +1198,21 @@
}
private void switchToRecognitionStatusView() {
- mHandler.post(new Runnable() {
- public void run() {
- mRecognizing = true;
- setInputView(mVoiceInput.getView());
- updateInputViewShown();
- }});
+ final boolean configChanged = mConfigurationChanging;
+ mHandler.post(new Runnable() {
+ public void run() {
+ mRecognizing = true;
+ View v = mVoiceInput.getView();
+ ViewParent p = v.getParent();
+ if (p != null && p instanceof ViewGroup) {
+ ((ViewGroup)v.getParent()).removeView(v);
+ }
+ setInputView(v);
+ updateInputViewShown();
+ if (configChanged) {
+ mVoiceInput.onConfigurationChanged();
+ }
+ }});
}
private void startListening(boolean swipe) {
diff --git a/src/com/android/inputmethod/voice/RecognitionView.java b/src/com/android/inputmethod/voice/RecognitionView.java
index 5d4a0e0..1e99c3c 100644
--- a/src/com/android/inputmethod/voice/RecognitionView.java
+++ b/src/com/android/inputmethod/voice/RecognitionView.java
@@ -16,7 +16,12 @@
package com.android.inputmethod.voice;
-import com.android.inputmethod.latin.R;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.ShortBuffer;
+import java.util.ArrayList;
+import java.util.List;
import android.content.ContentResolver;
import android.content.Context;
@@ -35,14 +40,10 @@
import android.view.View.OnClickListener;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.ImageView;
+import android.widget.ProgressBar;
import android.widget.TextView;
-import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-import java.util.ArrayList;
-import java.util.List;
+import com.android.inputmethod.latin.R;
/**
* The user interface for the "Speak now" and "working" states.
@@ -103,7 +104,6 @@
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mView = inflater.inflate(R.layout.recognition_status, null);
-
ContentResolver cr = context.getContentResolver();
mMinMicrophoneLevel = SettingsUtil.getSettingsFloat(
cr, SettingsUtil.LATIN_IME_MIN_MICROPHONE_LEVEL, 15.f);
@@ -139,6 +139,18 @@
return mView;
}
+ public void restoreState() {
+ mUiHandler.post(new Runnable() {
+ public void run() {
+ // Restart the spinner
+ if (mState == State.WORKING) {
+ ((ProgressBar)mProgress).setIndeterminate(false);
+ ((ProgressBar)mProgress).setIndeterminate(true);
+ }
+ }
+ });
+ }
+
public void showInitializing() {
mUiHandler.post(new Runnable() {
public void run() {
diff --git a/src/com/android/inputmethod/voice/VoiceInput.java b/src/com/android/inputmethod/voice/VoiceInput.java
index a2e2105..e881856 100644
--- a/src/com/android/inputmethod/voice/VoiceInput.java
+++ b/src/com/android/inputmethod/voice/VoiceInput.java
@@ -162,6 +162,14 @@
}
/**
+ * The configuration of the IME changed and may have caused the views to be layed out
+ * again. Restore the state of the recognition view.
+ */
+ public void onConfigurationChanged() {
+ mRecognitionView.restoreState();
+ }
+
+ /**
* @return true if field is blacklisted for voice
*/
public boolean isBlacklistedField(FieldContext context) {