1 package android.app.assist; 2 3 import android.annotation.FlaggedApi; 4 import android.annotation.Nullable; 5 import android.compat.annotation.UnsupportedAppUsage; 6 import android.content.ClipData; 7 import android.content.Intent; 8 import android.net.Uri; 9 import android.os.Build; 10 import android.os.Bundle; 11 import android.os.Parcel; 12 import android.os.Parcelable; 13 14 /** 15 * Holds information about the content an application is viewing, to hand to an 16 * assistant at the user's request. This is filled in by 17 * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. 18 */ 19 public class AssistContent implements Parcelable { 20 /** 21 * Extra for a {@link Bundle} that provides contextual AppFunction's information about the 22 * content currently being viewed in the application. 23 * <p> 24 * This extra can be optionally supplied in the {@link AssistContent#getExtras()} bundle. 25 * <p> 26 * The schema of the {@link Bundle} in this extra is defined in the AppFunction SDK. 27 * 28 * @see android.app.appfunctions.AppFunctionManager 29 */ 30 @FlaggedApi(android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER) 31 public static final String EXTRA_APP_FUNCTION_DATA = 32 "android.app.assist.extra.APP_FUNCTION_DATA"; 33 34 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 35 private boolean mIsAppProvidedIntent = false; 36 private boolean mIsAppProvidedWebUri = false; 37 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 38 private Intent mIntent; 39 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 40 private String mStructuredData; 41 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 42 private ClipData mClipData; 43 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 44 private Uri mUri; 45 private Uri mSessionTransferUri; 46 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 47 private final Bundle mExtras; 48 AssistContent()49 public AssistContent() { 50 mExtras = new Bundle(); 51 } 52 53 /** 54 * Create an AssistContent with extras initialized. 55 * 56 * @hide 57 */ AssistContent(@ndroid.annotation.NonNull Bundle extras)58 public AssistContent(@android.annotation.NonNull Bundle extras) { 59 mExtras = extras; 60 } 61 62 /** 63 * Called by {@link android.app.ActivityThread} to set the default Intent based on 64 * {@link android.app.Activity#getIntent Activity.getIntent}. 65 * 66 * <p>Automatically populates {@link #mUri} if that Intent is an {@link Intent#ACTION_VIEW} 67 * of a web (http or https scheme) URI.</p> 68 * 69 * @hide 70 */ setDefaultIntent(Intent intent)71 public void setDefaultIntent(Intent intent) { 72 mIntent = intent; 73 mIsAppProvidedIntent = false; 74 mIsAppProvidedWebUri = false; 75 mUri = null; 76 if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) { 77 Uri uri = intent.getData(); 78 if (uri != null) { 79 if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) { 80 mUri = uri; 81 } 82 } 83 } 84 } 85 86 /** 87 * Sets the Intent associated with the content, describing the current top-level context of 88 * the activity. If this contains a reference to a piece of data related to the activity, 89 * be sure to set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} so the accessibility 90 * service can access it. 91 */ setIntent(Intent intent)92 public void setIntent(Intent intent) { 93 mIsAppProvidedIntent = true; 94 mIntent = intent; 95 } 96 97 /** 98 * Returns the current {@link #setIntent} if one is set, else the default Intent obtained from 99 * {@link android.app.Activity#getIntent Activity.getIntent}. Can be modified in-place. 100 */ getIntent()101 public Intent getIntent() { 102 return mIntent; 103 } 104 105 /** 106 * Returns whether or not the current Intent was explicitly provided in 107 * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. If not, 108 * the Intent was automatically set based on 109 * {@link android.app.Activity#getIntent Activity.getIntent}. 110 */ isAppProvidedIntent()111 public boolean isAppProvidedIntent() { 112 return mIsAppProvidedIntent; 113 } 114 115 /** 116 * Optional additional content items that are involved with 117 * the current UI. Access to this content will be granted to the assistant as if you 118 * are sending it through an Intent with {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}. 119 */ setClipData(ClipData clip)120 public void setClipData(ClipData clip) { 121 mClipData = clip; 122 } 123 124 /** 125 * Return the current {@link #setClipData}, which you can modify in-place. 126 */ getClipData()127 public ClipData getClipData() { 128 return mClipData; 129 } 130 131 /** 132 * Sets optional structured data regarding the content being viewed. The provided data 133 * must be a string represented with <a href="http://json-ld.org/">JSON-LD</a> using the 134 * <a href="http://schema.org/">schema.org</a> vocabulary. 135 */ setStructuredData(String structuredData)136 public void setStructuredData(String structuredData) { 137 mStructuredData = structuredData; 138 } 139 140 /** 141 * Returns the current {@link #setStructuredData}. 142 */ getStructuredData()143 public String getStructuredData() { 144 return mStructuredData; 145 } 146 147 /** 148 * Set a web URI associated with the current data being shown to the user. 149 * This URI could be opened in a web browser, or in the app as an 150 * {@link Intent#ACTION_VIEW} Intent, to show the same data that is currently 151 * being displayed by it. The URI here should be something that is transportable 152 * off the device into other environments to acesss the same data as is currently 153 * being shown in the app; if the app does not have such a representation, it should 154 * leave the null and only report the local intent and clip data. 155 */ setWebUri(Uri uri)156 public void setWebUri(Uri uri) { 157 mIsAppProvidedWebUri = true; 158 mUri = uri; 159 } 160 161 /** 162 * Return the content's web URI as per {@link #setWebUri(android.net.Uri)}, or null if 163 * there is none. 164 */ getWebUri()165 public Uri getWebUri() { 166 return mUri; 167 } 168 169 /** 170 * Returns whether or not the current {@link #getWebUri} was explicitly provided in 171 * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. If not, 172 * the Intent was automatically set based on 173 * {@link android.app.Activity#getIntent Activity.getIntent}. 174 */ isAppProvidedWebUri()175 public boolean isAppProvidedWebUri() { 176 return mIsAppProvidedWebUri; 177 } 178 179 /** 180 * This method can be used to provide a {@link Uri} which will be utilized when transitioning a 181 * user's session to another surface. 182 * 183 * <p>If provided, instead of using the URI provided in {@link #setWebUri}, the 184 * "Open in browser" feature will use this URI to transition the current session from one 185 * surface to the other. Apps may choose to encode session or user information into this 186 * URI in order to provide a better session transfer experience. However, while this URI will 187 * only be available to the system and not other applications, developers should not encode 188 * authentication credentials into this URI, because it will be surfaced in the browser URL bar 189 * and may be copied and shared from there. 190 * 191 * <p>When providing this URI, developers should still continue to provide 192 * {@link #setWebUri} for backwards compatibility with features such as 193 * <a href="https://developer.android.com/guide/components/activities/recents#url-sharing"> 194 * recents URL sharing</a> which facilitate link sharing with other users and would not benefit 195 * from a session-transfer URI. 196 * 197 * @see android.app.Activity#requestOpenInBrowserEducation() 198 */ 199 @FlaggedApi(com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_TO_WEB_EDUCATION) setSessionTransferUri(@ullable Uri uri)200 public void setSessionTransferUri(@Nullable Uri uri) { 201 mSessionTransferUri = uri; 202 } 203 204 /** 205 * Return the content's session transfer web URI as per 206 * {@link #setSessionTransferUri(android.net.Uri)}, or null if there is none. 207 */ 208 @FlaggedApi(com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_TO_WEB_EDUCATION) 209 @Nullable getSessionTransferUri()210 public Uri getSessionTransferUri() { 211 return mSessionTransferUri; 212 } 213 214 /** 215 * Return Bundle for extra vendor-specific data that can be modified and examined. 216 */ getExtras()217 public Bundle getExtras() { 218 return mExtras; 219 } 220 221 @UnsupportedAppUsage AssistContent(Parcel in)222 AssistContent(Parcel in) { 223 if (in.readInt() != 0) { 224 mIntent = Intent.CREATOR.createFromParcel(in); 225 } 226 if (in.readInt() != 0) { 227 mClipData = ClipData.CREATOR.createFromParcel(in); 228 } 229 if (in.readInt() != 0) { 230 mUri = Uri.CREATOR.createFromParcel(in); 231 } 232 if (in.readInt() != 0) { 233 mSessionTransferUri = Uri.CREATOR.createFromParcel(in); 234 } 235 if (in.readInt() != 0) { 236 mStructuredData = in.readString(); 237 } 238 mIsAppProvidedIntent = in.readInt() == 1; 239 mExtras = in.readBundle(); 240 mIsAppProvidedWebUri = in.readInt() == 1; 241 } 242 243 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) writeToParcelInternal(Parcel dest, int flags)244 void writeToParcelInternal(Parcel dest, int flags) { 245 if (mIntent != null) { 246 dest.writeInt(1); 247 mIntent.writeToParcel(dest, flags); 248 } else { 249 dest.writeInt(0); 250 } 251 if (mClipData != null) { 252 dest.writeInt(1); 253 mClipData.writeToParcel(dest, flags); 254 } else { 255 dest.writeInt(0); 256 } 257 if (mUri != null) { 258 dest.writeInt(1); 259 mUri.writeToParcel(dest, flags); 260 } else { 261 dest.writeInt(0); 262 } 263 if (mSessionTransferUri != null) { 264 dest.writeInt(1); 265 mSessionTransferUri.writeToParcel(dest, flags); 266 } else { 267 dest.writeInt(0); 268 } 269 if (mStructuredData != null) { 270 dest.writeInt(1); 271 dest.writeString(mStructuredData); 272 } else { 273 dest.writeInt(0); 274 } 275 dest.writeInt(mIsAppProvidedIntent ? 1 : 0); 276 dest.writeBundle(mExtras); 277 dest.writeInt(mIsAppProvidedWebUri ? 1 : 0); 278 } 279 280 @Override describeContents()281 public int describeContents() { 282 return 0; 283 } 284 285 @Override writeToParcel(Parcel dest, int flags)286 public void writeToParcel(Parcel dest, int flags) { 287 writeToParcelInternal(dest, flags); 288 } 289 290 public static final @android.annotation.NonNull Parcelable.Creator<AssistContent> CREATOR 291 = new Parcelable.Creator<AssistContent>() { 292 public AssistContent createFromParcel(Parcel in) { 293 return new AssistContent(in); 294 } 295 296 public AssistContent[] newArray(int size) { 297 return new AssistContent[size]; 298 } 299 }; 300 } 301