1c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus/* 2c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Copyright (C) 2018 The Android Open Source Project 3c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 4c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Licensed under the Apache License, Version 2.0 (the "License"); 5c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * you may not use this file except in compliance with the License. 6c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * You may obtain a copy of the License at 7c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 8c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * http://www.apache.org/licenses/LICENSE-2.0 9c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 10c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Unless required by applicable law or agreed to in writing, software 11c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * distributed under the License is distributed on an "AS IS" BASIS, 12c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * See the License for the specific language governing permissions and 14c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * limitations under the License. 15c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 16c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 17ddf3bdd8f2a3afe5d8fd041f542ad4005a2ac869Aurimas Liutikaspackage androidx.textclassifier; 18c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 19c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.content.Intent; 20c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.graphics.Bitmap; 21c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.graphics.Canvas; 22c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.graphics.drawable.BitmapDrawable; 23c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.graphics.drawable.Drawable; 24c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.os.Parcel; 25c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.os.Parcelable; 26c65e03f6e729f8c5e5a766a1076ee3531dbdc0b2Aurimas Liutikas 27ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.FloatRange; 28ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.IntRange; 29ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull; 30ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.Nullable; 31ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RestrictTo; 32ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.collection.ArrayMap; 33c65e03f6e729f8c5e5a766a1076ee3531dbdc0b2Aurimas Liutikasimport androidx.core.os.LocaleListCompat; 34ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.util.Preconditions; 35c65e03f6e729f8c5e5a766a1076ee3531dbdc0b2Aurimas Liutikasimport androidx.textclassifier.TextClassifier.EntityType; 36c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 37c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.ArrayList; 385e36a8223de2be293b905f5e022eaf74a090f6acJan Althausimport java.util.Calendar; 39c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.List; 40c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.Locale; 41c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.Map; 42c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 43c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus/** 44c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Information for generating a widget to handle classified text. 45c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 46c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <p>A TextClassification object contains icons, labels, and intents that may be used to build a 47c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * widget that can be used to act on classified text. There is the concept of a <i>primary 48c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * action</i> and other <i>secondary actions</i>. 49c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 50c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <p>e.g. building a view that, when clicked, shares the classified text with the preferred app: 51c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 52c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <pre>{@code 53c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * // Called preferably outside the UiThread. 54c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * TextClassification classification = textClassifier.classifyText(allText, 10, 25); 55c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 56c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * // Called on the UiThread. 57c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Button button = new Button(context); 58c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * button.setCompoundDrawablesWithIntrinsicBounds(classification.getIcon(), null, null, null); 59c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * button.setText(classification.getLabel()); 60c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * button.setOnClickListener(v -> context.startActivity(classification.getIntent())); 61c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * }</pre> 62c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 63c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * TODO: describe how to start action mode for classified text. 64c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 65c08637c95be5e31268baf9b434a2d710423181f5Jan Althauspublic final class TextClassification implements Parcelable { 66c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 67c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 68c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @hide 69c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 70c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @RestrictTo(RestrictTo.Scope.LIBRARY) 71c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus static final TextClassification EMPTY = new TextClassification.Builder().build(); 72c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 73c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus // TODO: investigate a way to derive this based on device properties. 74c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private static final int MAX_PRIMARY_ICON_SIZE = 192; 75c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private static final int MAX_SECONDARY_ICON_SIZE = 144; 76c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 77c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable private final String mText; 78c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable private final Drawable mPrimaryIcon; 79c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable private final String mPrimaryLabel; 80c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable private final Intent mPrimaryIntent; 81c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final List<Drawable> mSecondaryIcons; 82c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final List<String> mSecondaryLabels; 83c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final List<Intent> mSecondaryIntents; 84c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final EntityConfidence mEntityConfidence; 85c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final String mSignature; 86c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 87c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private TextClassification( 88c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable String text, 89c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable Drawable primaryIcon, 90c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable String primaryLabel, 91c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable Intent primaryIntent, 92c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull List<Drawable> secondaryIcons, 93c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull List<String> secondaryLabels, 94c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull List<Intent> secondaryIntents, 95c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull Map<String, Float> entityConfidence, 96c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull String signature) { 97c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus Preconditions.checkArgument(secondaryLabels.size() == secondaryIntents.size()); 98c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus Preconditions.checkArgument(secondaryIcons.size() == secondaryIntents.size()); 99c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mText = text; 100c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIcon = primaryIcon; 101c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryLabel = primaryLabel; 102c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIntent = primaryIntent; 103c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIcons = secondaryIcons; 104c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryLabels = secondaryLabels; 105c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIntents = secondaryIntents; 106c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mEntityConfidence = new EntityConfidence(entityConfidence); 107c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSignature = signature; 108c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 109c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 110c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 111c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Gets the classified text. 112c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 113c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 114c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public String getText() { 115c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mText; 116c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 117c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 118c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 119c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns the number of entities found in the classified text. 120c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 121c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @IntRange(from = 0) 122c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public int getEntityCount() { 123c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mEntityConfidence.getEntities().size(); 124c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 125c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 126c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 127c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns the entity at the specified index. Entities are ordered from high confidence 128c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * to low confidence. 129c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 130c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @throws IndexOutOfBoundsException if the specified index is out of range. 131c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getEntityCount() for the number of entities available. 132c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 133c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull 134c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public @EntityType String getEntity(int index) { 135c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mEntityConfidence.getEntities().get(index); 136c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 137c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 138c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 139c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns the confidence score for the specified entity. The value ranges from 140c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 0 (low confidence) to 1 (high confidence). 0 indicates that the entity was not found for the 141c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * classified text. 142c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 143c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @FloatRange(from = 0.0, to = 1.0) 144c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public float getConfidenceScore(@EntityType String entity) { 145c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mEntityConfidence.getConfidenceScore(entity); 146c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 147c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 148c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 149c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns the number of <i>secondary</i> actions that are available to act on the classified 150c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * text. 151c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 152c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <p><strong>Note: </strong> that there may or may not be a <i>primary</i> action. 153c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 154c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryIntent(int) 155c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryLabel(int) 156c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryIcon(int) 157c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 158c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @IntRange(from = 0) 159c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public int getSecondaryActionsCount() { 160c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mSecondaryIntents.size(); 161c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 162c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 163c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 164c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns one of the <i>secondary</i> icons that maybe rendered on a widget used to act on the 165c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * classified text. 166c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 167c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param index Index of the action to get the icon for. 168c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @throws IndexOutOfBoundsException if the specified index is out of range. 169c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryActionsCount() for the number of actions available. 170c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryIntent(int) 171c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryLabel(int) 172c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getIcon() 173c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 174c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 175c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Drawable getSecondaryIcon(int index) { 176c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mSecondaryIcons.get(index); 177c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 178c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 179c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 180c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns an icon for the <i>primary</i> intent that may be rendered on a widget used to act 181c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * on the classified text. 182c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 183c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryIcon(int) 184c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 185c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 186c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Drawable getIcon() { 187c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mPrimaryIcon; 188c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 189c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 190c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 191c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns one of the <i>secondary</i> labels that may be rendered on a widget used to act on 192c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * the classified text. 193c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 194c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param index Index of the action to get the label for. 195c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @throws IndexOutOfBoundsException if the specified index is out of range. 196c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryActionsCount() 197c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryIntent(int) 198c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryIcon(int) 199c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getLabel() 200c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 201c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 202c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public CharSequence getSecondaryLabel(int index) { 203c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mSecondaryLabels.get(index); 204c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 205c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 206c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 207c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns a label for the <i>primary</i> intent that may be rendered on a widget used to act 208c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * on the classified text. 209c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 210c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryLabel(int) 211c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 212c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 213c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public CharSequence getLabel() { 214c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mPrimaryLabel; 215c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 216c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 217c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 218c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns one of the <i>secondary</i> intents that may be fired to act on the classified text. 219c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 220c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param index Index of the action to get the intent for. 221c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @throws IndexOutOfBoundsException if the specified index is out of range. 222c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryActionsCount() 223c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryLabel(int) 224c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryIcon(int) 225c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getIntent() 226c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 227c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 228c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Intent getSecondaryIntent(int index) { 229c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mSecondaryIntents.get(index); 230c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 231c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 232c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 233c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns the <i>primary</i> intent that may be fired to act on the classified text. 234c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 235c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #getSecondaryIntent(int) 236c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 237c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 238c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Intent getIntent() { 239c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mPrimaryIntent; 240c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 241c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 242c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 243c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns the signature for this object. 244c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * The TextClassifier that generates this object may use it as a way to internally identify 245c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * this object. 246c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 247c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull 248c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public String getSignature() { 249c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mSignature; 250c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 251c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 252c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 253c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public String toString() { 254c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return String.format(Locale.US, "TextClassification {" 255c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus + "text=%s, entities=%s, " 256c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus + "primaryLabel=%s, secondaryLabels=%s, " 257c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus + "primaryIntent=%s, secondaryIntents=%s, " 258c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus + "signature=%s}", 259c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mText, mEntityConfidence, 260c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryLabel, mSecondaryLabels, 261c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIntent, mSecondaryIntents, 262c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSignature); 263c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 264c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 265c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 266c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public int describeContents() { 267c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return 0; 268c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 269c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 270c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 271c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public void writeToParcel(Parcel dest, int flags) { 272c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeString(mText); 273c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final Bitmap primaryIconBitmap = drawableToBitmap(mPrimaryIcon, MAX_PRIMARY_ICON_SIZE); 274c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeInt(primaryIconBitmap != null ? 1 : 0); 275c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (primaryIconBitmap != null) { 276c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus primaryIconBitmap.writeToParcel(dest, flags); 277c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 278c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeString(mPrimaryLabel); 279c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeInt(mPrimaryIntent != null ? 1 : 0); 280c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (mPrimaryIntent != null) { 281c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIntent.writeToParcel(dest, flags); 282c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 283c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeTypedList(drawablesToBitmaps(mSecondaryIcons, MAX_SECONDARY_ICON_SIZE)); 284c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeStringList(mSecondaryLabels); 285c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeTypedList(mSecondaryIntents); 286c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mEntityConfidence.writeToParcel(dest, flags); 287c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeString(mSignature); 288c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 289c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 290c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final Parcelable.Creator<TextClassification> CREATOR = 291c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus new Parcelable.Creator<TextClassification>() { 292c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 293c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public TextClassification createFromParcel(Parcel in) { 294c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return new TextClassification(in); 295c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 296c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 297c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 298c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public TextClassification[] newArray(int size) { 299c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return new TextClassification[size]; 300c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 301c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus }; 302c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 303c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private TextClassification(Parcel in) { 304c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mText = in.readString(); 305c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIcon = in.readInt() == 0 306c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus ? null : new BitmapDrawable(null, Bitmap.CREATOR.createFromParcel(in)); 307c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryLabel = in.readString(); 308c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIntent = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in); 309c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIcons = bitmapsToDrawables(in.createTypedArrayList(Bitmap.CREATOR)); 310c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryLabels = in.createStringArrayList(); 311c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIntents = in.createTypedArrayList(Intent.CREATOR); 312c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in); 313c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSignature = in.readString(); 314c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 315c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 316c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 317c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns a Bitmap representation of the Drawable 318c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 319c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param drawable The drawable to convert. 320c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param maxDims The maximum edge length of the resulting bitmap (in pixels). 321c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 322c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 323c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private static Bitmap drawableToBitmap(@Nullable Drawable drawable, int maxDims) { 324c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (drawable == null) { 325c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return null; 326c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 327c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final int actualWidth = Math.max(1, drawable.getIntrinsicWidth()); 328c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final int actualHeight = Math.max(1, drawable.getIntrinsicHeight()); 329c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final double scaleWidth = ((double) maxDims) / actualWidth; 330c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final double scaleHeight = ((double) maxDims) / actualHeight; 331c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final double scale = Math.min(1.0, Math.min(scaleWidth, scaleHeight)); 332c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final int width = (int) (actualWidth * scale); 333c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final int height = (int) (actualHeight * scale); 334c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (drawable instanceof BitmapDrawable) { 335c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; 336c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (actualWidth != width || actualHeight != height) { 337c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return Bitmap.createScaledBitmap( 338c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus bitmapDrawable.getBitmap(), width, height, /*filter=*/false); 339c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } else { 340c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return bitmapDrawable.getBitmap(); 341c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 342c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } else { 343c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 344c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final Canvas canvas = new Canvas(bitmap); 345c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 346c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus drawable.draw(canvas); 347c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return bitmap; 348c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 349c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 350c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 351c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 352c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns a list of drawables converted to Bitmaps 353c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 354c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param drawables The drawables to convert. 355c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param maxDims The maximum edge length of the resulting bitmaps (in pixels). 356c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 357c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private static List<Bitmap> drawablesToBitmaps(List<Drawable> drawables, int maxDims) { 358c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final List<Bitmap> bitmaps = new ArrayList<>(drawables.size()); 359c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus for (Drawable drawable : drawables) { 360c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus bitmaps.add(drawableToBitmap(drawable, maxDims)); 361c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 362c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return bitmaps; 363c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 364c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 365c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Returns a list of drawable wrappers for a list of bitmaps. */ 366c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private static List<Drawable> bitmapsToDrawables(List<Bitmap> bitmaps) { 367c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus final List<Drawable> drawables = new ArrayList<>(bitmaps.size()); 368c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus for (Bitmap bitmap : bitmaps) { 369c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (bitmap != null) { 370c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus drawables.add(new BitmapDrawable(null, bitmap)); 371c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } else { 372c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus drawables.add(null); 373c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 374c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 375c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return drawables; 376c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 377c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 378c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 379c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Builder for building {@link TextClassification} objects. 380c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 381c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <p>e.g. 382c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 383c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <pre>{@code 384c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * TextClassification classification = new TextClassification.Builder() 385c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * .setText(classifiedText) 386c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * .setEntityType(TextClassifier.TYPE_EMAIL, 0.9) 387c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * .setEntityType(TextClassifier.TYPE_OTHER, 0.1) 388c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * .setPrimaryAction(intent, label, icon) 389c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * .addSecondaryAction(intent1, label1, icon1) 390c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * .addSecondaryAction(intent2, label2, icon2) 391c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * .build(); 392c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * }</pre> 393c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 394c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final class Builder { 395c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 396c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private String mText; 397c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final List<Drawable> mSecondaryIcons = new ArrayList<>(); 398c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final List<String> mSecondaryLabels = new ArrayList<>(); 399c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final List<Intent> mSecondaryIntents = new ArrayList<>(); 400c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private final Map<String, Float> mEntityConfidence = new ArrayMap<>(); 401c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable Drawable mPrimaryIcon; 402c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable String mPrimaryLabel; 403c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable Intent mPrimaryIntent; 404c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull private String mSignature = ""; 405c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 406c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 407c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Sets the classified text. 408c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 409c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder setText(@Nullable String text) { 410c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mText = text; 411c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 412c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 413c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 414c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 415c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Sets an entity type for the classification result and assigns a confidence score. 416c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * If a confidence score had already been set for the specified entity type, this will 417c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * override that score. 418c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 419c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param confidenceScore a value from 0 (low confidence) to 1 (high confidence). 420c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 0 implies the entity does not exist for the classified text. 421c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Values greater than 1 are clamped to 1. 422c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 423c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder setEntityType( 424c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @NonNull @EntityType String type, 425c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @FloatRange(from = 0.0, to = 1.0) float confidenceScore) { 426c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mEntityConfidence.put(type, confidenceScore); 427c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 428c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 429c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 430c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 431c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Adds an <i>secondary</i> action that may be performed on the classified text. 432c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Secondary actions are in addition to the <i>primary</i> action which may or may not 433c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * exist. 434c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 435c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <p>The label and icon are used for rendering of widgets that offer the intent. 436c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Actions should be added in order of priority. 437c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 438c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <p><stong>Note: </stong> If all input parameters are set to null, this method will be a 439c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * no-op. 440c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 441c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #setPrimaryAction(Intent, String, Drawable) 442c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 443c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder addSecondaryAction( 444c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable Intent intent, @Nullable String label, @Nullable Drawable icon) { 445c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (intent != null || label != null || icon != null) { 446c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIntents.add(intent); 447c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryLabels.add(label); 448c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIcons.add(icon); 449c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 450c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 451c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 452c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 453c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 454c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Removes all the <i>secondary</i> actions. 455c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 456c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder clearSecondaryActions() { 457c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIntents.clear(); 458c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryLabels.clear(); 459c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIcons.clear(); 460c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 461c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 462c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 463c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 464c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Sets the <i>primary</i> action that may be performed on the classified text. This is 465c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * equivalent to calling {@code setIntent(intent).setLabel(label).setIcon(icon)}. 466c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 467c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <p><strong>Note: </strong>If all input parameters are null, there will be no 468c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <i>primary</i> action but there may still be <i>secondary</i> actions. 469c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 470c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #addSecondaryAction(Intent, String, Drawable) 471c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 472c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder setPrimaryAction( 473c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable Intent intent, @Nullable String label, @Nullable Drawable icon) { 474c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return setIntent(intent).setLabel(label).setIcon(icon); 475c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 476c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 477c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 478c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Sets the icon for the <i>primary</i> action that may be rendered on a widget used to act 479c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * on the classified text. 480c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 481c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #setPrimaryAction(Intent, String, Drawable) 482c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 483c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder setIcon(@Nullable Drawable icon) { 484c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIcon = icon; 485c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 486c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 487c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 488c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 489c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Sets the label for the <i>primary</i> action that may be rendered on a widget used to 490c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * act on the classified text. 491c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 492c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #setPrimaryAction(Intent, String, Drawable) 493c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 494c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder setLabel(@Nullable String label) { 495c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryLabel = label; 496c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 497c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 498c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 499c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 500c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Sets the intent for the <i>primary</i> action that may be fired to act on the classified 501c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * text. 502c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 503c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #setPrimaryAction(Intent, String, Drawable) 504c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 505c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder setIntent(@Nullable Intent intent) { 506c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIntent = intent; 507c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 508c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 509c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 510c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 511c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Sets a signature for the TextClassification object. 512c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * The TextClassifier that generates the TextClassification object may use it as a way to 513c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * internally identify the TextClassification object. 514c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 515c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Builder setSignature(@NonNull String signature) { 516c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSignature = Preconditions.checkNotNull(signature); 517c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 518c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 519c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 520c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 521c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Builds and returns a {@link TextClassification} object. 522c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 523c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public TextClassification build() { 524c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return new TextClassification( 525c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mText, 526c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mPrimaryIcon, mPrimaryLabel, mPrimaryIntent, 527c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mSecondaryIcons, mSecondaryLabels, mSecondaryIntents, 528c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mEntityConfidence, mSignature); 529c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 530c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 531c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 532c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 533c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Optional input parameters for generating TextClassification. 534c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 535c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final class Options implements Parcelable { 536c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 5375e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus private @Nullable LocaleListCompat mDefaultLocales; 5385e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus private @Nullable Calendar mReferenceTime; 539fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus private @Nullable String mCallingPackageName; 540c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 541c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Options() {} 542c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 543c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 544c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @param defaultLocales ordered list of locale preferences that may be used to disambiguate 545c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * the provided text. If no locale preferences exist, set this to null or an empty 546c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * locale list. 547c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 5485e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus public Options setDefaultLocales(@Nullable LocaleListCompat defaultLocales) { 5495e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus mDefaultLocales = defaultLocales; 5505e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus return this; 5515e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus } 5525e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus 5535e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus /** 5545e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus * @param referenceTime reference time based on which relative dates (e.g. "tomorrow" should 5555e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus * be interpreted. This should usually be the time when the text was originally 5565e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus * composed. If no reference time is set, now is used. 5575e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus */ 5585e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus public Options setReferenceTime(Calendar referenceTime) { 5595e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus mReferenceTime = referenceTime; 560c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 561c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 562c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 563c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 564fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus * @param packageName name of the package from which the call was made. 565fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus * 566fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus * @hide 567fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus */ 568fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus @RestrictTo(RestrictTo.Scope.LIBRARY) 569fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus public Options setCallingPackageName(@Nullable String packageName) { 570fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus mCallingPackageName = packageName; 571fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus return this; 572fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus } 573fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus 574fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus /** 575c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @return ordered list of locale preferences that can be used to disambiguate 576c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * the provided text. 577c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 578c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Nullable 5795e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus public LocaleListCompat getDefaultLocales() { 580c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return mDefaultLocales; 581c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 582c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 5835e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus /** 5845e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus * @return reference time based on which relative dates (e.g. "tomorrow") should be 5855e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus * interpreted. 5865e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus */ 5875e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus @Nullable 5885e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus public Calendar getReferenceTime() { 5895e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus return mReferenceTime; 5905e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus } 5915e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus 592fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus /** 593fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus * @return name of the package from which the call was made. 594fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus */ 595fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus @Nullable 596fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus public String getCallingPackageName() { 597fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus return mCallingPackageName; 598fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus } 599fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus 600c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 601c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public int describeContents() { 602c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return 0; 603c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 604c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 605c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 606c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public void writeToParcel(Parcel dest, int flags) { 6075e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus dest.writeInt(mDefaultLocales != null ? 1 : 0); 608c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (mDefaultLocales != null) { 6095e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus dest.writeString(mDefaultLocales.toLanguageTags()); 6105e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus } 6115e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus dest.writeInt(mReferenceTime != null ? 1 : 0); 6125e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus if (mReferenceTime != null) { 6135e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus dest.writeSerializable(mReferenceTime); 614c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 615fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus dest.writeString(mCallingPackageName); 616c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 617c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 618c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final Parcelable.Creator<Options> CREATOR = 619c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus new Parcelable.Creator<Options>() { 620c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 621c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Options createFromParcel(Parcel in) { 622c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return new Options(in); 623c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 624c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 625c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 626c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public Options[] newArray(int size) { 627c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return new Options[size]; 628c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 629c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus }; 630c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 631c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private Options(Parcel in) { 6325e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus if (in.readInt() > 0) { 6335e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus mDefaultLocales = LocaleListCompat.forLanguageTags(in.readString()); 6345e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus } 6355e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus if (in.readInt() > 0) { 6365e36a8223de2be293b905f5e022eaf74a090f6acJan Althaus mReferenceTime = (Calendar) in.readSerializable(); 637c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 638fa2de0056203d1cd59387416a1ebcee587c4b151Jan Althaus mCallingPackageName = in.readString(); 639c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 640c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 641c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus} 642