am fb3183ef: am bbd651a0: Change the UI of Voice IME to be more like Voice Search.
* commit 'fb3183efe049798b7dbecdfcbb049009d44b5a66': Change the UI of Voice IME to be more like Voice Search.main
After Width: | Height: | Size: 182 B |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 3.6 KiB |
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2011, The Android Open Source Project
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<gradient
|
||||||
|
android:startColor="#ff000000"
|
||||||
|
android:endColor="#ff000e29"
|
||||||
|
android:angle="90" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2011, The Android Open Source Project
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
||||||
|
<item
|
||||||
|
android:state_window_focused="false"
|
||||||
|
android:state_enabled="true"
|
||||||
|
android:drawable="@drawable/btn_center_default" />
|
||||||
|
<item
|
||||||
|
android:state_pressed="true"
|
||||||
|
android:drawable="@drawable/btn_center_pressed" />
|
||||||
|
<item
|
||||||
|
android:state_focused="true"
|
||||||
|
android:state_enabled="true"
|
||||||
|
android:drawable="@drawable/btn_center_selected" />
|
||||||
|
<item
|
||||||
|
android:state_enabled="true"
|
||||||
|
android:drawable="@drawable/btn_center_default" />
|
||||||
|
<item
|
||||||
|
android:drawable="@drawable/btn_center_default" />
|
||||||
|
</selector>
|
After Width: | Height: | Size: 182 B |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 3.6 KiB |
|
@ -16,83 +16,70 @@
|
||||||
** See the License for the specific language governing permissions and
|
** See the License for the specific language governing permissions and
|
||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:background="@android:color/black"
|
|
||||||
android:paddingBottom="0dip"
|
|
||||||
android:paddingLeft="0dip"
|
|
||||||
android:paddingRight="0dip"
|
|
||||||
>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/main_image"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@drawable/voice_ime_background"
|
|
||||||
android:scaleType="fitXY"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="180dip"
|
|
||||||
android:paddingBottom="2dip"
|
|
||||||
android:paddingTop="2dip"
|
|
||||||
>
|
|
||||||
|
|
||||||
<TextView android:id="@+id/text"
|
|
||||||
android:text="@string/voice_initializing"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_marginTop="15dip"
|
|
||||||
android:textSize="28sp"
|
|
||||||
android:textColor="#ffffff"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ImageView android:id="@+id/image"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_marginTop="20dip"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:src="@drawable/mic_slash_holo"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ProgressBar android:id="@+id/progress"
|
|
||||||
android:layout_height="60dip"
|
|
||||||
android:layout_width="60dip"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:indeterminate="true"
|
|
||||||
android:indeterminateOnly="false"
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout android:id="@+id/button"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@drawable/ok_cancel"
|
|
||||||
android:scaleType="fitXY"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="42dip"
|
android:background="@drawable/background_voice">
|
||||||
android:paddingLeft="1dip"
|
<LinearLayout
|
||||||
android:paddingRight="1dip"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
>
|
android:id="@+id/popup_layout"
|
||||||
|
android:orientation="vertical"
|
||||||
<TextView android:id="@+id/button_text"
|
android:layout_height="0dip"
|
||||||
android:text="@string/cancel"
|
android:layout_width="500dip"
|
||||||
android:layout_height="wrap_content"
|
android:layout_centerInParent="true"
|
||||||
android:layout_width="wrap_content"
|
android:background="@drawable/vs_dialog_red">
|
||||||
android:layout_marginTop="7dip"
|
<TextView
|
||||||
android:textSize="19sp"
|
android:id="@+id/text"
|
||||||
android:textColor="#ffffff"
|
android:text="@string/voice_error"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_height="wrap_content"
|
||||||
/>
|
android:layout_width="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:layout_marginTop="10dip"
|
||||||
|
android:textSize="28sp"
|
||||||
|
android:textColor="#ffffff"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="invisible"/>
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_height="0dip"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_weight="1.0">
|
||||||
|
<com.android.inputmethod.voice.SoundIndicator
|
||||||
|
android:id="@+id/sound_indicator"
|
||||||
|
android:src="@drawable/mic_full"
|
||||||
|
android:background="@drawable/mic_base"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:src="@drawable/mic_slash"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:visibility="visible"/>
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:indeterminateOnly="false"
|
||||||
|
android:layout_height="60dip"
|
||||||
|
android:layout_width="60dip"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="54dip"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:background="@drawable/btn_center"
|
||||||
|
android:textColor="#ffffff"
|
||||||
|
android:textSize="19sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
</RelativeLayout>
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
|
@ -456,7 +456,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
|
|
||||||
mConfigurationChanging = true;
|
mConfigurationChanging = true;
|
||||||
super.onConfigurationChanged(conf);
|
super.onConfigurationChanged(conf);
|
||||||
mVoiceConnector.onConfigurationChanged(mConfigurationChanging);
|
mVoiceConnector.onConfigurationChanged(conf);
|
||||||
mConfigurationChanging = false;
|
mConfigurationChanging = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -439,7 +439,7 @@ public class SubtypeSwitcher {
|
||||||
private void triggerVoiceIME() {
|
private void triggerVoiceIME() {
|
||||||
if (!mService.isInputViewShown()) return;
|
if (!mService.isInputViewShown()) return;
|
||||||
VoiceIMEConnector.getInstance().startListening(false,
|
VoiceIMEConnector.getInstance().startListening(false,
|
||||||
KeyboardSwitcher.getInstance().getInputView().getWindowToken(), false);
|
KeyboardSwitcher.getInstance().getInputView().getWindowToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
|
|
||||||
package com.android.inputmethod.voice;
|
package com.android.inputmethod.voice;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.R;
|
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
@ -29,20 +26,21 @@ import android.graphics.Path;
|
||||||
import android.graphics.PathEffect;
|
import android.graphics.PathEffect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.TypedValue;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup.MarginLayoutParams;
|
import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,79 +56,55 @@ public class RecognitionView {
|
||||||
private View mView;
|
private View mView;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
private ImageView mImage;
|
|
||||||
private TextView mText;
|
private TextView mText;
|
||||||
private View mButton;
|
private ImageView mImage;
|
||||||
private TextView mButtonText;
|
|
||||||
private View mProgress;
|
private View mProgress;
|
||||||
|
private SoundIndicator mSoundIndicator;
|
||||||
|
private Button mButton;
|
||||||
|
|
||||||
private Drawable mInitializing;
|
private Drawable mInitializing;
|
||||||
private Drawable mError;
|
private Drawable mError;
|
||||||
private List<Drawable> mSpeakNow;
|
|
||||||
|
|
||||||
private float mVolume = 0.0f;
|
private static final int INIT = 0;
|
||||||
private int mLevel = 0;
|
private static final int LISTENING = 1;
|
||||||
|
private static final int WORKING = 2;
|
||||||
|
private static final int READY = 3;
|
||||||
|
|
||||||
|
private int mState = INIT;
|
||||||
|
|
||||||
private enum State {LISTENING, WORKING, READY}
|
private final View mPopupLayout;
|
||||||
private State mState = State.READY;
|
|
||||||
|
|
||||||
private float mMinMicrophoneLevel;
|
private final Drawable mListeningBorder;
|
||||||
private float mMaxMicrophoneLevel;
|
private final Drawable mWorkingBorder;
|
||||||
|
private final Drawable mErrorBorder;
|
||||||
/** Updates the microphone icon to show user their volume.*/
|
|
||||||
private Runnable mUpdateVolumeRunnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (mState != State.LISTENING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final float min = mMinMicrophoneLevel;
|
|
||||||
final float max = mMaxMicrophoneLevel;
|
|
||||||
final int maxLevel = mSpeakNow.size() - 1;
|
|
||||||
|
|
||||||
int index = (int) ((mVolume - min) / (max - min) * maxLevel);
|
|
||||||
final int level = Math.min(Math.max(0, index), maxLevel);
|
|
||||||
|
|
||||||
if (level != mLevel) {
|
|
||||||
mImage.setImageDrawable(mSpeakNow.get(level));
|
|
||||||
mLevel = level;
|
|
||||||
}
|
|
||||||
mUiHandler.postDelayed(mUpdateVolumeRunnable, 50);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public RecognitionView(Context context, OnClickListener clickListener) {
|
public RecognitionView(Context context, OnClickListener clickListener) {
|
||||||
mUiHandler = new Handler();
|
mUiHandler = new Handler();
|
||||||
|
|
||||||
mView = LayoutInflater.from(context).inflate(R.layout.recognition_status, null);
|
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
|
||||||
ContentResolver cr = context.getContentResolver();
|
Context.LAYOUT_INFLATER_SERVICE);
|
||||||
mMinMicrophoneLevel = SettingsUtil.getSettingsFloat(
|
|
||||||
cr, SettingsUtil.LATIN_IME_MIN_MICROPHONE_LEVEL, 15.f);
|
mView = inflater.inflate(R.layout.recognition_status, null);
|
||||||
mMaxMicrophoneLevel = SettingsUtil.getSettingsFloat(
|
|
||||||
cr, SettingsUtil.LATIN_IME_MAX_MICROPHONE_LEVEL, 30.f);
|
mPopupLayout= mView.findViewById(R.id.popup_layout);
|
||||||
|
|
||||||
// Pre-load volume level images
|
// Pre-load volume level images
|
||||||
Resources r = context.getResources();
|
Resources r = context.getResources();
|
||||||
|
|
||||||
mSpeakNow = new ArrayList<Drawable>();
|
mListeningBorder = r.getDrawable(R.drawable.vs_dialog_red);
|
||||||
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level0));
|
mWorkingBorder = r.getDrawable(R.drawable.vs_dialog_blue);
|
||||||
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level1));
|
mErrorBorder = r.getDrawable(R.drawable.vs_dialog_yellow);
|
||||||
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level2));
|
|
||||||
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level3));
|
|
||||||
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level4));
|
|
||||||
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level5));
|
|
||||||
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level6));
|
|
||||||
|
|
||||||
mInitializing = r.getDrawable(R.drawable.mic_slash);
|
mInitializing = r.getDrawable(R.drawable.mic_slash);
|
||||||
mError = r.getDrawable(R.drawable.caution);
|
mError = r.getDrawable(R.drawable.caution);
|
||||||
|
|
||||||
mImage = (ImageView) mView.findViewById(R.id.image);
|
mImage = (ImageView) mView.findViewById(R.id.image);
|
||||||
mButton = mView.findViewById(R.id.button);
|
mProgress = mView.findViewById(R.id.progress);
|
||||||
|
mSoundIndicator = (SoundIndicator) mView.findViewById(R.id.sound_indicator);
|
||||||
|
|
||||||
|
mButton = (Button) mView.findViewById(R.id.button);
|
||||||
mButton.setOnClickListener(clickListener);
|
mButton.setOnClickListener(clickListener);
|
||||||
mText = (TextView) mView.findViewById(R.id.text);
|
mText = (TextView) mView.findViewById(R.id.text);
|
||||||
mButtonText = (TextView) mView.findViewById(R.id.button_text);
|
|
||||||
mProgress = mView.findViewById(R.id.progress);
|
|
||||||
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
@ -144,9 +118,9 @@ public class RecognitionView {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// Restart the spinner
|
// Restart the spinner
|
||||||
if (mState == State.WORKING) {
|
if (mState == WORKING) {
|
||||||
((ProgressBar)mProgress).setIndeterminate(false);
|
((ProgressBar) mProgress).setIndeterminate(false);
|
||||||
((ProgressBar)mProgress).setIndeterminate(true);
|
((ProgressBar) mProgress).setIndeterminate(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -156,48 +130,48 @@ public class RecognitionView {
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
prepareDialog(false, mContext.getText(R.string.voice_initializing), mInitializing,
|
mState = INIT;
|
||||||
mContext.getText(R.string.cancel));
|
prepareDialog(mContext.getText(R.string.voice_initializing), mInitializing,
|
||||||
|
mContext.getText(R.string.cancel));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showListening() {
|
public void showListening() {
|
||||||
|
Log.d(TAG, "#showListening");
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mState = State.LISTENING;
|
mState = LISTENING;
|
||||||
prepareDialog(false, mContext.getText(R.string.voice_listening), mSpeakNow.get(0),
|
prepareDialog(mContext.getText(R.string.voice_listening), null,
|
||||||
mContext.getText(R.string.cancel));
|
mContext.getText(R.string.cancel));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mUiHandler.postDelayed(mUpdateVolumeRunnable, 50);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateVoiceMeter(final float rmsdB) {
|
public void updateVoiceMeter(float rmsdB) {
|
||||||
mVolume = rmsdB;
|
mSoundIndicator.setRmsdB(rmsdB);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showError(final String message) {
|
public void showError(final String message) {
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mState = State.READY;
|
mState = READY;
|
||||||
prepareDialog(false, message, mError, mContext.getText(R.string.ok));
|
prepareDialog(message, mError, mContext.getText(R.string.ok));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showWorking(
|
public void showWorking(
|
||||||
final ByteArrayOutputStream waveBuffer,
|
final ByteArrayOutputStream waveBuffer,
|
||||||
final int speechStartPosition,
|
final int speechStartPosition,
|
||||||
final int speechEndPosition) {
|
final int speechEndPosition) {
|
||||||
|
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mState = State.WORKING;
|
mState = WORKING;
|
||||||
prepareDialog(true, mContext.getText(R.string.voice_working), null, mContext
|
prepareDialog(mContext.getText(R.string.voice_working), null, mContext
|
||||||
.getText(R.string.cancel));
|
.getText(R.string.cancel));
|
||||||
final ShortBuffer buf = ByteBuffer.wrap(waveBuffer.toByteArray()).order(
|
final ShortBuffer buf = ByteBuffer.wrap(waveBuffer.toByteArray()).order(
|
||||||
ByteOrder.nativeOrder()).asShortBuffer();
|
ByteOrder.nativeOrder()).asShortBuffer();
|
||||||
|
@ -205,21 +179,71 @@ public class RecognitionView {
|
||||||
waveBuffer.reset();
|
waveBuffer.reset();
|
||||||
showWave(buf, speechStartPosition / 2, speechEndPosition / 2);
|
showWave(buf, speechStartPosition / 2, speechEndPosition / 2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareDialog(boolean spinVisible, CharSequence text, Drawable image,
|
private void prepareDialog(CharSequence text, Drawable image,
|
||||||
CharSequence btnTxt) {
|
CharSequence btnTxt) {
|
||||||
if (spinVisible) {
|
switch (mState) {
|
||||||
mProgress.setVisibility(View.VISIBLE);
|
case INIT:
|
||||||
mImage.setVisibility(View.GONE);
|
mText.setVisibility(View.GONE);
|
||||||
} else {
|
|
||||||
mProgress.setVisibility(View.GONE);
|
mProgress.setVisibility(View.GONE);
|
||||||
mImage.setImageDrawable(image);
|
|
||||||
mImage.setVisibility(View.VISIBLE);
|
mImage.setVisibility(View.VISIBLE);
|
||||||
|
mImage.setImageResource(R.drawable.mic_slash);
|
||||||
|
|
||||||
|
mSoundIndicator.setVisibility(View.GONE);
|
||||||
|
mSoundIndicator.stop();
|
||||||
|
|
||||||
|
mPopupLayout.setBackgroundDrawable(mListeningBorder);
|
||||||
|
break;
|
||||||
|
case LISTENING:
|
||||||
|
mText.setVisibility(View.VISIBLE);
|
||||||
|
mText.setText(text);
|
||||||
|
|
||||||
|
mProgress.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
mImage.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
mSoundIndicator.setVisibility(View.VISIBLE);
|
||||||
|
mSoundIndicator.start();
|
||||||
|
|
||||||
|
mPopupLayout.setBackgroundDrawable(mListeningBorder);
|
||||||
|
break;
|
||||||
|
case WORKING:
|
||||||
|
|
||||||
|
mText.setVisibility(View.VISIBLE);
|
||||||
|
mText.setText(text);
|
||||||
|
|
||||||
|
mProgress.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
mImage.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
mSoundIndicator.setVisibility(View.GONE);
|
||||||
|
mSoundIndicator.stop();
|
||||||
|
|
||||||
|
mPopupLayout.setBackgroundDrawable(mWorkingBorder);
|
||||||
|
break;
|
||||||
|
case READY:
|
||||||
|
mText.setVisibility(View.VISIBLE);
|
||||||
|
mText.setText(text);
|
||||||
|
|
||||||
|
mProgress.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
mImage.setVisibility(View.VISIBLE);
|
||||||
|
mImage.setImageResource(R.drawable.caution);
|
||||||
|
|
||||||
|
mSoundIndicator.setVisibility(View.GONE);
|
||||||
|
mSoundIndicator.stop();
|
||||||
|
|
||||||
|
mPopupLayout.setBackgroundDrawable(mErrorBorder);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.w(TAG, "Unknown state " + mState);
|
||||||
}
|
}
|
||||||
mText.setText(text);
|
mPopupLayout.requestLayout();
|
||||||
mButtonText.setText(btnTxt);
|
mButton.setText(btnTxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,7 +270,7 @@ public class RecognitionView {
|
||||||
*/
|
*/
|
||||||
private void showWave(ShortBuffer waveBuffer, int startPosition, int endPosition) {
|
private void showWave(ShortBuffer waveBuffer, int startPosition, int endPosition) {
|
||||||
final int w = ((View) mImage.getParent()).getWidth();
|
final int w = ((View) mImage.getParent()).getWidth();
|
||||||
final int h = mImage.getHeight();
|
final int h = ((View) mImage.getParent()).getHeight();
|
||||||
if (w <= 0 || h <= 0) {
|
if (w <= 0 || h <= 0) {
|
||||||
// view is not visible this time. Skip drawing.
|
// view is not visible this time. Skip drawing.
|
||||||
return;
|
return;
|
||||||
|
@ -257,7 +281,7 @@ public class RecognitionView {
|
||||||
paint.setColor(0xFFFFFFFF); // 0xAARRGGBB
|
paint.setColor(0xFFFFFFFF); // 0xAARRGGBB
|
||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
paint.setAlpha(0x90);
|
paint.setAlpha(80);
|
||||||
|
|
||||||
final PathEffect effect = new CornerPathEffect(3);
|
final PathEffect effect = new CornerPathEffect(3);
|
||||||
paint.setPathEffect(effect);
|
paint.setPathEffect(effect);
|
||||||
|
@ -279,7 +303,7 @@ public class RecognitionView {
|
||||||
|
|
||||||
final int count = (endIndex - startIndex) / numSamplePerWave;
|
final int count = (endIndex - startIndex) / numSamplePerWave;
|
||||||
final float deltaX = 1.0f * w / count;
|
final float deltaX = 1.0f * w / count;
|
||||||
int yMax = h / 2 - 8;
|
int yMax = h / 2;
|
||||||
Path path = new Path();
|
Path path = new Path();
|
||||||
c.translate(0, yMax);
|
c.translate(0, yMax);
|
||||||
float x = 0;
|
float x = 0;
|
||||||
|
@ -293,37 +317,20 @@ public class RecognitionView {
|
||||||
path.lineTo(x, y);
|
path.lineTo(x, y);
|
||||||
}
|
}
|
||||||
if (deltaX > 4) {
|
if (deltaX > 4) {
|
||||||
paint.setStrokeWidth(3);
|
paint.setStrokeWidth(2);
|
||||||
} else {
|
} else {
|
||||||
paint.setStrokeWidth(Math.max(1, (int) (deltaX -.05)));
|
paint.setStrokeWidth(Math.max(0, (int) (deltaX -.05)));
|
||||||
}
|
}
|
||||||
c.drawPath(path, paint);
|
c.drawPath(path, paint);
|
||||||
mImage.setImageBitmap(b);
|
mImage.setImageBitmap(b);
|
||||||
mImage.setVisibility(View.VISIBLE);
|
|
||||||
MarginLayoutParams mProgressParams = (MarginLayoutParams)mProgress.getLayoutParams();
|
|
||||||
mProgressParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
|
|
||||||
-h , mContext.getResources().getDisplayMetrics());
|
|
||||||
|
|
||||||
// Tweak the padding manually to fill out the whole view horizontally.
|
|
||||||
// TODO: Do this in the xml layout instead.
|
|
||||||
((View) mImage.getParent()).setPadding(4, ((View) mImage.getParent()).getPaddingTop(), 3,
|
|
||||||
((View) mImage.getParent()).getPaddingBottom());
|
|
||||||
mProgress.setLayoutParams(mProgressParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void finish() {
|
public void finish() {
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mState = State.READY;
|
mSoundIndicator.stop();
|
||||||
exitWorking();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private void exitWorking() {
|
|
||||||
mProgress.setVisibility(View.GONE);
|
|
||||||
mImage.setVisibility(View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.inputmethod.voice;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Bitmap.Config;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffXfermode;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A widget which shows the volume of audio using a microphone icon
|
||||||
|
*/
|
||||||
|
public class SoundIndicator extends ImageView {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static final String TAG = "SoundIndicator";
|
||||||
|
|
||||||
|
private static final float UP_SMOOTHING_FACTOR = 0.9f;
|
||||||
|
private static final float DOWN_SMOOTHING_FACTOR = 0.4f;
|
||||||
|
|
||||||
|
private static final float AUDIO_METER_MIN_DB = 7.0f;
|
||||||
|
private static final float AUDIO_METER_DB_RANGE = 20.0f;
|
||||||
|
|
||||||
|
private static final long FRAME_DELAY = 50;
|
||||||
|
|
||||||
|
private Bitmap mDrawingBuffer;
|
||||||
|
private Canvas mBufferCanvas;
|
||||||
|
private Bitmap mEdgeBitmap;
|
||||||
|
private float mLevel = 0.0f;
|
||||||
|
private Drawable mFrontDrawable;
|
||||||
|
private Paint mClearPaint;
|
||||||
|
private Paint mMultPaint;
|
||||||
|
private int mEdgeBitmapOffset;
|
||||||
|
|
||||||
|
private Handler mHandler;
|
||||||
|
|
||||||
|
private Runnable mDrawFrame = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
invalidate();
|
||||||
|
mHandler.postDelayed(mDrawFrame, FRAME_DELAY);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public SoundIndicator(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoundIndicator(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
|
||||||
|
mFrontDrawable = getDrawable();
|
||||||
|
BitmapDrawable edgeDrawable =
|
||||||
|
(BitmapDrawable) context.getResources().getDrawable(R.drawable.vs_popup_mic_edge);
|
||||||
|
mEdgeBitmap = edgeDrawable.getBitmap();
|
||||||
|
mEdgeBitmapOffset = mEdgeBitmap.getHeight() / 2;
|
||||||
|
|
||||||
|
mDrawingBuffer =
|
||||||
|
Bitmap.createBitmap(mFrontDrawable.getIntrinsicWidth(),
|
||||||
|
mFrontDrawable.getIntrinsicHeight(), Config.ARGB_8888);
|
||||||
|
|
||||||
|
mBufferCanvas = new Canvas(mDrawingBuffer);
|
||||||
|
|
||||||
|
// Initialize Paints.
|
||||||
|
mClearPaint = new Paint();
|
||||||
|
mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
||||||
|
|
||||||
|
mMultPaint = new Paint();
|
||||||
|
mMultPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
|
||||||
|
|
||||||
|
mHandler = new Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDraw(Canvas canvas) {
|
||||||
|
//super.onDraw(canvas);
|
||||||
|
|
||||||
|
float w = getWidth();
|
||||||
|
float h = getHeight();
|
||||||
|
|
||||||
|
// Clear the buffer canvas
|
||||||
|
mBufferCanvas.drawRect(0, 0, w, h, mClearPaint);
|
||||||
|
|
||||||
|
// Set its clip so we don't draw the front image all the way to the top
|
||||||
|
Rect clip = new Rect(0,
|
||||||
|
(int) ((1.0 - mLevel) * (h + mEdgeBitmapOffset)) - mEdgeBitmapOffset,
|
||||||
|
(int) w,
|
||||||
|
(int) h);
|
||||||
|
|
||||||
|
mBufferCanvas.save();
|
||||||
|
mBufferCanvas.clipRect(clip);
|
||||||
|
|
||||||
|
// Draw the front image
|
||||||
|
mFrontDrawable.setBounds(new Rect(0, 0, (int) w, (int) h));
|
||||||
|
mFrontDrawable.draw(mBufferCanvas);
|
||||||
|
|
||||||
|
mBufferCanvas.restore();
|
||||||
|
|
||||||
|
// Draw the edge image on top of the buffer image with a multiply mode
|
||||||
|
mBufferCanvas.drawBitmap(mEdgeBitmap, 0, clip.top, mMultPaint);
|
||||||
|
|
||||||
|
// Draw the buffer image (on top of the background image)
|
||||||
|
canvas.drawBitmap(mDrawingBuffer, 0, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the sound level
|
||||||
|
*
|
||||||
|
* @param rmsdB The level of the sound, in dB.
|
||||||
|
*/
|
||||||
|
public void setRmsdB(float rmsdB) {
|
||||||
|
float level = ((rmsdB - AUDIO_METER_MIN_DB) / AUDIO_METER_DB_RANGE);
|
||||||
|
|
||||||
|
level = Math.min(Math.max(0.0f, level), 1.0f);
|
||||||
|
|
||||||
|
// We smooth towards the new level
|
||||||
|
if (level > mLevel) {
|
||||||
|
mLevel = (level - mLevel) * UP_SMOOTHING_FACTOR + mLevel;
|
||||||
|
} else {
|
||||||
|
mLevel = (level - mLevel) * DOWN_SMOOTHING_FACTOR + mLevel;
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
mHandler.post(mDrawFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
mHandler.removeCallbacks(mDrawFrame);
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
@ -78,6 +79,9 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
// dialog is already showing a voice search button.
|
// dialog is already showing a voice search button.
|
||||||
private static final String IME_OPTION_NO_MICROPHONE = "nm";
|
private static final String IME_OPTION_NO_MICROPHONE = "nm";
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static final String TAG = "VoiceIMEConnector";
|
||||||
|
|
||||||
private boolean mAfterVoiceInput;
|
private boolean mAfterVoiceInput;
|
||||||
private boolean mHasUsedVoiceInput;
|
private boolean mHasUsedVoiceInput;
|
||||||
private boolean mHasUsedVoiceInputUnsupportedLocale;
|
private boolean mHasUsedVoiceInputUnsupportedLocale;
|
||||||
|
@ -164,8 +168,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showVoiceWarningDialog(final boolean swipe, IBinder token,
|
private void showVoiceWarningDialog(final boolean swipe, IBinder token) {
|
||||||
final boolean configurationChanging) {
|
|
||||||
if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
|
if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +179,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
mVoiceInput.logKeyboardWarningDialogOk();
|
mVoiceInput.logKeyboardWarningDialogOk();
|
||||||
reallyStartListening(swipe, configurationChanging);
|
reallyStartListening(swipe);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
|
@ -519,22 +522,38 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
onCancelVoice();
|
onCancelVoice();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void switchToRecognitionStatusView(final boolean configurationChanging) {
|
public void switchToRecognitionStatusView(final Configuration configuration) {
|
||||||
final boolean configChanged = configurationChanging;
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mService.setCandidatesViewShown(false);
|
mService.setCandidatesViewShown(false);
|
||||||
mRecognizing = true;
|
mRecognizing = true;
|
||||||
|
mVoiceInput.newView();
|
||||||
View v = mVoiceInput.getView();
|
View v = mVoiceInput.getView();
|
||||||
|
|
||||||
ViewParent p = v.getParent();
|
ViewParent p = v.getParent();
|
||||||
if (p != null && p instanceof ViewGroup) {
|
if (p != null && p instanceof ViewGroup) {
|
||||||
((ViewGroup)p).removeView(v);
|
((ViewGroup) p).removeView(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
View keyboardView = KeyboardSwitcher.getInstance().getInputView();
|
||||||
|
|
||||||
|
// The full height of the keyboard is difficult to calculate
|
||||||
|
// as the dimension is expressed in "mm" and not in "pixel"
|
||||||
|
// As we add mm, we don't know how the rounding is going to work
|
||||||
|
// thus we may end up with few pixels extra (or less).
|
||||||
|
if (keyboardView != null) {
|
||||||
|
int h = keyboardView.getHeight();
|
||||||
|
if (h > 0) {
|
||||||
|
View popupLayout = v.findViewById(R.id.popup_layout);
|
||||||
|
popupLayout.getLayoutParams().height = h;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mService.setInputView(v);
|
mService.setInputView(v);
|
||||||
mService.updateInputViewShown();
|
mService.updateInputViewShown();
|
||||||
if (configChanged) {
|
|
||||||
mVoiceInput.onConfigurationChanged();
|
if (configuration != null) {
|
||||||
|
mVoiceInput.onConfigurationChanged(configuration);
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
@ -544,7 +563,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
mImm.switchToLastInputMethod(token);
|
mImm.switchToLastInputMethod(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reallyStartListening(boolean swipe, final boolean configurationChanging) {
|
private void reallyStartListening(boolean swipe) {
|
||||||
if (!VOICE_INSTALLED) {
|
if (!VOICE_INSTALLED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -573,22 +592,21 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
|
|
||||||
FieldContext context = makeFieldContext();
|
FieldContext context = makeFieldContext();
|
||||||
mVoiceInput.startListening(context, swipe);
|
mVoiceInput.startListening(context, swipe);
|
||||||
switchToRecognitionStatusView(configurationChanging);
|
switchToRecognitionStatusView(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startListening(final boolean swipe, IBinder token,
|
public void startListening(final boolean swipe, IBinder token) {
|
||||||
final boolean configurationChanging) {
|
// TODO: remove swipe which is no longer used.
|
||||||
if (VOICE_INSTALLED) {
|
if (VOICE_INSTALLED) {
|
||||||
if (needsToShowWarningDialog()) {
|
if (needsToShowWarningDialog()) {
|
||||||
// Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
|
// Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
|
||||||
showVoiceWarningDialog(swipe, token, configurationChanging);
|
showVoiceWarningDialog(swipe, token);
|
||||||
} else {
|
} else {
|
||||||
reallyStartListening(swipe, configurationChanging);
|
reallyStartListening(swipe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean fieldCanDoVoice(FieldContext fieldContext) {
|
private boolean fieldCanDoVoice(FieldContext fieldContext) {
|
||||||
return !mPasswordText
|
return !mPasswordText
|
||||||
&& mVoiceInput != null
|
&& mVoiceInput != null
|
||||||
|
@ -632,7 +650,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
// Close keyboard view if it is been shown.
|
// Close keyboard view if it is been shown.
|
||||||
if (KeyboardSwitcher.getInstance().isInputViewShown())
|
if (KeyboardSwitcher.getInstance().isInputViewShown())
|
||||||
KeyboardSwitcher.getInstance().getInputView().purgeKeyboardAndClosing();
|
KeyboardSwitcher.getInstance().getInputView().purgeKeyboardAndClosing();
|
||||||
startListening(false, token, false);
|
startListening(false, token);
|
||||||
}
|
}
|
||||||
// If we have no token, onAttachedToWindow will take care of showing dialog and start
|
// If we have no token, onAttachedToWindow will take care of showing dialog and start
|
||||||
// listening.
|
// listening.
|
||||||
|
@ -644,9 +662,9 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
mSubtypeSwitcher.setVoiceInput(mVoiceInput);
|
mSubtypeSwitcher.setVoiceInput(mVoiceInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onConfigurationChanged(boolean configurationChanging) {
|
public void onConfigurationChanged(Configuration configuration) {
|
||||||
if (mRecognizing) {
|
if (mRecognizing) {
|
||||||
switchToRecognitionStatusView(configurationChanging);
|
switchToRecognitionStatusView(configuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.android.inputmethod.latin.R;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
@ -129,12 +130,17 @@ public class VoiceInput implements OnClickListener {
|
||||||
|
|
||||||
private final static int MSG_CLOSE_ERROR_DIALOG = 1;
|
private final static int MSG_CLOSE_ERROR_DIALOG = 1;
|
||||||
|
|
||||||
|
private final static int MSG_RESET = 2;
|
||||||
|
|
||||||
private final Handler mHandler = new Handler() {
|
private final Handler mHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
if (msg.what == MSG_CLOSE_ERROR_DIALOG) {
|
if (msg.what == MSG_RESET || msg.what == MSG_CLOSE_ERROR_DIALOG) {
|
||||||
mState = DEFAULT;
|
mState = DEFAULT;
|
||||||
mRecognitionView.finish();
|
mRecognitionView.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.what == MSG_CLOSE_ERROR_DIALOG) {
|
||||||
mUiListener.onCancelVoice();
|
mUiListener.onCancelVoice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,8 +283,9 @@ public class VoiceInput implements OnClickListener {
|
||||||
* The configuration of the IME changed and may have caused the views to be layed out
|
* The configuration of the IME changed and may have caused the views to be layed out
|
||||||
* again. Restore the state of the recognition view.
|
* again. Restore the state of the recognition view.
|
||||||
*/
|
*/
|
||||||
public void onConfigurationChanged() {
|
public void onConfigurationChanged(Configuration configuration) {
|
||||||
mRecognitionView.restoreState();
|
mRecognitionView.restoreState();
|
||||||
|
mRecognitionView.getView().dispatchConfigurationChanged(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -509,7 +516,7 @@ public class VoiceInput implements OnClickListener {
|
||||||
mState = DEFAULT;
|
mState = DEFAULT;
|
||||||
|
|
||||||
// Remove all pending tasks (e.g., timers to cancel voice input)
|
// Remove all pending tasks (e.g., timers to cancel voice input)
|
||||||
mHandler.removeMessages(MSG_CLOSE_ERROR_DIALOG);
|
mHandler.removeMessages(MSG_RESET);
|
||||||
|
|
||||||
mSpeechRecognizer.cancel();
|
mSpeechRecognizer.cancel();
|
||||||
mUiListener.onCancelVoice();
|
mUiListener.onCancelVoice();
|
||||||
|
|