am 9f49dcda: Merge "Add voice interaction support to ResolverActivity/ChooserActivity" into mnc-dev
* commit '9f49dcda24ea63efc8b16d0c7d69cc697cdf20d7': Add voice interaction support to ResolverActivity/ChooserActivity
This commit is contained in:
@@ -100,6 +100,10 @@ public class ChooserActivity extends ResolverActivity {
|
||||
mChooserListAdapter.addServiceResults(sri.originalTarget, sri.resultTargets);
|
||||
unbindService(sri.connection);
|
||||
mServiceConnections.remove(sri.connection);
|
||||
if (mServiceConnections.isEmpty()) {
|
||||
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
|
||||
sendVoiceChoicesIfNeeded();
|
||||
}
|
||||
break;
|
||||
|
||||
case CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT:
|
||||
@@ -107,6 +111,7 @@ public class ChooserActivity extends ResolverActivity {
|
||||
Log.d(TAG, "CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT; unbinding services");
|
||||
}
|
||||
unbindRemainingServices();
|
||||
sendVoiceChoicesIfNeeded();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -384,6 +389,8 @@ public class ChooserActivity extends ResolverActivity {
|
||||
+ WATCHDOG_TIMEOUT_MILLIS + "ms");
|
||||
mChooserHandler.sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT,
|
||||
WATCHDOG_TIMEOUT_MILLIS);
|
||||
} else {
|
||||
sendVoiceChoicesIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,6 +425,10 @@ public class ChooserActivity extends ResolverActivity {
|
||||
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
|
||||
}
|
||||
|
||||
void onSetupVoiceInteraction() {
|
||||
// Do nothing. We'll send the voice stuff ourselves.
|
||||
}
|
||||
|
||||
void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
|
||||
if (mRefinementResultReceiver != null) {
|
||||
mRefinementResultReceiver.destroy();
|
||||
@@ -956,6 +967,10 @@ public class ChooserActivity extends ResolverActivity {
|
||||
if (DEBUG) Log.d(TAG, "onServiceDisconnected: " + name);
|
||||
unbindService(this);
|
||||
mServiceConnections.remove(this);
|
||||
if (mServiceConnections.isEmpty()) {
|
||||
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
|
||||
sendVoiceChoicesIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,10 +16,17 @@
|
||||
|
||||
package com.android.internal.app;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityThread;
|
||||
import android.app.VoiceInteractor;
|
||||
import android.app.VoiceInteractor.PickOptionRequest;
|
||||
import android.app.VoiceInteractor.PickOptionRequest.Option;
|
||||
import android.app.VoiceInteractor.Prompt;
|
||||
import android.app.VoiceInteractor.Request;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.Settings;
|
||||
import android.service.chooser.ChooserTarget;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
import android.widget.AbsListView;
|
||||
@@ -96,6 +103,7 @@ public class ResolverActivity extends Activity {
|
||||
private int mProfileSwitchMessageId = -1;
|
||||
private final ArrayList<Intent> mIntents = new ArrayList<>();
|
||||
private ResolverComparator mResolverComparator;
|
||||
private PickTargetOptionRequest mPickOptionRequest;
|
||||
|
||||
private boolean mRegistered;
|
||||
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
|
||||
@@ -242,6 +250,9 @@ public class ResolverActivity extends Activity {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
if (isVoiceInteraction()) {
|
||||
rdl.setCollapsed(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (title == null) {
|
||||
@@ -313,6 +324,39 @@ public class ResolverActivity extends Activity {
|
||||
});
|
||||
bindProfileView();
|
||||
}
|
||||
|
||||
if (isVoiceInteraction()) {
|
||||
onSetupVoiceInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any initialization needed for voice interaction.
|
||||
*/
|
||||
void onSetupVoiceInteraction() {
|
||||
// Do it right now. Subclasses may delay this and send it later.
|
||||
sendVoiceChoicesIfNeeded();
|
||||
}
|
||||
|
||||
void sendVoiceChoicesIfNeeded() {
|
||||
if (!isVoiceInteraction()) {
|
||||
// Clearly not needed.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final Option[] options = new Option[mAdapter.getCount()];
|
||||
for (int i = 0, N = options.length; i < N; i++) {
|
||||
options[i] = optionForChooserTarget(mAdapter.getItem(i), i);
|
||||
}
|
||||
|
||||
mPickOptionRequest = new PickTargetOptionRequest(
|
||||
new Prompt(getTitle()), options, null);
|
||||
getVoiceInteractor().submitRequest(mPickOptionRequest);
|
||||
}
|
||||
|
||||
Option optionForChooserTarget(TargetInfo target, int index) {
|
||||
return new Option(target.getDisplayLabel(), index);
|
||||
}
|
||||
|
||||
protected final void setAdditionalTargets(Intent[] intents) {
|
||||
@@ -472,6 +516,14 @@ public class ResolverActivity extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (!isChangingConfigurations() && mPickOptionRequest != null) {
|
||||
mPickOptionRequest.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
@@ -510,16 +562,12 @@ public class ResolverActivity extends Activity {
|
||||
try {
|
||||
ApplicationInfo appInfo = getPackageManager().getApplicationInfo(
|
||||
resolveInfo.activityInfo.packageName, 0 /* default flags */);
|
||||
return versionNumberAtLeastL(appInfo.targetSdkVersion);
|
||||
return appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
|
||||
} catch (NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean versionNumberAtLeastL(int versionNumber) {
|
||||
return versionNumber >= Build.VERSION_CODES.LOLLIPOP;
|
||||
}
|
||||
|
||||
private void setAlwaysButtonEnabled(boolean hasValidSelection, int checkedPos,
|
||||
boolean filtered) {
|
||||
boolean enabled = false;
|
||||
@@ -1644,4 +1692,39 @@ public class ResolverActivity extends Activity {
|
||||
&& match <= IntentFilter.MATCH_CATEGORY_PATH;
|
||||
}
|
||||
|
||||
static class PickTargetOptionRequest extends PickOptionRequest {
|
||||
public PickTargetOptionRequest(@Nullable Prompt prompt, Option[] options,
|
||||
@Nullable Bundle extras) {
|
||||
super(prompt, options, extras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
super.onCancel();
|
||||
final ResolverActivity ra = (ResolverActivity) getActivity();
|
||||
if (ra != null) {
|
||||
ra.mPickOptionRequest = null;
|
||||
ra.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
|
||||
super.onPickOptionResult(finished, selections, result);
|
||||
if (selections.length != 1) {
|
||||
// TODO In a better world we would filter the UI presented here and let the
|
||||
// user refine. Maybe later.
|
||||
return;
|
||||
}
|
||||
|
||||
final ResolverActivity ra = (ResolverActivity) getActivity();
|
||||
if (ra != null) {
|
||||
final TargetInfo ti = ra.mAdapter.getItem(selections[0].getIndex());
|
||||
if (ra.onTargetSelected(ti, false)) {
|
||||
ra.mPickOptionRequest = null;
|
||||
ra.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +144,14 @@ public class ResolverDrawerLayout extends ViewGroup {
|
||||
return mCollapseOffset > 0;
|
||||
}
|
||||
|
||||
public void setCollapsed(boolean collapsed) {
|
||||
if (!isLaidOut()) {
|
||||
mOpenOnLayout = collapsed;
|
||||
} else {
|
||||
smoothScrollTo(collapsed ? mCollapsibleHeight : 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMoving() {
|
||||
return mIsDragging || !mScroller.isFinished();
|
||||
}
|
||||
@@ -575,7 +583,13 @@ public class ResolverDrawerLayout extends ViewGroup {
|
||||
@Override
|
||||
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
|
||||
if (!consumed && Math.abs(velocityY) > mMinFlingVelocity) {
|
||||
smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY);
|
||||
if (mOnDismissedListener != null
|
||||
&& velocityY < 0 && mCollapseOffset > mCollapsibleHeight) {
|
||||
smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, velocityY);
|
||||
mDismissOnScrollerFinished = true;
|
||||
} else {
|
||||
smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -2457,6 +2457,7 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.CHOOSER" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.VOICE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.android.internal.app.IntentForwarderActivity"
|
||||
|
||||
Reference in New Issue
Block a user