Merge "Introduce TextAssistant for Smart Text Share feature."

This commit is contained in:
Abodunrinwa Toki
2016-11-23 16:29:37 +00:00
committed by Android (Google) Code Review
9 changed files with 303 additions and 13 deletions

View File

@@ -3497,6 +3497,7 @@ package android.app {
method public int getRequestedOrientation();
method public final android.view.SearchEvent getSearchEvent();
method public int getTaskId();
method public android.text.TextAssistant getTextAssistant();
method public final java.lang.CharSequence getTitle();
method public final int getTitleColor();
method public android.app.VoiceInteractor getVoiceInteractor();
@@ -3646,6 +3647,7 @@ package android.app {
method public final void setResult(int, android.content.Intent);
method public final deprecated void setSecondaryProgress(int);
method public void setTaskDescription(android.app.ActivityManager.TaskDescription);
method public void setTextAssistant(android.text.TextAssistant);
method public void setTitle(java.lang.CharSequence);
method public void setTitle(int);
method public deprecated void setTitleColor(int);
@@ -38988,6 +38990,16 @@ package android.text {
method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic);
}
public abstract interface TextAssistant {
method public abstract void addLinks(android.text.Spannable, int);
method public abstract android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int);
}
public class TextClassification {
ctor public TextClassification();
method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence();
}
public abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -39015,6 +39027,13 @@ package android.text {
field public int linkColor;
}
public class TextSelection {
ctor public TextSelection();
method public int getSelectionEndIndex();
method public int getSelectionStartIndex();
method public android.text.TextClassification getTextClassification();
}
public class TextUtils {
method public static deprecated java.lang.CharSequence commaEllipsize(java.lang.CharSequence, android.text.TextPaint, float, java.lang.String, java.lang.String);
method public static java.lang.CharSequence concat(java.lang.CharSequence...);
@@ -48487,6 +48506,7 @@ package android.widget {
method public float getShadowRadius();
method public final boolean getShowSoftInputOnFocus();
method public java.lang.CharSequence getText();
method public android.text.TextAssistant getTextAssistant();
method public final android.content.res.ColorStateList getTextColors();
method public java.util.Locale getTextLocale();
method public android.os.LocaleList getTextLocales();
@@ -48597,6 +48617,7 @@ package android.widget {
method public final void setText(int, android.widget.TextView.BufferType);
method public void setTextAppearance(int);
method public deprecated void setTextAppearance(android.content.Context, int);
method public void setTextAssistant(android.text.TextAssistant);
method public void setTextColor(int);
method public void setTextColor(android.content.res.ColorStateList);
method public void setTextIsSelectable(boolean);

View File

@@ -3614,6 +3614,7 @@ package android.app {
method public int getRequestedOrientation();
method public final android.view.SearchEvent getSearchEvent();
method public int getTaskId();
method public android.text.TextAssistant getTextAssistant();
method public final java.lang.CharSequence getTitle();
method public final int getTitleColor();
method public android.app.VoiceInteractor getVoiceInteractor();
@@ -3765,6 +3766,7 @@ package android.app {
method public final void setResult(int, android.content.Intent);
method public final deprecated void setSecondaryProgress(int);
method public void setTaskDescription(android.app.ActivityManager.TaskDescription);
method public void setTextAssistant(android.text.TextAssistant);
method public void setTitle(java.lang.CharSequence);
method public void setTitle(int);
method public deprecated void setTitleColor(int);
@@ -42150,6 +42152,16 @@ package android.text {
method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic);
}
public abstract interface TextAssistant {
method public abstract void addLinks(android.text.Spannable, int);
method public abstract android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int);
}
public class TextClassification {
ctor public TextClassification();
method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence();
}
public abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -42177,6 +42189,13 @@ package android.text {
field public int linkColor;
}
public class TextSelection {
ctor public TextSelection();
method public int getSelectionEndIndex();
method public int getSelectionStartIndex();
method public android.text.TextClassification getTextClassification();
}
public class TextUtils {
method public static deprecated java.lang.CharSequence commaEllipsize(java.lang.CharSequence, android.text.TextPaint, float, java.lang.String, java.lang.String);
method public static java.lang.CharSequence concat(java.lang.CharSequence...);
@@ -52008,6 +52027,7 @@ package android.widget {
method public float getShadowRadius();
method public final boolean getShowSoftInputOnFocus();
method public java.lang.CharSequence getText();
method public android.text.TextAssistant getTextAssistant();
method public final android.content.res.ColorStateList getTextColors();
method public java.util.Locale getTextLocale();
method public android.os.LocaleList getTextLocales();
@@ -52118,6 +52138,7 @@ package android.widget {
method public final void setText(int, android.widget.TextView.BufferType);
method public void setTextAppearance(int);
method public deprecated void setTextAppearance(android.content.Context, int);
method public void setTextAssistant(android.text.TextAssistant);
method public void setTextColor(int);
method public void setTextColor(android.content.res.ColorStateList);
method public void setTextIsSelectable(boolean);

View File

@@ -3499,6 +3499,7 @@ package android.app {
method public int getRequestedOrientation();
method public final android.view.SearchEvent getSearchEvent();
method public int getTaskId();
method public android.text.TextAssistant getTextAssistant();
method public final java.lang.CharSequence getTitle();
method public final int getTitleColor();
method public android.app.VoiceInteractor getVoiceInteractor();
@@ -3648,6 +3649,7 @@ package android.app {
method public final void setResult(int, android.content.Intent);
method public final deprecated void setSecondaryProgress(int);
method public void setTaskDescription(android.app.ActivityManager.TaskDescription);
method public void setTextAssistant(android.text.TextAssistant);
method public void setTitle(java.lang.CharSequence);
method public void setTitle(int);
method public deprecated void setTitleColor(int);
@@ -39080,6 +39082,16 @@ package android.text {
method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic);
}
public abstract interface TextAssistant {
method public abstract void addLinks(android.text.Spannable, int);
method public abstract android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int);
}
public class TextClassification {
ctor public TextClassification();
method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence();
}
public abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -39107,6 +39119,13 @@ package android.text {
field public int linkColor;
}
public class TextSelection {
ctor public TextSelection();
method public int getSelectionEndIndex();
method public int getSelectionStartIndex();
method public android.text.TextClassification getTextClassification();
}
public class TextUtils {
method public static deprecated java.lang.CharSequence commaEllipsize(java.lang.CharSequence, android.text.TextPaint, float, java.lang.String, java.lang.String);
method public static java.lang.CharSequence concat(java.lang.CharSequence...);
@@ -48745,6 +48764,7 @@ package android.widget {
method public float getShadowRadius();
method public final boolean getShowSoftInputOnFocus();
method public java.lang.CharSequence getText();
method public android.text.TextAssistant getTextAssistant();
method public final android.content.res.ColorStateList getTextColors();
method public java.util.Locale getTextLocale();
method public android.os.LocaleList getTextLocales();
@@ -48855,6 +48875,7 @@ package android.widget {
method public final void setText(int, android.widget.TextView.BufferType);
method public void setTextAppearance(int);
method public deprecated void setTextAppearance(android.content.Context, int);
method public void setTextAssistant(android.text.TextAssistant);
method public void setTextColor(int);
method public void setTextColor(android.content.res.ColorStateList);
method public void setTextIsSelectable(boolean);

View File

@@ -74,6 +74,7 @@ import android.service.autofill.AutoFillService;
import android.service.autofill.IAutoFillCallback;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextAssistant;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
import android.transition.Scene;
@@ -783,6 +784,8 @@ public class Activity extends ContextThemeWrapper
private VoiceInteractor mVoiceInteractor;
private TextAssistant mTextAssistant;
private CharSequence mTitle;
private int mTitleColor = 0;
@@ -1384,6 +1387,24 @@ public class Activity extends ContextThemeWrapper
}
}
/**
* Sets the default {@link TextAssistant} for {@link android.widget.TextView}s in this Activity.
*/
public void setTextAssistant(TextAssistant textAssistant) {
mTextAssistant = textAssistant;
}
/**
* Returns the default {@link TextAssistant} for {@link android.widget.TextView}s
* in this Activity.
*/
public TextAssistant getTextAssistant() {
if (mTextAssistant != null) {
return mTextAssistant;
}
return TextAssistant.NO_OP;
}
/**
* This is called for activities that set launchMode to "singleTop" in
* their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2016 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.
*/
package android.text;
/**
* Interface for providing text assistant features.
*/
public interface TextAssistant {
/**
* NO_OP TextAssistant. This will act as the default TextAssistant until we implement a
* TextClassificationManager.
* @hide
*/
TextAssistant NO_OP = new TextAssistant() {
private final TextSelection mTextSelection = new TextSelection();
@Override
public TextSelection suggestSelection(
CharSequence text, int selectionStartIndex, int selectionEndIndex) {
mTextSelection.mStartIndex = selectionStartIndex;
mTextSelection.mEndIndex = selectionEndIndex;
return mTextSelection;
}
@Override
public void addLinks(Spannable text, int linkMask) {}
};
/**
* Returns suggested text selection indices, recognized types and their associated confidence
* scores. The selections are ordered from highest to lowest scoring.
*/
TextSelection suggestSelection(
CharSequence text, int selectionStartIndex, int selectionEndIndex);
/**
* Adds assistance clickable spans to the provided text.
*/
void addLinks(Spannable text, int linkMask);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2016 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.
*/
package android.text;
import java.util.Collections;
import java.util.Map;
/**
* Information about entities that a specific piece of text is classified as.
*/
public class TextClassification {
/** @hide */
public static final TextClassification NO_OP = new TextClassification();
private Map<String, Float> mTypeConfidence = Collections.unmodifiableMap(Collections.EMPTY_MAP);
/**
* Returns a map of text classification types to their respective confidence scores.
* The scores range from 0 (low confidence) to 1 (high confidence). The items are ordered from
* high scoring items to low scoring items.
*/
public Map<String, Float> getTypeConfidence() {
return mTypeConfidence;
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2016 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.
*/
package android.text;
/**
* Text selection information.
*/
public class TextSelection {
/** @hide */
int mStartIndex;
/** @hide */
int mEndIndex;
private TextClassification mTextClassification = TextClassification.NO_OP;
/**
* Returns the start index of the text selection.
*/
public int getSelectionStartIndex() {
return mStartIndex;
}
/**
* Returns the end index of the text selection.
*/
public int getSelectionEndIndex() {
return mEndIndex;
}
/**
* Returns information about what the text selection is classified as.
*/
public TextClassification getTextClassification() {
return mTextClassification;
}
}

View File

@@ -60,6 +60,8 @@ import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextClassification;
import android.text.TextSelection;
import android.text.TextUtils;
import android.text.method.KeyListener;
import android.text.method.MetaKeyKeyListener;
@@ -147,16 +149,17 @@ public class Editor {
private static final String UNDO_OWNER_TAG = "Editor";
// Ordering constants used to place the Action Mode or context menu items in their menu.
private static final int MENU_ITEM_ORDER_UNDO = 1;
private static final int MENU_ITEM_ORDER_REDO = 2;
private static final int MENU_ITEM_ORDER_CUT = 3;
private static final int MENU_ITEM_ORDER_COPY = 4;
private static final int MENU_ITEM_ORDER_PASTE = 5;
private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 6;
private static final int MENU_ITEM_ORDER_SHARE = 7;
private static final int MENU_ITEM_ORDER_SELECT_ALL = 8;
private static final int MENU_ITEM_ORDER_REPLACE = 9;
private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 10;
// Reserve 1 for the app that the ASSIST logic suggests as the best app to handle the selection.
private static final int MENU_ITEM_ORDER_UNDO = 2;
private static final int MENU_ITEM_ORDER_REDO = 3;
private static final int MENU_ITEM_ORDER_SHARE = 4;
private static final int MENU_ITEM_ORDER_CUT = 5;
private static final int MENU_ITEM_ORDER_COPY = 6;
private static final int MENU_ITEM_ORDER_PASTE = 7;
private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 8;
private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
private static final int MENU_ITEM_ORDER_REPLACE = 10;
private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 11;
// Each Editor manages its own undo stack.
private final UndoManager mUndoManager = new UndoManager();
@@ -3767,10 +3770,12 @@ public class Editor {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
TextClassification textClassification = updateSelectionWithTextAssistant();
mode.setTitle(null);
mode.setSubtitle(null);
mode.setTitleOptionalHint(true);
populateMenuWithItems(menu);
populateMenuWithItems(menu, textClassification);
Callback customCallback = getCustomCallback();
if (customCallback != null) {
@@ -3796,13 +3801,30 @@ public class Editor {
}
}
private TextClassification updateSelectionWithTextAssistant() {
// Trim the text so that only text necessary to provide context of the selected text is
// sent to the assistant.
CharSequence trimmedText = mTextView.getText();
int textLength = mTextView.getText().length();
int trimStartIndex = 0;
int startIndex = mTextView.getSelectionStart() - trimStartIndex;
int endIndex = mTextView.getSelectionEnd() - trimStartIndex;
TextSelection textSelection = mTextView.getTextAssistant()
.suggestSelection(trimmedText, startIndex, endIndex);
Selection.setSelection(
(Spannable) mTextView.getText(),
Math.max(0, textSelection.getSelectionStartIndex() + trimStartIndex),
Math.min(textLength, textSelection.getSelectionEndIndex() + trimStartIndex));
return textSelection.getTextClassification();
}
private Callback getCustomCallback() {
return mHasSelection
? mCustomSelectionActionModeCallback
: mCustomInsertionActionModeCallback;
}
private void populateMenuWithItems(Menu menu) {
private void populateMenuWithItems(Menu menu, TextClassification textClassification) {
if (mTextView.canCut()) {
menu.add(Menu.NONE, TextView.ID_CUT, MENU_ITEM_ORDER_CUT,
com.android.internal.R.string.cut)
@@ -3827,11 +3849,12 @@ public class Editor {
if (mTextView.canShare()) {
menu.add(Menu.NONE, TextView.ID_SHARE, MENU_ITEM_ORDER_SHARE,
com.android.internal.R.string.share)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
updateSelectAllItem(menu);
updateReplaceItem(menu);
updateAssistMenuItem(menu, textClassification);
}
@Override
@@ -3870,6 +3893,12 @@ public class Editor {
}
}
private void updateAssistMenuItem(Menu menu, TextClassification textClassification) {
// TODO: Find the best app available to handle the selected text based on information in
// the TextClassification object.
// Add app icon + intent to trigger app to the menu.
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (mProcessTextIntentActionsHandler.performMenuItemAction(item)) {

View File

@@ -76,6 +76,7 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.StaticLayout;
import android.text.TextAssistant;
import android.text.TextDirectionHeuristic;
import android.text.TextDirectionHeuristics;
import android.text.TextPaint;
@@ -9819,6 +9820,35 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mEditor == null ? null : mEditor.mCustomInsertionActionModeCallback;
}
private TextAssistant mTextAssistant;
/**
* Sets the {@link TextAssistant} for this TextView.
* If null, this TextView uses the default TextAssistant which comes from the Activity.
*/
public void setTextAssistant(TextAssistant textAssistant) {
mTextAssistant = textAssistant;
}
/**
* Returns the {@link TextAssistant} used by this TextView.
* If no TextAssistant is set, it'll use the one from this TextView's {@link Activity} or
* {@link Context}. If no TextAssistant is found, it'll use a no-op TextAssistant.
*/
public TextAssistant getTextAssistant() {
if (mTextAssistant != null) {
return mTextAssistant;
}
if (mContext instanceof Activity) {
mTextAssistant = ((Activity) mContext).getTextAssistant();
} else {
// The context of this TextView should be an Activity. If it is not and no
// text assistant has been set, return a NO_OP TextAssistant.
mTextAssistant = TextAssistant.NO_OP;
}
return mTextAssistant;
}
/**
* @hide
*/