ChooserTarget.java revision 13036beab1579fabe1a93e1839c13cb68a49adf6
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18package android.service.chooser; 19 20import android.app.Activity; 21import android.app.PendingIntent; 22import android.content.ComponentName; 23import android.content.Context; 24import android.content.Intent; 25import android.content.IntentFilter; 26import android.content.IntentSender; 27import android.graphics.Bitmap; 28import android.graphics.drawable.Icon; 29import android.os.Bundle; 30import android.os.Parcel; 31import android.os.Parcelable; 32import android.os.UserHandle; 33import android.util.Log; 34 35/** 36 * A ChooserTarget represents a deep-link into an application as returned by a 37 * {@link android.service.chooser.ChooserTargetService}. 38 * 39 * <p>A chooser target represents a specific deep link target into an application exposed 40 * for selection by the user. This might be a frequently emailed contact, a recently active 41 * group messaging conversation, a folder in a cloud storage app, a collection of related 42 * items published on a social media service or any other contextually relevant grouping 43 * of target app + relevant metadata.</p> 44 * 45 * <p>Creators of chooser targets should consult the relevant design guidelines for the type 46 * of target they are presenting. For example, targets involving people should be presented 47 * with a circular icon.</p> 48 */ 49public final class ChooserTarget implements Parcelable { 50 private static final String TAG = "ChooserTarget"; 51 52 /** 53 * The title of this target that will be shown to the user. The title may be truncated 54 * if it is too long to display in the space provided. 55 */ 56 private CharSequence mTitle; 57 58 /** 59 * The icon that will be shown to the user to represent this target. 60 * The system may resize this icon as appropriate. 61 */ 62 private Icon mIcon; 63 64 /** 65 * The IntentSender that will be used to deliver the intent to the target. 66 * It will be {@link android.content.Intent#fillIn(android.content.Intent, int)} filled in} 67 * by the real intent sent by the application. 68 */ 69 private IntentSender mIntentSender; 70 71 /** 72 * The score given to this item. It can be normalized. 73 */ 74 private float mScore; 75 76 /** 77 * Construct a deep link target for presentation by a chooser UI. 78 * 79 * <p>A target is composed of a title and an icon for presentation to the user. 80 * The UI presenting this target may truncate the title if it is too long to be presented 81 * in the available space, as well as crop, resize or overlay the supplied icon.</p> 82 * 83 * <p>The creator of a target may supply a ranking score. This score is assumed to be relative 84 * to the other targets supplied by the same 85 * {@link ChooserTargetService#onGetChooserTargets(ComponentName, IntentFilter) query}. 86 * Scores should be in the range from 0.0f (unlikely match) to 1.0f (very relevant match). 87 * Scores for a set of targets do not need to sum to 1.</p> 88 * 89 * <p>Before being sent, the PendingIntent supplied will be 90 * {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied 91 * to the chooser. When constructing a PendingIntent for use in a ChooserTarget, make sure 92 * that you permit the relevant fields to be filled in using the appropriate flags such as 93 * {@link Intent#FILL_IN_ACTION}, {@link Intent#FILL_IN_CATEGORIES}, 94 * {@link Intent#FILL_IN_DATA} and {@link Intent#FILL_IN_CLIP_DATA}. Note that 95 * {@link Intent#FILL_IN_CLIP_DATA} is required to appropriately receive URI permission grants 96 * for {@link Intent#ACTION_SEND} intents.</p> 97 * 98 * <p>Take care not to place custom {@link android.os.Parcelable} types into 99 * the PendingIntent as extras, as the system will not be able to unparcel it to merge 100 * additional extras.</p> 101 * 102 * @param title title of this target that will be shown to a user 103 * @param icon icon to represent this target 104 * @param score ranking score for this target between 0.0f and 1.0f, inclusive 105 * @param pendingIntent PendingIntent to fill in and send if the user chooses this target 106 */ 107 public ChooserTarget(CharSequence title, Icon icon, float score, 108 PendingIntent pendingIntent) { 109 this(title, icon, score, pendingIntent.getIntentSender()); 110 } 111 112 /** 113 * Construct a deep link target for presentation by a chooser UI. 114 * 115 * <p>A target is composed of a title and an icon for presentation to the user. 116 * The UI presenting this target may truncate the title if it is too long to be presented 117 * in the available space, as well as crop, resize or overlay the supplied icon.</p> 118 * 119 * <p>The creator of a target may supply a ranking score. This score is assumed to be relative 120 * to the other targets supplied by the same 121 * {@link ChooserTargetService#onGetChooserTargets(ComponentName, IntentFilter) query}. 122 * Scores should be in the range from 0.0f (unlikely match) to 1.0f (very relevant match). 123 * Scores for a set of targets do not need to sum to 1.</p> 124 * 125 * <p>Before being sent, the IntentSender supplied will be 126 * {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied 127 * to the chooser. When constructing an IntentSender for use in a ChooserTarget, make sure 128 * that you permit the relevant fields to be filled in using the appropriate flags such as 129 * {@link Intent#FILL_IN_ACTION}, {@link Intent#FILL_IN_CATEGORIES}, 130 * {@link Intent#FILL_IN_DATA} and {@link Intent#FILL_IN_CLIP_DATA}. Note that 131 * {@link Intent#FILL_IN_CLIP_DATA} is required to appropriately receive URI permission grants 132 * for {@link Intent#ACTION_SEND} intents.</p> 133 * 134 * <p>Take care not to place custom {@link android.os.Parcelable} types into 135 * the IntentSender as extras, as the system will not be able to unparcel it to merge 136 * additional extras.</p> 137 * 138 * @param title title of this target that will be shown to a user 139 * @param icon icon to represent this target 140 * @param score ranking score for this target between 0.0f and 1.0f, inclusive 141 * @param intentSender IntentSender to fill in and send if the user chooses this target 142 */ 143 public ChooserTarget(CharSequence title, Icon icon, float score, IntentSender intentSender) { 144 mTitle = title; 145 mIcon = icon; 146 if (score > 1.f || score < 0.f) { 147 throw new IllegalArgumentException("Score " + score + " out of range; " 148 + "must be between 0.0f and 1.0f"); 149 } 150 mScore = score; 151 mIntentSender = intentSender; 152 } 153 154 ChooserTarget(Parcel in) { 155 mTitle = in.readCharSequence(); 156 if (in.readInt() != 0) { 157 mIcon = Icon.CREATOR.createFromParcel(in); 158 } else { 159 mIcon = null; 160 } 161 mScore = in.readFloat(); 162 mIntentSender = IntentSender.readIntentSenderOrNullFromParcel(in); 163 } 164 165 /** 166 * Returns the title of this target for display to a user. The UI displaying the title 167 * may truncate this title if it is too long to be displayed in full. 168 * 169 * @return the title of this target, intended to be shown to a user 170 */ 171 public CharSequence getTitle() { 172 return mTitle; 173 } 174 175 /** 176 * Returns the icon representing this target for display to a user. The UI displaying the icon 177 * may crop, resize or overlay this icon. 178 * 179 * @return the icon representing this target, intended to be shown to a user 180 */ 181 public Icon getIcon() { 182 return mIcon; 183 } 184 185 /** 186 * Returns the ranking score supplied by the creator of this ChooserTarget. 187 * Values are between 0.0f and 1.0f. The UI displaying the target may 188 * take this score into account when sorting and merging targets from multiple sources. 189 * 190 * @return the ranking score for this target between 0.0f and 1.0f, inclusive 191 */ 192 public float getScore() { 193 return mScore; 194 } 195 196 /** 197 * Returns the raw IntentSender supplied by the ChooserTarget's creator. 198 * This may be null if the creator specified a regular Intent instead. 199 * 200 * <p>To fill in and send the intent, see {@link #sendIntent(Context, Intent)}.</p> 201 * 202 * @return the IntentSender supplied by the ChooserTarget's creator 203 */ 204 public IntentSender getIntentSender() { 205 return mIntentSender; 206 } 207 208 /** 209 * Fill in the IntentSender supplied by the ChooserTarget's creator and send it. 210 * 211 * @param context the sending Context; generally the Activity presenting the chooser UI 212 * @param fillInIntent the Intent provided to the Chooser to be sent to a selected target 213 * @return true if sending the Intent was successful 214 */ 215 public boolean sendIntent(Context context, Intent fillInIntent) { 216 if (fillInIntent != null) { 217 fillInIntent.migrateExtraStreamToClipData(); 218 fillInIntent.prepareToLeaveProcess(); 219 } 220 if (mIntentSender != null) { 221 try { 222 mIntentSender.sendIntent(context, 0, fillInIntent, null, null); 223 return true; 224 } catch (IntentSender.SendIntentException e) { 225 Log.e(TAG, "sendIntent " + this + " failed", e); 226 return false; 227 } 228 } else { 229 Log.e(TAG, "sendIntent " + this + " failed - no IntentSender to send"); 230 return false; 231 } 232 } 233 234 @Override 235 public String toString() { 236 return "ChooserTarget{" 237 + (mIntentSender != null ? mIntentSender.getCreatorPackage() : null) 238 + ", " 239 + "'" + mTitle 240 + "', " + mScore + "}"; 241 } 242 243 @Override 244 public int describeContents() { 245 return 0; 246 } 247 248 @Override 249 public void writeToParcel(Parcel dest, int flags) { 250 dest.writeCharSequence(mTitle); 251 if (mIcon != null) { 252 dest.writeInt(1); 253 mIcon.writeToParcel(dest, 0); 254 } else { 255 dest.writeInt(0); 256 } 257 dest.writeFloat(mScore); 258 IntentSender.writeIntentSenderOrNullToParcel(mIntentSender, dest); 259 } 260 261 public static final Creator<ChooserTarget> CREATOR 262 = new Creator<ChooserTarget>() { 263 @Override 264 public ChooserTarget createFromParcel(Parcel source) { 265 return new ChooserTarget(source); 266 } 267 268 @Override 269 public ChooserTarget[] newArray(int size) { 270 return new ChooserTarget[size]; 271 } 272 }; 273} 274