Loading api/current.txt +7 −0 Original line number Original line Diff line number Diff line Loading @@ -48693,19 +48693,26 @@ package android.view.inputmethod { package android.view.textclassifier { package android.view.textclassifier { public final class TextClassification { public final class TextClassification { method public int getActionCount(); method public float getConfidenceScore(java.lang.String); method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); method public java.lang.String getEntity(int); method public int getEntityCount(); method public int getEntityCount(); method public android.graphics.drawable.Drawable getIcon(int); method public android.graphics.drawable.Drawable getIcon(); method public android.graphics.drawable.Drawable getIcon(); method public android.content.Intent getIntent(int); method public android.content.Intent getIntent(); method public android.content.Intent getIntent(); method public java.lang.CharSequence getLabel(int); method public java.lang.CharSequence getLabel(); method public java.lang.CharSequence getLabel(); method public android.view.View.OnClickListener getOnClickListener(int); method public android.view.View.OnClickListener getOnClickListener(); method public android.view.View.OnClickListener getOnClickListener(); method public java.lang.String getText(); method public java.lang.String getText(); } } public static final class TextClassification.Builder { public static final class TextClassification.Builder { ctor public TextClassification.Builder(); ctor public TextClassification.Builder(); method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification.Builder clearActions(); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); api/system-current.txt +7 −0 Original line number Original line Diff line number Diff line Loading @@ -52389,19 +52389,26 @@ package android.view.inputmethod { package android.view.textclassifier { package android.view.textclassifier { public final class TextClassification { public final class TextClassification { method public int getActionCount(); method public float getConfidenceScore(java.lang.String); method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); method public java.lang.String getEntity(int); method public int getEntityCount(); method public int getEntityCount(); method public android.graphics.drawable.Drawable getIcon(int); method public android.graphics.drawable.Drawable getIcon(); method public android.graphics.drawable.Drawable getIcon(); method public android.content.Intent getIntent(int); method public android.content.Intent getIntent(); method public android.content.Intent getIntent(); method public java.lang.CharSequence getLabel(int); method public java.lang.CharSequence getLabel(); method public java.lang.CharSequence getLabel(); method public android.view.View.OnClickListener getOnClickListener(int); method public android.view.View.OnClickListener getOnClickListener(); method public android.view.View.OnClickListener getOnClickListener(); method public java.lang.String getText(); method public java.lang.String getText(); } } public static final class TextClassification.Builder { public static final class TextClassification.Builder { ctor public TextClassification.Builder(); ctor public TextClassification.Builder(); method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification.Builder clearActions(); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); api/test-current.txt +7 −0 Original line number Original line Diff line number Diff line Loading @@ -49249,19 +49249,26 @@ package android.view.inputmethod { package android.view.textclassifier { package android.view.textclassifier { public final class TextClassification { public final class TextClassification { method public int getActionCount(); method public float getConfidenceScore(java.lang.String); method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); method public java.lang.String getEntity(int); method public int getEntityCount(); method public int getEntityCount(); method public android.graphics.drawable.Drawable getIcon(int); method public android.graphics.drawable.Drawable getIcon(); method public android.graphics.drawable.Drawable getIcon(); method public android.content.Intent getIntent(int); method public android.content.Intent getIntent(); method public android.content.Intent getIntent(); method public java.lang.CharSequence getLabel(int); method public java.lang.CharSequence getLabel(); method public java.lang.CharSequence getLabel(); method public android.view.View.OnClickListener getOnClickListener(int); method public android.view.View.OnClickListener getOnClickListener(); method public android.view.View.OnClickListener getOnClickListener(); method public java.lang.String getText(); method public java.lang.String getText(); } } public static final class TextClassification.Builder { public static final class TextClassification.Builder { ctor public TextClassification.Builder(); ctor public TextClassification.Builder(); method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification.Builder clearActions(); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); core/java/android/view/textclassifier/TextClassification.java +153 −35 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.view.textclassifier.TextClassifier.EntityType; import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.List; import java.util.List; /** /** Loading @@ -41,10 +42,10 @@ public final class TextClassification { static final TextClassification EMPTY = new TextClassification.Builder().build(); static final TextClassification EMPTY = new TextClassification.Builder().build(); @NonNull private final String mText; @NonNull private final String mText; @Nullable private final Drawable mIcon; @NonNull private final List<Drawable> mIcons; @Nullable private final String mLabel; @NonNull private final List<String> mLabels; @Nullable private final Intent mIntent; @NonNull private final List<Intent> mIntents; @Nullable private final OnClickListener mOnClickListener; @NonNull private final List<OnClickListener> mOnClickListeners; @NonNull private final EntityConfidence<String> mEntityConfidence; @NonNull private final EntityConfidence<String> mEntityConfidence; @NonNull private final List<String> mEntities; @NonNull private final List<String> mEntities; private int mLogType; private int mLogType; Loading @@ -52,18 +53,21 @@ public final class TextClassification { private TextClassification( private TextClassification( @Nullable String text, @Nullable String text, @Nullable Drawable icon, @NonNull List<Drawable> icons, @Nullable String label, @NonNull List<String> labels, @Nullable Intent intent, @NonNull List<Intent> intents, @Nullable OnClickListener onClickListener, @NonNull List<OnClickListener> onClickListeners, @NonNull EntityConfidence<String> entityConfidence, @NonNull EntityConfidence<String> entityConfidence, int logType, int logType, @NonNull String versionInfo) { @NonNull String versionInfo) { Preconditions.checkArgument(labels.size() == intents.size()); Preconditions.checkArgument(icons.size() == intents.size()); Preconditions.checkArgument(onClickListeners.size() == intents.size()); mText = text; mText = text; mIcon = icon; mIcons = icons; mLabel = label; mLabels = labels; mIntent = intent; mIntents = intents; mOnClickListener = onClickListener; mOnClickListeners = onClickListeners; mEntityConfidence = new EntityConfidence<>(entityConfidence); mEntityConfidence = new EntityConfidence<>(entityConfidence); mEntities = mEntityConfidence.getEntities(); mEntities = mEntityConfidence.getEntities(); mLogType = logType; mLogType = logType; Loading Loading @@ -109,35 +113,106 @@ public final class TextClassification { } } /** /** * Returns an icon that may be rendered on a widget used to act on the classified text. * Returns the number of actions that are available to act on the classified text. * @see #getIntent(int) * @see #getLabel(int) * @see #getIcon(int) * @see #getOnClickListener(int) */ @IntRange(from = 0) public int getActionCount() { return mIntents.size(); } /** * Returns one of the icons that maybe rendered on a widget used to act on the classified text. * @param index Index of the action to get the icon for. * @throws IndexOutOfBoundsException if the specified index is out of range. * @see #getActionCount() for the number of entities available. * @see #getIntent(int) * @see #getLabel(int) * @see #getOnClickListener(int) */ @Nullable public Drawable getIcon(int index) { return mIcons.get(index); } /** * Returns an icon for the default intent that may be rendered on a widget used to act on the * classified text. */ */ @Nullable @Nullable public Drawable getIcon() { public Drawable getIcon() { return mIcon; return mIcons.isEmpty() ? null : mIcons.get(0); } } /** /** * Returns a label that may be rendered on a widget used to act on the classified text. * Returns one of the labels that may be rendered on a widget used to act on the classified * text. * @param index Index of the action to get the label for. * @throws IndexOutOfBoundsException if the specified index is out of range. * @see #getActionCount() * @see #getIntent(int) * @see #getIcon(int) * @see #getOnClickListener(int) */ @Nullable public CharSequence getLabel(int index) { return mLabels.get(index); } /** * Returns a label for the default intent that may be rendered on a widget used to act on the * classified text. */ */ @Nullable @Nullable public CharSequence getLabel() { public CharSequence getLabel() { return mLabel; return mLabels.isEmpty() ? null : mLabels.get(0); } /** * Returns one of the intents that may be fired to act on the classified text. * @param index Index of the action to get the intent for. * @throws IndexOutOfBoundsException if the specified index is out of range. * @see #getActionCount() * @see #getLabel(int) * @see #getIcon(int) * @see #getOnClickListener(int) */ @Nullable public Intent getIntent(int index) { return mIntents.get(index); } } /** /** * Returns an intent that may be fired to act on the classified text. * Returns the default intent that may be fired to act on the classified text. */ */ @Nullable @Nullable public Intent getIntent() { public Intent getIntent() { return mIntent; return mIntents.isEmpty() ? null : mIntents.get(0); } /** * Returns one of the OnClickListeners that may be triggered to act on the classified text. * @param index Index of the action to get the click listener for. * @throws IndexOutOfBoundsException if the specified index is out of range. * @see #getActionCount() * @see #getIntent(int) * @see #getLabel(int) * @see #getIcon(int) */ @Nullable public OnClickListener getOnClickListener(int index) { return mOnClickListeners.get(index); } } /** /** * Returns an OnClickListener that may be triggered to act on the classified text. * Returns the default OnClickListener that may be triggered to act on the classified text. */ */ @Nullable @Nullable public OnClickListener getOnClickListener() { public OnClickListener getOnClickListener() { return mOnClickListener; return mOnClickListeners.isEmpty() ? null : mOnClickListeners.get(0); } } /** /** Loading @@ -160,8 +235,8 @@ public final class TextClassification { @Override @Override public String toString() { public String toString() { return String.format("TextClassification {" return String.format("TextClassification {" + "text=%s, entities=%s, label=%s, intent=%s}", + "text=%s, entities=%s, labels=%s, intents=%s}", mText, mEntityConfidence, mLabel, mIntent); mText, mEntityConfidence, mLabels, mIntents); } } /** /** Loading @@ -184,10 +259,10 @@ public final class TextClassification { public static final class Builder { public static final class Builder { @NonNull private String mText; @NonNull private String mText; @Nullable private Drawable mIcon; @NonNull private final List<Drawable> mIcons = new ArrayList<>(); @Nullable private String mLabel; @NonNull private final List<String> mLabels = new ArrayList<>(); @Nullable private Intent mIntent; @NonNull private final List<Intent> mIntents = new ArrayList<>(); @Nullable private OnClickListener mOnClickListener; @NonNull private final List<OnClickListener> mOnClickListeners = new ArrayList<>(); @NonNull private final EntityConfidence<String> mEntityConfidence = @NonNull private final EntityConfidence<String> mEntityConfidence = new EntityConfidence<>(); new EntityConfidence<>(); private int mLogType; private int mLogType; Loading Loading @@ -216,26 +291,57 @@ public final class TextClassification { } } /** /** * Sets an icon that may be rendered on a widget used to act on the classified text. * Adds an action that may be performed on the classified text. The label and icon are used * for rendering of widgets that offer the intent. Actions should be added in order of * priority and the first one will be treated as the default. */ public Builder addAction( Intent intent, @Nullable String label, @Nullable Drawable icon, @Nullable OnClickListener onClickListener) { mIntents.add(intent); mLabels.add(label); mIcons.add(icon); mOnClickListeners.add(onClickListener); return this; } /** * Removes all actions. */ public Builder clearActions() { mIntents.clear(); mOnClickListeners.clear(); mLabels.clear(); mIcons.clear(); return this; } /** * Sets the icon for the default action that may be rendered on a widget used to act on the * classified text. */ */ public Builder setIcon(@Nullable Drawable icon) { public Builder setIcon(@Nullable Drawable icon) { mIcon = icon; ensureDefaultActionAvailable(); mIcons.set(0, icon); return this; return this; } } /** /** * Sets a label that may be rendered on a widget used to act on the classified text. * Sets the label for the default action that may be rendered on a widget used to act on the * classified text. */ */ public Builder setLabel(@Nullable String label) { public Builder setLabel(@Nullable String label) { mLabel = label; ensureDefaultActionAvailable(); mLabels.set(0, label); return this; return this; } } /** /** * Sets an intent that may be fired to act on the classified text. * Sets the intent for the default action that may be fired to act on the classified text. */ */ public Builder setIntent(@Nullable Intent intent) { public Builder setIntent(@Nullable Intent intent) { mIntent = intent; ensureDefaultActionAvailable(); mIntents.set(0, intent); return this; return this; } } Loading @@ -249,10 +355,12 @@ public final class TextClassification { } } /** /** * Sets an OnClickListener that may be triggered to act on the classified text. * Sets the OnClickListener for the default action that may be triggered to act on the * classified text. */ */ public Builder setOnClickListener(@Nullable OnClickListener onClickListener) { public Builder setOnClickListener(@Nullable OnClickListener onClickListener) { mOnClickListener = onClickListener; ensureDefaultActionAvailable(); mOnClickListeners.set(0, onClickListener); return this; return this; } } Loading @@ -265,12 +373,22 @@ public final class TextClassification { return this; return this; } } /** * Ensures that we have at we have storage for the default action. */ private void ensureDefaultActionAvailable() { if (mIntents.isEmpty()) mIntents.add(null); if (mLabels.isEmpty()) mLabels.add(null); if (mIcons.isEmpty()) mIcons.add(null); if (mOnClickListeners.isEmpty()) mOnClickListeners.add(null); } /** /** * Builds and returns a {@link TextClassification} object. * Builds and returns a {@link TextClassification} object. */ */ public TextClassification build() { public TextClassification build() { return new TextClassification( return new TextClassification( mText, mIcon, mLabel, mIntent, mOnClickListener, mEntityConfidence, mText, mIcons, mLabels, mIntents, mOnClickListeners, mEntityConfidence, mLogType, mVersionInfo); mLogType, mVersionInfo); } } } } Loading core/java/android/view/textclassifier/TextClassifierImpl.java +81 −37 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.net.Uri; import android.os.LocaleList; import android.os.LocaleList; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; import android.provider.Browser; import android.provider.Browser; import android.provider.ContactsContract; import android.text.Spannable; import android.text.Spannable; import android.text.TextUtils; import android.text.TextUtils; import android.text.method.WordIterator; import android.text.method.WordIterator; Loading Loading @@ -356,7 +357,16 @@ final class TextClassifierImpl implements TextClassifier { final String type = getHighestScoringType(classifications); final String type = getHighestScoringType(classifications); builder.setLogType(IntentFactory.getLogType(type)); builder.setLogType(IntentFactory.getLogType(type)); final Intent intent = IntentFactory.create(mContext, type, text.toString()); final List<Intent> intents = IntentFactory.create(mContext, type, text.toString()); for (Intent intent : intents) { extendClassificationWithIntent(intent, builder); } return builder.setVersionInfo(getVersionInfo()).build(); } /** Extends the classification with the intent if it can be resolved. */ private void extendClassificationWithIntent(Intent intent, TextClassification.Builder builder) { final PackageManager pm; final PackageManager pm; final ResolveInfo resolveInfo; final ResolveInfo resolveInfo; if (intent != null) { if (intent != null) { Loading @@ -367,30 +377,29 @@ final class TextClassifierImpl implements TextClassifier { resolveInfo = null; resolveInfo = null; } } if (resolveInfo != null && resolveInfo.activityInfo != null) { if (resolveInfo != null && resolveInfo.activityInfo != null) { builder.setIntent(intent) .setOnClickListener(TextClassification.createStartActivityOnClickListener( mContext, intent)); final String packageName = resolveInfo.activityInfo.packageName; final String packageName = resolveInfo.activityInfo.packageName; CharSequence label; Drawable icon; if ("android".equals(packageName)) { if ("android".equals(packageName)) { // Requires the chooser to find an activity to handle the intent. // Requires the chooser to find an activity to handle the intent. builder.setLabel(IntentFactory.getLabel(mContext, type)); label = IntentFactory.getLabel(mContext, intent); icon = null; } else { } else { // A default activity will handle the intent. // A default activity will handle the intent. intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name)); intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name)); Drawable icon = resolveInfo.activityInfo.loadIcon(pm); icon = resolveInfo.activityInfo.loadIcon(pm); if (icon == null) { if (icon == null) { icon = resolveInfo.loadIcon(pm); icon = resolveInfo.loadIcon(pm); } } builder.setIcon(icon); label = resolveInfo.activityInfo.loadLabel(pm); CharSequence label = resolveInfo.activityInfo.loadLabel(pm); if (label == null) { if (label == null) { label = resolveInfo.loadLabel(pm); label = resolveInfo.loadLabel(pm); } } builder.setLabel(label != null ? label.toString() : null); } } builder.addAction( intent, label != null ? label.toString() : null, icon, TextClassification.createStartActivityOnClickListener(mContext, intent)); } } return builder.setVersionInfo(getVersionInfo()).build(); } } private static int getHintFlags(CharSequence text, int start, int end) { private static int getHintFlags(CharSequence text, int start, int end) { Loading Loading @@ -477,10 +486,11 @@ final class TextClassifierImpl implements TextClassifier { if (results.length > 0) { if (results.length > 0) { final String type = getHighestScoringType(results); final String type = getHighestScoringType(results); if (matches(type, linkMask)) { if (matches(type, linkMask)) { final Intent intent = IntentFactory.create( // For links without disambiguation, we simply use the default intent. final List<Intent> intents = IntentFactory.create( context, type, text.substring(selectionStart, selectionEnd)); context, type, text.substring(selectionStart, selectionEnd)); if (hasActivityHandler(context, intent)) { if (!intents.isEmpty() && hasActivityHandler(context, intents.get(0))) { final ClickableSpan span = createSpan(context, intent); final ClickableSpan span = createSpan(context, intents.get(0)); spans.add(new SpanSpec(selectionStart, selectionEnd, span)); spans.add(new SpanSpec(selectionStart, selectionEnd, span)); } } } } Loading Loading @@ -564,7 +574,7 @@ final class TextClassifierImpl implements TextClassifier { }; }; } } private static boolean hasActivityHandler(Context context, @Nullable Intent intent) { private static boolean hasActivityHandler(Context context, Intent intent) { if (intent == null) { if (intent == null) { return false; return false; } } Loading Loading @@ -625,20 +635,32 @@ final class TextClassifierImpl implements TextClassifier { private IntentFactory() {} private IntentFactory() {} @Nullable @NonNull public static Intent create(Context context, String type, String text) { public static List<Intent> create(Context context, String type, String text) { final List<Intent> intents = new ArrayList<>(); type = type.trim().toLowerCase(Locale.ENGLISH); type = type.trim().toLowerCase(Locale.ENGLISH); text = text.trim(); text = text.trim(); switch (type) { switch (type) { case TextClassifier.TYPE_EMAIL: case TextClassifier.TYPE_EMAIL: return new Intent(Intent.ACTION_SENDTO) intents.add(new Intent(Intent.ACTION_SENDTO) .setData(Uri.parse(String.format("mailto:%s", text))); .setData(Uri.parse(String.format("mailto:%s", text)))); intents.add(new Intent(Intent.ACTION_INSERT_OR_EDIT) .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE) .putExtra(ContactsContract.Intents.Insert.EMAIL, text)); break; case TextClassifier.TYPE_PHONE: case TextClassifier.TYPE_PHONE: return new Intent(Intent.ACTION_DIAL) intents.add(new Intent(Intent.ACTION_DIAL) .setData(Uri.parse(String.format("tel:%s", text))); .setData(Uri.parse(String.format("tel:%s", text)))); intents.add(new Intent(Intent.ACTION_INSERT_OR_EDIT) .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE) .putExtra(ContactsContract.Intents.Insert.PHONE, text)); intents.add(new Intent(Intent.ACTION_SENDTO) .setData(Uri.parse(String.format("smsto:%s", text)))); break; case TextClassifier.TYPE_ADDRESS: case TextClassifier.TYPE_ADDRESS: return new Intent(Intent.ACTION_VIEW) intents.add(new Intent(Intent.ACTION_VIEW) .setData(Uri.parse(String.format("geo:0,0?q=%s", text))); .setData(Uri.parse(String.format("geo:0,0?q=%s", text)))); break; case TextClassifier.TYPE_URL: case TextClassifier.TYPE_URL: final String httpPrefix = "http://"; final String httpPrefix = "http://"; final String httpsPrefix = "https://"; final String httpsPrefix = "https://"; Loading @@ -649,28 +671,50 @@ final class TextClassifierImpl implements TextClassifier { } else { } else { text = httpPrefix + text; text = httpPrefix + text; } } return new Intent(Intent.ACTION_VIEW, Uri.parse(text)) intents.add(new Intent(Intent.ACTION_VIEW, Uri.parse(text)) .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName())); default: break; return null; } } return intents; } } @Nullable @Nullable public static String getLabel(Context context, String type) { public static String getLabel(Context context, @Nullable Intent intent) { type = type.trim().toLowerCase(Locale.ENGLISH); if (intent == null || intent.getAction() == null) { switch (type) { return null; case TextClassifier.TYPE_EMAIL: } return context.getString(com.android.internal.R.string.email); switch (intent.getAction()) { case TextClassifier.TYPE_PHONE: case Intent.ACTION_DIAL: return context.getString(com.android.internal.R.string.dial); return context.getString(com.android.internal.R.string.dial); case TextClassifier.TYPE_ADDRESS: case Intent.ACTION_SENDTO: switch (intent.getScheme()) { case "mailto": return context.getString(com.android.internal.R.string.email); case "smsto": return context.getString(com.android.internal.R.string.sms); default: return null; } case Intent.ACTION_INSERT_OR_EDIT: switch (intent.getDataString()) { case ContactsContract.Contacts.CONTENT_ITEM_TYPE: return context.getString(com.android.internal.R.string.add_contact); default: return null; } case Intent.ACTION_VIEW: switch (intent.getScheme()) { case "geo": return context.getString(com.android.internal.R.string.map); return context.getString(com.android.internal.R.string.map); case TextClassifier.TYPE_URL: case "http": // fall through case "https": return context.getString(com.android.internal.R.string.browse); return context.getString(com.android.internal.R.string.browse); default: default: return null; return null; } } default: return null; } } } @Nullable @Nullable Loading Loading
api/current.txt +7 −0 Original line number Original line Diff line number Diff line Loading @@ -48693,19 +48693,26 @@ package android.view.inputmethod { package android.view.textclassifier { package android.view.textclassifier { public final class TextClassification { public final class TextClassification { method public int getActionCount(); method public float getConfidenceScore(java.lang.String); method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); method public java.lang.String getEntity(int); method public int getEntityCount(); method public int getEntityCount(); method public android.graphics.drawable.Drawable getIcon(int); method public android.graphics.drawable.Drawable getIcon(); method public android.graphics.drawable.Drawable getIcon(); method public android.content.Intent getIntent(int); method public android.content.Intent getIntent(); method public android.content.Intent getIntent(); method public java.lang.CharSequence getLabel(int); method public java.lang.CharSequence getLabel(); method public java.lang.CharSequence getLabel(); method public android.view.View.OnClickListener getOnClickListener(int); method public android.view.View.OnClickListener getOnClickListener(); method public android.view.View.OnClickListener getOnClickListener(); method public java.lang.String getText(); method public java.lang.String getText(); } } public static final class TextClassification.Builder { public static final class TextClassification.Builder { ctor public TextClassification.Builder(); ctor public TextClassification.Builder(); method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification.Builder clearActions(); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
api/system-current.txt +7 −0 Original line number Original line Diff line number Diff line Loading @@ -52389,19 +52389,26 @@ package android.view.inputmethod { package android.view.textclassifier { package android.view.textclassifier { public final class TextClassification { public final class TextClassification { method public int getActionCount(); method public float getConfidenceScore(java.lang.String); method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); method public java.lang.String getEntity(int); method public int getEntityCount(); method public int getEntityCount(); method public android.graphics.drawable.Drawable getIcon(int); method public android.graphics.drawable.Drawable getIcon(); method public android.graphics.drawable.Drawable getIcon(); method public android.content.Intent getIntent(int); method public android.content.Intent getIntent(); method public android.content.Intent getIntent(); method public java.lang.CharSequence getLabel(int); method public java.lang.CharSequence getLabel(); method public java.lang.CharSequence getLabel(); method public android.view.View.OnClickListener getOnClickListener(int); method public android.view.View.OnClickListener getOnClickListener(); method public android.view.View.OnClickListener getOnClickListener(); method public java.lang.String getText(); method public java.lang.String getText(); } } public static final class TextClassification.Builder { public static final class TextClassification.Builder { ctor public TextClassification.Builder(); ctor public TextClassification.Builder(); method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification.Builder clearActions(); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
api/test-current.txt +7 −0 Original line number Original line Diff line number Diff line Loading @@ -49249,19 +49249,26 @@ package android.view.inputmethod { package android.view.textclassifier { package android.view.textclassifier { public final class TextClassification { public final class TextClassification { method public int getActionCount(); method public float getConfidenceScore(java.lang.String); method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); method public java.lang.String getEntity(int); method public int getEntityCount(); method public int getEntityCount(); method public android.graphics.drawable.Drawable getIcon(int); method public android.graphics.drawable.Drawable getIcon(); method public android.graphics.drawable.Drawable getIcon(); method public android.content.Intent getIntent(int); method public android.content.Intent getIntent(); method public android.content.Intent getIntent(); method public java.lang.CharSequence getLabel(int); method public java.lang.CharSequence getLabel(); method public java.lang.CharSequence getLabel(); method public android.view.View.OnClickListener getOnClickListener(int); method public android.view.View.OnClickListener getOnClickListener(); method public android.view.View.OnClickListener getOnClickListener(); method public java.lang.String getText(); method public java.lang.String getText(); } } public static final class TextClassification.Builder { public static final class TextClassification.Builder { ctor public TextClassification.Builder(); ctor public TextClassification.Builder(); method public android.view.textclassifier.TextClassification.Builder addAction(android.content.Intent, java.lang.String, android.graphics.drawable.Drawable, android.view.View.OnClickListener); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification build(); method public android.view.textclassifier.TextClassification.Builder clearActions(); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent); method public android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
core/java/android/view/textclassifier/TextClassification.java +153 −35 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.view.textclassifier.TextClassifier.EntityType; import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.List; import java.util.List; /** /** Loading @@ -41,10 +42,10 @@ public final class TextClassification { static final TextClassification EMPTY = new TextClassification.Builder().build(); static final TextClassification EMPTY = new TextClassification.Builder().build(); @NonNull private final String mText; @NonNull private final String mText; @Nullable private final Drawable mIcon; @NonNull private final List<Drawable> mIcons; @Nullable private final String mLabel; @NonNull private final List<String> mLabels; @Nullable private final Intent mIntent; @NonNull private final List<Intent> mIntents; @Nullable private final OnClickListener mOnClickListener; @NonNull private final List<OnClickListener> mOnClickListeners; @NonNull private final EntityConfidence<String> mEntityConfidence; @NonNull private final EntityConfidence<String> mEntityConfidence; @NonNull private final List<String> mEntities; @NonNull private final List<String> mEntities; private int mLogType; private int mLogType; Loading @@ -52,18 +53,21 @@ public final class TextClassification { private TextClassification( private TextClassification( @Nullable String text, @Nullable String text, @Nullable Drawable icon, @NonNull List<Drawable> icons, @Nullable String label, @NonNull List<String> labels, @Nullable Intent intent, @NonNull List<Intent> intents, @Nullable OnClickListener onClickListener, @NonNull List<OnClickListener> onClickListeners, @NonNull EntityConfidence<String> entityConfidence, @NonNull EntityConfidence<String> entityConfidence, int logType, int logType, @NonNull String versionInfo) { @NonNull String versionInfo) { Preconditions.checkArgument(labels.size() == intents.size()); Preconditions.checkArgument(icons.size() == intents.size()); Preconditions.checkArgument(onClickListeners.size() == intents.size()); mText = text; mText = text; mIcon = icon; mIcons = icons; mLabel = label; mLabels = labels; mIntent = intent; mIntents = intents; mOnClickListener = onClickListener; mOnClickListeners = onClickListeners; mEntityConfidence = new EntityConfidence<>(entityConfidence); mEntityConfidence = new EntityConfidence<>(entityConfidence); mEntities = mEntityConfidence.getEntities(); mEntities = mEntityConfidence.getEntities(); mLogType = logType; mLogType = logType; Loading Loading @@ -109,35 +113,106 @@ public final class TextClassification { } } /** /** * Returns an icon that may be rendered on a widget used to act on the classified text. * Returns the number of actions that are available to act on the classified text. * @see #getIntent(int) * @see #getLabel(int) * @see #getIcon(int) * @see #getOnClickListener(int) */ @IntRange(from = 0) public int getActionCount() { return mIntents.size(); } /** * Returns one of the icons that maybe rendered on a widget used to act on the classified text. * @param index Index of the action to get the icon for. * @throws IndexOutOfBoundsException if the specified index is out of range. * @see #getActionCount() for the number of entities available. * @see #getIntent(int) * @see #getLabel(int) * @see #getOnClickListener(int) */ @Nullable public Drawable getIcon(int index) { return mIcons.get(index); } /** * Returns an icon for the default intent that may be rendered on a widget used to act on the * classified text. */ */ @Nullable @Nullable public Drawable getIcon() { public Drawable getIcon() { return mIcon; return mIcons.isEmpty() ? null : mIcons.get(0); } } /** /** * Returns a label that may be rendered on a widget used to act on the classified text. * Returns one of the labels that may be rendered on a widget used to act on the classified * text. * @param index Index of the action to get the label for. * @throws IndexOutOfBoundsException if the specified index is out of range. * @see #getActionCount() * @see #getIntent(int) * @see #getIcon(int) * @see #getOnClickListener(int) */ @Nullable public CharSequence getLabel(int index) { return mLabels.get(index); } /** * Returns a label for the default intent that may be rendered on a widget used to act on the * classified text. */ */ @Nullable @Nullable public CharSequence getLabel() { public CharSequence getLabel() { return mLabel; return mLabels.isEmpty() ? null : mLabels.get(0); } /** * Returns one of the intents that may be fired to act on the classified text. * @param index Index of the action to get the intent for. * @throws IndexOutOfBoundsException if the specified index is out of range. * @see #getActionCount() * @see #getLabel(int) * @see #getIcon(int) * @see #getOnClickListener(int) */ @Nullable public Intent getIntent(int index) { return mIntents.get(index); } } /** /** * Returns an intent that may be fired to act on the classified text. * Returns the default intent that may be fired to act on the classified text. */ */ @Nullable @Nullable public Intent getIntent() { public Intent getIntent() { return mIntent; return mIntents.isEmpty() ? null : mIntents.get(0); } /** * Returns one of the OnClickListeners that may be triggered to act on the classified text. * @param index Index of the action to get the click listener for. * @throws IndexOutOfBoundsException if the specified index is out of range. * @see #getActionCount() * @see #getIntent(int) * @see #getLabel(int) * @see #getIcon(int) */ @Nullable public OnClickListener getOnClickListener(int index) { return mOnClickListeners.get(index); } } /** /** * Returns an OnClickListener that may be triggered to act on the classified text. * Returns the default OnClickListener that may be triggered to act on the classified text. */ */ @Nullable @Nullable public OnClickListener getOnClickListener() { public OnClickListener getOnClickListener() { return mOnClickListener; return mOnClickListeners.isEmpty() ? null : mOnClickListeners.get(0); } } /** /** Loading @@ -160,8 +235,8 @@ public final class TextClassification { @Override @Override public String toString() { public String toString() { return String.format("TextClassification {" return String.format("TextClassification {" + "text=%s, entities=%s, label=%s, intent=%s}", + "text=%s, entities=%s, labels=%s, intents=%s}", mText, mEntityConfidence, mLabel, mIntent); mText, mEntityConfidence, mLabels, mIntents); } } /** /** Loading @@ -184,10 +259,10 @@ public final class TextClassification { public static final class Builder { public static final class Builder { @NonNull private String mText; @NonNull private String mText; @Nullable private Drawable mIcon; @NonNull private final List<Drawable> mIcons = new ArrayList<>(); @Nullable private String mLabel; @NonNull private final List<String> mLabels = new ArrayList<>(); @Nullable private Intent mIntent; @NonNull private final List<Intent> mIntents = new ArrayList<>(); @Nullable private OnClickListener mOnClickListener; @NonNull private final List<OnClickListener> mOnClickListeners = new ArrayList<>(); @NonNull private final EntityConfidence<String> mEntityConfidence = @NonNull private final EntityConfidence<String> mEntityConfidence = new EntityConfidence<>(); new EntityConfidence<>(); private int mLogType; private int mLogType; Loading Loading @@ -216,26 +291,57 @@ public final class TextClassification { } } /** /** * Sets an icon that may be rendered on a widget used to act on the classified text. * Adds an action that may be performed on the classified text. The label and icon are used * for rendering of widgets that offer the intent. Actions should be added in order of * priority and the first one will be treated as the default. */ public Builder addAction( Intent intent, @Nullable String label, @Nullable Drawable icon, @Nullable OnClickListener onClickListener) { mIntents.add(intent); mLabels.add(label); mIcons.add(icon); mOnClickListeners.add(onClickListener); return this; } /** * Removes all actions. */ public Builder clearActions() { mIntents.clear(); mOnClickListeners.clear(); mLabels.clear(); mIcons.clear(); return this; } /** * Sets the icon for the default action that may be rendered on a widget used to act on the * classified text. */ */ public Builder setIcon(@Nullable Drawable icon) { public Builder setIcon(@Nullable Drawable icon) { mIcon = icon; ensureDefaultActionAvailable(); mIcons.set(0, icon); return this; return this; } } /** /** * Sets a label that may be rendered on a widget used to act on the classified text. * Sets the label for the default action that may be rendered on a widget used to act on the * classified text. */ */ public Builder setLabel(@Nullable String label) { public Builder setLabel(@Nullable String label) { mLabel = label; ensureDefaultActionAvailable(); mLabels.set(0, label); return this; return this; } } /** /** * Sets an intent that may be fired to act on the classified text. * Sets the intent for the default action that may be fired to act on the classified text. */ */ public Builder setIntent(@Nullable Intent intent) { public Builder setIntent(@Nullable Intent intent) { mIntent = intent; ensureDefaultActionAvailable(); mIntents.set(0, intent); return this; return this; } } Loading @@ -249,10 +355,12 @@ public final class TextClassification { } } /** /** * Sets an OnClickListener that may be triggered to act on the classified text. * Sets the OnClickListener for the default action that may be triggered to act on the * classified text. */ */ public Builder setOnClickListener(@Nullable OnClickListener onClickListener) { public Builder setOnClickListener(@Nullable OnClickListener onClickListener) { mOnClickListener = onClickListener; ensureDefaultActionAvailable(); mOnClickListeners.set(0, onClickListener); return this; return this; } } Loading @@ -265,12 +373,22 @@ public final class TextClassification { return this; return this; } } /** * Ensures that we have at we have storage for the default action. */ private void ensureDefaultActionAvailable() { if (mIntents.isEmpty()) mIntents.add(null); if (mLabels.isEmpty()) mLabels.add(null); if (mIcons.isEmpty()) mIcons.add(null); if (mOnClickListeners.isEmpty()) mOnClickListeners.add(null); } /** /** * Builds and returns a {@link TextClassification} object. * Builds and returns a {@link TextClassification} object. */ */ public TextClassification build() { public TextClassification build() { return new TextClassification( return new TextClassification( mText, mIcon, mLabel, mIntent, mOnClickListener, mEntityConfidence, mText, mIcons, mLabels, mIntents, mOnClickListeners, mEntityConfidence, mLogType, mVersionInfo); mLogType, mVersionInfo); } } } } Loading
core/java/android/view/textclassifier/TextClassifierImpl.java +81 −37 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.net.Uri; import android.os.LocaleList; import android.os.LocaleList; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; import android.provider.Browser; import android.provider.Browser; import android.provider.ContactsContract; import android.text.Spannable; import android.text.Spannable; import android.text.TextUtils; import android.text.TextUtils; import android.text.method.WordIterator; import android.text.method.WordIterator; Loading Loading @@ -356,7 +357,16 @@ final class TextClassifierImpl implements TextClassifier { final String type = getHighestScoringType(classifications); final String type = getHighestScoringType(classifications); builder.setLogType(IntentFactory.getLogType(type)); builder.setLogType(IntentFactory.getLogType(type)); final Intent intent = IntentFactory.create(mContext, type, text.toString()); final List<Intent> intents = IntentFactory.create(mContext, type, text.toString()); for (Intent intent : intents) { extendClassificationWithIntent(intent, builder); } return builder.setVersionInfo(getVersionInfo()).build(); } /** Extends the classification with the intent if it can be resolved. */ private void extendClassificationWithIntent(Intent intent, TextClassification.Builder builder) { final PackageManager pm; final PackageManager pm; final ResolveInfo resolveInfo; final ResolveInfo resolveInfo; if (intent != null) { if (intent != null) { Loading @@ -367,30 +377,29 @@ final class TextClassifierImpl implements TextClassifier { resolveInfo = null; resolveInfo = null; } } if (resolveInfo != null && resolveInfo.activityInfo != null) { if (resolveInfo != null && resolveInfo.activityInfo != null) { builder.setIntent(intent) .setOnClickListener(TextClassification.createStartActivityOnClickListener( mContext, intent)); final String packageName = resolveInfo.activityInfo.packageName; final String packageName = resolveInfo.activityInfo.packageName; CharSequence label; Drawable icon; if ("android".equals(packageName)) { if ("android".equals(packageName)) { // Requires the chooser to find an activity to handle the intent. // Requires the chooser to find an activity to handle the intent. builder.setLabel(IntentFactory.getLabel(mContext, type)); label = IntentFactory.getLabel(mContext, intent); icon = null; } else { } else { // A default activity will handle the intent. // A default activity will handle the intent. intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name)); intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name)); Drawable icon = resolveInfo.activityInfo.loadIcon(pm); icon = resolveInfo.activityInfo.loadIcon(pm); if (icon == null) { if (icon == null) { icon = resolveInfo.loadIcon(pm); icon = resolveInfo.loadIcon(pm); } } builder.setIcon(icon); label = resolveInfo.activityInfo.loadLabel(pm); CharSequence label = resolveInfo.activityInfo.loadLabel(pm); if (label == null) { if (label == null) { label = resolveInfo.loadLabel(pm); label = resolveInfo.loadLabel(pm); } } builder.setLabel(label != null ? label.toString() : null); } } builder.addAction( intent, label != null ? label.toString() : null, icon, TextClassification.createStartActivityOnClickListener(mContext, intent)); } } return builder.setVersionInfo(getVersionInfo()).build(); } } private static int getHintFlags(CharSequence text, int start, int end) { private static int getHintFlags(CharSequence text, int start, int end) { Loading Loading @@ -477,10 +486,11 @@ final class TextClassifierImpl implements TextClassifier { if (results.length > 0) { if (results.length > 0) { final String type = getHighestScoringType(results); final String type = getHighestScoringType(results); if (matches(type, linkMask)) { if (matches(type, linkMask)) { final Intent intent = IntentFactory.create( // For links without disambiguation, we simply use the default intent. final List<Intent> intents = IntentFactory.create( context, type, text.substring(selectionStart, selectionEnd)); context, type, text.substring(selectionStart, selectionEnd)); if (hasActivityHandler(context, intent)) { if (!intents.isEmpty() && hasActivityHandler(context, intents.get(0))) { final ClickableSpan span = createSpan(context, intent); final ClickableSpan span = createSpan(context, intents.get(0)); spans.add(new SpanSpec(selectionStart, selectionEnd, span)); spans.add(new SpanSpec(selectionStart, selectionEnd, span)); } } } } Loading Loading @@ -564,7 +574,7 @@ final class TextClassifierImpl implements TextClassifier { }; }; } } private static boolean hasActivityHandler(Context context, @Nullable Intent intent) { private static boolean hasActivityHandler(Context context, Intent intent) { if (intent == null) { if (intent == null) { return false; return false; } } Loading Loading @@ -625,20 +635,32 @@ final class TextClassifierImpl implements TextClassifier { private IntentFactory() {} private IntentFactory() {} @Nullable @NonNull public static Intent create(Context context, String type, String text) { public static List<Intent> create(Context context, String type, String text) { final List<Intent> intents = new ArrayList<>(); type = type.trim().toLowerCase(Locale.ENGLISH); type = type.trim().toLowerCase(Locale.ENGLISH); text = text.trim(); text = text.trim(); switch (type) { switch (type) { case TextClassifier.TYPE_EMAIL: case TextClassifier.TYPE_EMAIL: return new Intent(Intent.ACTION_SENDTO) intents.add(new Intent(Intent.ACTION_SENDTO) .setData(Uri.parse(String.format("mailto:%s", text))); .setData(Uri.parse(String.format("mailto:%s", text)))); intents.add(new Intent(Intent.ACTION_INSERT_OR_EDIT) .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE) .putExtra(ContactsContract.Intents.Insert.EMAIL, text)); break; case TextClassifier.TYPE_PHONE: case TextClassifier.TYPE_PHONE: return new Intent(Intent.ACTION_DIAL) intents.add(new Intent(Intent.ACTION_DIAL) .setData(Uri.parse(String.format("tel:%s", text))); .setData(Uri.parse(String.format("tel:%s", text)))); intents.add(new Intent(Intent.ACTION_INSERT_OR_EDIT) .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE) .putExtra(ContactsContract.Intents.Insert.PHONE, text)); intents.add(new Intent(Intent.ACTION_SENDTO) .setData(Uri.parse(String.format("smsto:%s", text)))); break; case TextClassifier.TYPE_ADDRESS: case TextClassifier.TYPE_ADDRESS: return new Intent(Intent.ACTION_VIEW) intents.add(new Intent(Intent.ACTION_VIEW) .setData(Uri.parse(String.format("geo:0,0?q=%s", text))); .setData(Uri.parse(String.format("geo:0,0?q=%s", text)))); break; case TextClassifier.TYPE_URL: case TextClassifier.TYPE_URL: final String httpPrefix = "http://"; final String httpPrefix = "http://"; final String httpsPrefix = "https://"; final String httpsPrefix = "https://"; Loading @@ -649,28 +671,50 @@ final class TextClassifierImpl implements TextClassifier { } else { } else { text = httpPrefix + text; text = httpPrefix + text; } } return new Intent(Intent.ACTION_VIEW, Uri.parse(text)) intents.add(new Intent(Intent.ACTION_VIEW, Uri.parse(text)) .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName())); default: break; return null; } } return intents; } } @Nullable @Nullable public static String getLabel(Context context, String type) { public static String getLabel(Context context, @Nullable Intent intent) { type = type.trim().toLowerCase(Locale.ENGLISH); if (intent == null || intent.getAction() == null) { switch (type) { return null; case TextClassifier.TYPE_EMAIL: } return context.getString(com.android.internal.R.string.email); switch (intent.getAction()) { case TextClassifier.TYPE_PHONE: case Intent.ACTION_DIAL: return context.getString(com.android.internal.R.string.dial); return context.getString(com.android.internal.R.string.dial); case TextClassifier.TYPE_ADDRESS: case Intent.ACTION_SENDTO: switch (intent.getScheme()) { case "mailto": return context.getString(com.android.internal.R.string.email); case "smsto": return context.getString(com.android.internal.R.string.sms); default: return null; } case Intent.ACTION_INSERT_OR_EDIT: switch (intent.getDataString()) { case ContactsContract.Contacts.CONTENT_ITEM_TYPE: return context.getString(com.android.internal.R.string.add_contact); default: return null; } case Intent.ACTION_VIEW: switch (intent.getScheme()) { case "geo": return context.getString(com.android.internal.R.string.map); return context.getString(com.android.internal.R.string.map); case TextClassifier.TYPE_URL: case "http": // fall through case "https": return context.getString(com.android.internal.R.string.browse); return context.getString(com.android.internal.R.string.browse); default: default: return null; return null; } } default: return null; } } } @Nullable @Nullable Loading