19f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn/** 29f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Copyright (c) 2010, The Android Open Source Project 39f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * 49f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 59f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * you may not use this file except in compliance with the License. 69f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * You may obtain a copy of the License at 79f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * 89f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 99f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * 109f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Unless required by applicable law or agreed to in writing, software 119f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 129f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * See the License for the specific language governing permissions and 149f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * limitations under the License. 159f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn */ 169f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 179f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornpackage android.content; 189f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 19d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevotimport static android.content.ContentProvider.maybeAddUserId; 20c14df8e73d093f839c4ea2585eade6ae6690d224Vladislav Kaznacheev 2123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport android.content.res.AssetFileDescriptor; 229f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.graphics.Bitmap; 239f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.net.Uri; 249f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.Parcel; 259f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.os.Parcelable; 26a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkeyimport android.os.StrictMode; 27acb69bb909d098cea284df47d794c17171d84c91Dianne Hackbornimport android.text.Html; 28acb69bb909d098cea284df47d794c17171d84c91Dianne Hackbornimport android.text.Spannable; 29acb69bb909d098cea284df47d794c17171d84c91Dianne Hackbornimport android.text.SpannableStringBuilder; 30acb69bb909d098cea284df47d794c17171d84c91Dianne Hackbornimport android.text.Spanned; 319f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport android.text.TextUtils; 32acb69bb909d098cea284df47d794c17171d84c91Dianne Hackbornimport android.text.style.URLSpan; 3323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport android.util.Log; 349f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 3523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport java.io.FileInputStream; 3623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport java.io.FileNotFoundException; 3723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport java.io.IOException; 3823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport java.io.InputStreamReader; 399f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackbornimport java.util.ArrayList; 409149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheevimport java.util.List; 419f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 429f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn/** 439f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Representation of a clipped data on the clipboard. 449f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * 457e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev * <p>ClipData is a complex type containing one or more Item instances, 469f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * each of which can hold one or more representations of an item of data. 477e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev * For display to the user, it also has a label.</p> 489f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * 49f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * <p>A ClipData contains a {@link ClipDescription}, which describes 50f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * important meta-data about the clip. In particular, its 51f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * {@link ClipDescription#getMimeType(int) getDescription().getMimeType(int)} 521040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * must return correct MIME type(s) describing the data in the clip. For help 531040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * in correctly constructing a clip with the correct MIME type, use 54327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * {@link #newPlainText(CharSequence, CharSequence)}, 55327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * {@link #newUri(ContentResolver, CharSequence, Uri)}, and 56327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * {@link #newIntent(CharSequence, Intent)}. 571040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * 5823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>Each Item instance can be one of three main classes of data: a simple 5923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * CharSequence of text, a single Intent object, or a Uri. See {@link Item} 6023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * for more details. 6123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 623aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference"> 633aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3> 643aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about using the clipboard framework, read the 653aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a> 663aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * developer guide.</p> 673aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div> 683aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * 6923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <a name="ImplementingPaste"></a> 7023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <h3>Implementing Paste or Drop</h3> 7123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 727e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev * <p>To implement a paste or drop of a ClipData object into an application, 7323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * the application must correctly interpret the data for its use. If the {@link Item} 7423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * it contains is simple text or an Intent, there is little to be done: text 7523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * can only be interpreted as text, and an Intent will typically be used for 7623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * creating shortcuts (such as placing icons on the home screen) or other 7723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * actions. 7823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 7923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>If all you want is the textual representation of the clipped data, you 8023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * can use the convenience method {@link Item#coerceToText Item.coerceToText}. 811040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * In this case there is generally no need to worry about the MIME types 82f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * reported by {@link ClipDescription#getMimeType(int) getDescription().getMimeType(int)}, 834465d1a03ee5fddc5987c19fc36b0bb79e19572fNewton Allen * since any clip item can always be converted to a string. 8423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 8523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>More complicated exchanges will be done through URIs, in particular 867e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev * "content:" URIs. A content URI allows the recipient of a ClipData item 8723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * to interact closely with the ContentProvider holding the data in order to 881040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * negotiate the transfer of that data. The clip must also be filled in with 89327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * the available MIME types; {@link #newUri(ContentResolver, CharSequence, Uri)} 901040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * will take care of correctly doing this. 9123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 9223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>For example, here is the paste function of a simple NotePad application. 9323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * When retrieving the data from the clipboard, it can do either two things: 9423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * if the clipboard contains a URI reference to an existing note, it copies 9523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * the entire structure of the note into a new note; otherwise, it simply 9623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * coerces the clip into text and uses that as the new note's contents. 9723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 9823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * {@sample development/samples/NotePad/src/com/example/android/notepad/NoteEditor.java 9923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * paste} 10023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 10123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>In many cases an application can paste various types of streams of data. For 10223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * example, an e-mail application may want to allow the user to paste an image 10323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * or other binary data as an attachment. This is accomplished through the 10423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * ContentResolver {@link ContentResolver#getStreamTypes(Uri, String)} and 10523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, android.os.Bundle)} 10623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * methods. These allow a client to discover the type(s) of data that a particular 10723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * content URI can make available as a stream and retrieve the stream of data. 10823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 10923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>For example, the implementation of {@link Item#coerceToText Item.coerceToText} 11023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * itself uses this to try to retrieve a URI clip as a stream of text: 11123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 112f6d952bbc85706031e1ad29ec389c1e02cfff433Dianne Hackborn * {@sample frameworks/base/core/java/android/content/ClipData.java coerceToText} 11323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 11423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <a name="ImplementingCopy"></a> 11523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <h3>Implementing Copy or Drag</h3> 11623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 1177e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev * <p>To be the source of a clip, the application must construct a ClipData 11823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * object that any recipient can interpret best for their context. If the clip 11923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * is to contain a simple text, Intent, or URI, this is easy: an {@link Item} 12023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * containing the appropriate data type can be constructed and used. 12123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 12223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>More complicated data types require the implementation of support in 12323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * a ContentProvider for describing and generating the data for the recipient. 12423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * A common scenario is one where an application places on the clipboard the 12523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * content: URI of an object that the user has copied, with the data at that 12623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * URI consisting of a complicated structure that only other applications with 12723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * direct knowledge of the structure can use. 12823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 12923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>For applications that do not have intrinsic knowledge of the data structure, 13023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * the content provider holding it can make the data available as an arbitrary 13123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * number of types of data streams. This is done by implementing the 13223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * ContentProvider {@link ContentProvider#getStreamTypes(Uri, String)} and 13323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * {@link ContentProvider#openTypedAssetFile(Uri, String, android.os.Bundle)} 13423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * methods. 13523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 13623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>Going back to our simple NotePad application, this is the implementation 13723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * it may have to convert a single note URI (consisting of a title and the note 13823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * text) into a stream of plain text data. 13923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 14023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * {@sample development/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java 14123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * stream} 14223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 14323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>The copy operation in our NotePad application is now just a simple matter 14423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * of making a clip containing the URI of the note being copied: 14523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 14623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * {@sample development/samples/NotePad/src/com/example/android/notepad/NotesList.java 14723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * copy} 14823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 14923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>Note if a paste operation needs this clip as text (for example to paste 15023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * into an editor), then {@link Item#coerceToText(Context)} will ask the content 15123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * provider for the clip URI as text and successfully paste the entire note. 1529f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn */ 153f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackbornpublic class ClipData implements Parcelable { 154f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn static final String[] MIMETYPES_TEXT_PLAIN = new String[] { 155f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn ClipDescription.MIMETYPE_TEXT_PLAIN }; 156acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn static final String[] MIMETYPES_TEXT_HTML = new String[] { 157acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn ClipDescription.MIMETYPE_TEXT_HTML }; 158f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn static final String[] MIMETYPES_TEXT_URILIST = new String[] { 159f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn ClipDescription.MIMETYPE_TEXT_URILIST }; 160f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn static final String[] MIMETYPES_TEXT_INTENT = new String[] { 161f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn ClipDescription.MIMETYPE_TEXT_INTENT }; 162f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn 163f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn final ClipDescription mClipDescription; 1647e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev 1651040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn final Bitmap mIcon; 1669f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 16721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn final ArrayList<Item> mItems; 1689f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 16923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 1707e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev * Description of a single item in a ClipData. 17123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 17223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>The types than an individual item can currently contain are:</p> 17323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 17423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <ul> 17523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <li> Text: a basic string of text. This is actually a CharSequence, 17623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * so it can be formatted text supported by corresponding Android built-in 17723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * style spans. (Custom application spans are not supported and will be 17823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * stripped when transporting through the clipboard.) 17923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <li> Intent: an arbitrary Intent object. A typical use is the shortcut 18023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * to create when pasting a clipped item on to the home screen. 18123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <li> Uri: a URI reference. This may be any URI (such as an http: URI 18223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * representing a bookmark), however it is often a content: URI. Using 18323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * content provider references as clips like this allows an application to 18423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * share complex or large clips through the standard content provider 18523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * facilities. 18623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * </ul> 18723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 1889f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public static class Item { 1891040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn final CharSequence mText; 190acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn final String mHtmlText; 1911040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn final Intent mIntent; 192d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot Uri mUri; 1939f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 19423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 19523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Create an Item consisting of a single block of (possibly styled) text. 19623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 1979f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public Item(CharSequence text) { 1989f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mText = text; 199acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mHtmlText = null; 200acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mIntent = null; 201acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mUri = null; 202acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 203acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 204acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn /** 205acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * Create an Item consisting of a single block of (possibly styled) text, 206acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * with an alternative HTML formatted representation. You <em>must</em> 207acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * supply a plain text representation in addition to HTML text; coercion 208acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * will not be done from HTML formated text into plain text. 209acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn */ 210acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn public Item(CharSequence text, String htmlText) { 211acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mText = text; 212acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mHtmlText = htmlText; 2131040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mIntent = null; 2141040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mUri = null; 2159f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 2169f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 21723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 21823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Create an Item consisting of an arbitrary Intent. 21923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 2209f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public Item(Intent intent) { 2211040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mText = null; 222acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mHtmlText = null; 2239f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mIntent = intent; 2241040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mUri = null; 2259f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 2269f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 22723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 22823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Create an Item consisting of an arbitrary URI. 22923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 2309f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public Item(Uri uri) { 2311040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mText = null; 232acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mHtmlText = null; 2331040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mIntent = null; 2349f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mUri = uri; 2359f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 2369f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 23723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 23823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Create a complex Item, containing multiple representations of 239acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * text, Intent, and/or URI. 24023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 2419f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public Item(CharSequence text, Intent intent, Uri uri) { 2429f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mText = text; 243acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mHtmlText = null; 244acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mIntent = intent; 245acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mUri = uri; 246acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 247acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 248acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn /** 249acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * Create a complex Item, containing multiple representations of 250acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * text, HTML text, Intent, and/or URI. If providing HTML text, you 251acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * <em>must</em> supply a plain text representation as well; coercion 252acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * will not be done from HTML formated text into plain text. 253acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn */ 254acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn public Item(CharSequence text, String htmlText, Intent intent, Uri uri) { 255acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (htmlText != null && text == null) { 256acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn throw new IllegalArgumentException( 257acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn "Plain text must be supplied if HTML text is supplied"); 258acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 259acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mText = text; 260acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mHtmlText = htmlText; 2619f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mIntent = intent; 2629f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mUri = uri; 2639f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 2649f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 26523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 26623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Retrieve the raw text contained in this Item. 26723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 2689f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public CharSequence getText() { 2699f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn return mText; 2709f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 2719f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 27223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 273acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * Retrieve the raw HTML text contained in this Item. 274acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn */ 275acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn public String getHtmlText() { 276acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return mHtmlText; 277acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 278acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 279acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn /** 28023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Retrieve the raw Intent contained in this Item. 28123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 2829f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public Intent getIntent() { 2839f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn return mIntent; 2849f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 2859f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 28623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 28723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Retrieve the raw URI contained in this Item. 28823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 2899f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public Uri getUri() { 2909f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn return mUri; 2919f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 29223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 29323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 29423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Turn this item into text, regardless of the type of data it 29523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * actually contains. 29623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 29723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>The algorithm for deciding what text to return is: 29823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <ul> 29923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <li> If {@link #getText} is non-null, return that. 30023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <li> If {@link #getUri} is non-null, try to retrieve its data 30123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * as a text stream from its content provider. If this succeeds, copy 30223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * the text into a String and return it. If it is not a content: URI or 30323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * the content provider does not supply a text representation, return 30423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * the raw URI as a string. 30523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <li> If {@link #getIntent} is non-null, convert that to an intent: 306acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * URI and return it. 30723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <li> Otherwise, return an empty string. 30823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * </ul> 30923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 31023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param context The caller's Context, from which its ContentResolver 31123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * and other things can be retrieved. 31223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @return Returns the item's textual representation. 31323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 31423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn//BEGIN_INCLUDE(coerceToText) 31523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public CharSequence coerceToText(Context context) { 31623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // If this Item has an explicit textual value, simply return that. 317acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn CharSequence text = getText(); 318acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (text != null) { 319acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return text; 32023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 32123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 32223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // If this Item has a URI value, try using that. 323acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn Uri uri = getUri(); 324acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (uri != null) { 32523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 32623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // First see if the URI can be opened as a plain text stream 32723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // (of any sub-type). If so, this is the best textual 32823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // representation for it. 32923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn FileInputStream stream = null; 33023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn try { 33123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // Ask for a stream of the desired type. 33223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn AssetFileDescriptor descr = context.getContentResolver() 333acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn .openTypedAssetFileDescriptor(uri, "text/*", null); 33423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn stream = descr.createInputStream(); 33523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); 33623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 33723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // Got it... copy the stream into a local string and return it. 33823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn StringBuilder builder = new StringBuilder(128); 33923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn char[] buffer = new char[8192]; 34023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn int len; 34123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn while ((len=reader.read(buffer)) > 0) { 34223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn builder.append(buffer, 0, len); 34323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 34423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return builder.toString(); 34523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 34623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } catch (FileNotFoundException e) { 34723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // Unable to open content URI as text... not really an 34823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // error, just something to ignore. 34923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 35023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } catch (IOException e) { 35123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // Something bad has happened. 3527e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev Log.w("ClipData", "Failure loading text", e); 35323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return e.toString(); 35423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 35523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } finally { 35623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn if (stream != null) { 35723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn try { 35823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn stream.close(); 35923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } catch (IOException e) { 36023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 36123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 36223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 36323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 36423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // If we couldn't open the URI as a stream, then the URI itself 36523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // probably serves fairly well as a textual representation. 366acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return uri.toString(); 36723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 36823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 36923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // Finally, if all we have is an Intent, then we can just turn that 37023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // into text. Not the most user-friendly thing, but it's something. 371acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn Intent intent = getIntent(); 372acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (intent != null) { 373acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return intent.toUri(Intent.URI_INTENT_SCHEME); 37423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 37523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 37623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn // Shouldn't get here, but just in case... 37723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return ""; 37823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 37923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn//END_INCLUDE(coerceToText) 38021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 381acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn /** 382acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * Like {@link #coerceToHtmlText(Context)}, but any text that would 383acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * be returned as HTML formatting will be returned as text with 384acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * style spans. 385acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * @param context The caller's Context, from which its ContentResolver 386acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * and other things can be retrieved. 387acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * @return Returns the item's textual representation. 388acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn */ 389acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn public CharSequence coerceToStyledText(Context context) { 390acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn CharSequence text = getText(); 391acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (text instanceof Spanned) { 392acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return text; 393acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 394acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn String htmlText = getHtmlText(); 395acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (htmlText != null) { 396acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn try { 397acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn CharSequence newText = Html.fromHtml(htmlText); 398acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (newText != null) { 399acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return newText; 400acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 401acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } catch (RuntimeException e) { 402acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // If anything bad happens, we'll fall back on the plain text. 403acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 404acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 405acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 406acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (text != null) { 407acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return text; 408acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 409acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return coerceToHtmlOrStyledText(context, true); 410acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 411acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 412acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn /** 413acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * Turn this item into HTML text, regardless of the type of data it 414acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * actually contains. 415acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * 416acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * <p>The algorithm for deciding what text to return is: 417acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * <ul> 418acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * <li> If {@link #getHtmlText} is non-null, return that. 419acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * <li> If {@link #getText} is non-null, return that, converting to 420acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * valid HTML text. If this text contains style spans, 421acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * {@link Html#toHtml(Spanned) Html.toHtml(Spanned)} is used to 422acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * convert them to HTML formatting. 423acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * <li> If {@link #getUri} is non-null, try to retrieve its data 424acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * as a text stream from its content provider. If the provider can 425acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * supply text/html data, that will be preferred and returned as-is. 426acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * Otherwise, any text/* data will be returned and escaped to HTML. 427acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * If it is not a content: URI or the content provider does not supply 428acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * a text representation, HTML text containing a link to the URI 429acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * will be returned. 430acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * <li> If {@link #getIntent} is non-null, convert that to an intent: 431acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * URI and return as an HTML link. 432acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * <li> Otherwise, return an empty string. 433acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * </ul> 434acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * 435acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * @param context The caller's Context, from which its ContentResolver 436acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * and other things can be retrieved. 437acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * @return Returns the item's representation as HTML text. 438acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn */ 439acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn public String coerceToHtmlText(Context context) { 440acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // If the item has an explicit HTML value, simply return that. 441acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn String htmlText = getHtmlText(); 442acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (htmlText != null) { 443acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return htmlText; 444acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 445acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 446acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // If this Item has a plain text value, return it as HTML. 447acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn CharSequence text = getText(); 448acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (text != null) { 449acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (text instanceof Spanned) { 450acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return Html.toHtml((Spanned)text); 451acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 452acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return Html.escapeHtml(text); 453acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 454acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 455acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn text = coerceToHtmlOrStyledText(context, false); 456acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return text != null ? text.toString() : null; 457acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 458acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 459acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn private CharSequence coerceToHtmlOrStyledText(Context context, boolean styled) { 460acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // If this Item has a URI value, try using that. 461acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (mUri != null) { 462acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 463acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // Check to see what data representations the content 464acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // provider supports. We would like HTML text, but if that 465acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // is not possible we'll live with plan text. 466c14df8e73d093f839c4ea2585eade6ae6690d224Vladislav Kaznacheev String[] types = null; 467c14df8e73d093f839c4ea2585eade6ae6690d224Vladislav Kaznacheev try { 468c14df8e73d093f839c4ea2585eade6ae6690d224Vladislav Kaznacheev types = context.getContentResolver().getStreamTypes(mUri, "text/*"); 469c14df8e73d093f839c4ea2585eade6ae6690d224Vladislav Kaznacheev } catch (SecurityException e) { 470c14df8e73d093f839c4ea2585eade6ae6690d224Vladislav Kaznacheev // No read permission for mUri, assume empty stream types list. 471c14df8e73d093f839c4ea2585eade6ae6690d224Vladislav Kaznacheev } 472acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn boolean hasHtml = false; 473acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn boolean hasText = false; 474acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (types != null) { 475acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn for (String type : types) { 476acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if ("text/html".equals(type)) { 477acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn hasHtml = true; 478acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } else if (type.startsWith("text/")) { 479acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn hasText = true; 480acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 481acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 482acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 483acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 484acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // If the provider can serve data we can use, open and load it. 485acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (hasHtml || hasText) { 486acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn FileInputStream stream = null; 487acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn try { 488acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // Ask for a stream of the desired type. 489acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn AssetFileDescriptor descr = context.getContentResolver() 490acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn .openTypedAssetFileDescriptor(mUri, 491acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn hasHtml ? "text/html" : "text/plain", null); 492acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn stream = descr.createInputStream(); 493acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); 494acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 495acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // Got it... copy the stream into a local string and return it. 496acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn StringBuilder builder = new StringBuilder(128); 497acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn char[] buffer = new char[8192]; 498acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn int len; 499acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn while ((len=reader.read(buffer)) > 0) { 500acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn builder.append(buffer, 0, len); 501acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 502acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn String text = builder.toString(); 503acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (hasHtml) { 504acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (styled) { 505acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // We loaded HTML formatted text and the caller 506acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // want styled text, convert it. 507acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn try { 508acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn CharSequence newText = Html.fromHtml(text); 509acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return newText != null ? newText : text; 510acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } catch (RuntimeException e) { 511acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return text; 512acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 513acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } else { 514acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // We loaded HTML formatted text and that is what 515acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // the caller wants, just return it. 516acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return text.toString(); 517acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 518acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 519acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (styled) { 520acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // We loaded plain text and the caller wants styled 521acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // text, that is all we have so return it. 522acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return text; 523acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } else { 524acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // We loaded plain text and the caller wants HTML 525acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // text, escape it for HTML. 526acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return Html.escapeHtml(text); 527acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 528acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 529acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } catch (FileNotFoundException e) { 530acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // Unable to open content URI as text... not really an 531acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // error, just something to ignore. 532acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 533acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } catch (IOException e) { 534acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // Something bad has happened. 5357e4669c5a6de347fe85b976475e7e749512114faVladislav Kaznacheev Log.w("ClipData", "Failure loading text", e); 536acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return Html.escapeHtml(e.toString()); 537acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 538acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } finally { 539acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (stream != null) { 540acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn try { 541acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn stream.close(); 542acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } catch (IOException e) { 543acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 544acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 545acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 546acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 547acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 548acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // If we couldn't open the URI as a stream, then we can build 549acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // some HTML text with the URI itself. 550acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // probably serves fairly well as a textual representation. 551acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (styled) { 552acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return uriToStyledText(mUri.toString()); 553acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } else { 554acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return uriToHtml(mUri.toString()); 555acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 556acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 557acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 558acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // Finally, if all we have is an Intent, then we can just turn that 559acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // into text. Not the most user-friendly thing, but it's something. 560acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (mIntent != null) { 561acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (styled) { 562acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return uriToStyledText(mIntent.toUri(Intent.URI_INTENT_SCHEME)); 563acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } else { 564acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return uriToHtml(mIntent.toUri(Intent.URI_INTENT_SCHEME)); 565acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 566acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 567acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 568acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn // Shouldn't get here, but just in case... 569acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return ""; 570acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 571acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 572acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn private String uriToHtml(String uri) { 573acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn StringBuilder builder = new StringBuilder(256); 574acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn builder.append("<a href=\""); 575c92db391379cc19738de8bb5008ed619cb049ebeNick Kralevich builder.append(Html.escapeHtml(uri)); 576acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn builder.append("\">"); 577acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn builder.append(Html.escapeHtml(uri)); 578acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn builder.append("</a>"); 579acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return builder.toString(); 580acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 581acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 582acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn private CharSequence uriToStyledText(String uri) { 583acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn SpannableStringBuilder builder = new SpannableStringBuilder(); 584acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn builder.append(uri); 585acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn builder.setSpan(new URLSpan(uri), 0, builder.length(), 586acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 587acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return builder; 588acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 589acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 59021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn @Override 59121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn public String toString() { 59221c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn StringBuilder b = new StringBuilder(128); 59321c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 59421c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append("ClipData.Item { "); 59521c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn toShortString(b); 59621c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append(" }"); 59721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 59821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn return b.toString(); 59921c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 60021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 60121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn /** @hide */ 60221c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn public void toShortString(StringBuilder b) { 603acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn if (mHtmlText != null) { 604acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn b.append("H:"); 605acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn b.append(mHtmlText); 606acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } else if (mText != null) { 60721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append("T:"); 60821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append(mText); 60921c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } else if (mUri != null) { 61021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append("U:"); 61121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append(mUri); 61221c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } else if (mIntent != null) { 61321c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append("I:"); 61421c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn mIntent.toShortString(b, true, true, true, true); 61521c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } else { 61621c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append("NULL"); 61721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 61821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 619ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn 620ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn /** @hide */ 621ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn public void toShortSummaryString(StringBuilder b) { 622ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn if (mHtmlText != null) { 623ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn b.append("HTML"); 624ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } else if (mText != null) { 625ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn b.append("TEXT"); 626ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } else if (mUri != null) { 627ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn b.append("U:"); 628ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn b.append(mUri); 629ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } else if (mIntent != null) { 630ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn b.append("I:"); 631ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn mIntent.toShortString(b, true, true, true, true); 632ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } else { 633ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn b.append("NULL"); 634ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } 635ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } 6369f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 6379f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 6389f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn /** 6399f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * Create a new clip. 6409f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * 6419f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * @param label Label to show to the user describing this clip. 6421040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param mimeTypes An array of MIME types this data is available as. 6439f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn * @param item The contents of the first item in the clip. 6449f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn */ 645327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn public ClipData(CharSequence label, String[] mimeTypes, Item item) { 646f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn mClipDescription = new ClipDescription(label, mimeTypes); 647f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn if (item == null) { 648f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn throw new NullPointerException("item is null"); 649f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn } 650327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn mIcon = null; 65121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn mItems = new ArrayList<Item>(); 652f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn mItems.add(item); 653f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn } 654f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn 655f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn /** 656f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * Create a new clip. 657f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * 658f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * @param description The ClipDescription describing the clip contents. 659f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * @param item The contents of the first item in the clip. 660f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn */ 661327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn public ClipData(ClipDescription description, Item item) { 662f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn mClipDescription = description; 6639f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn if (item == null) { 6649f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn throw new NullPointerException("item is null"); 6659f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 666327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn mIcon = null; 66721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn mItems = new ArrayList<Item>(); 6689f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mItems.add(item); 6699f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 6709f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 6711040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn /** 67221c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn * Create a new clip that is a copy of another clip. This does a deep-copy 67321c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn * of all items in the clip. 67421c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn * 67521c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn * @param other The existing ClipData that is to be copied. 67621c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn */ 67721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn public ClipData(ClipData other) { 67821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn mClipDescription = other.mClipDescription; 67921c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn mIcon = other.mIcon; 68021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn mItems = new ArrayList<Item>(other.mItems); 68121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 68221c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 68321c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn /** 684f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * Create a new ClipData holding data of the type 685f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * {@link ClipDescription#MIMETYPE_TEXT_PLAIN}. 6861040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * 6871040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param label User-visible label for the clip data. 6881040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param text The actual text in the clip. 6891040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @return Returns a new ClipData containing the specified data. 6901040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn */ 691327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn static public ClipData newPlainText(CharSequence label, CharSequence text) { 6921040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn Item item = new Item(text); 693327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn return new ClipData(label, MIMETYPES_TEXT_PLAIN, item); 694327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn } 695327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn 6961040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn /** 697acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * Create a new ClipData holding data of the type 698acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * {@link ClipDescription#MIMETYPE_TEXT_HTML}. 699acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * 700acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * @param label User-visible label for the clip data. 701acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * @param text The text of clip as plain text, for receivers that don't 702acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * handle HTML. This is required. 703acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * @param htmlText The actual HTML text in the clip. 704acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn * @return Returns a new ClipData containing the specified data. 705acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn */ 706acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn static public ClipData newHtmlText(CharSequence label, CharSequence text, 707acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn String htmlText) { 708acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn Item item = new Item(text, htmlText); 709acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn return new ClipData(label, MIMETYPES_TEXT_HTML, item); 710acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn } 711acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn 712acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn /** 713f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * Create a new ClipData holding an Intent with MIME type 714f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * {@link ClipDescription#MIMETYPE_TEXT_INTENT}. 7151040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * 7161040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param label User-visible label for the clip data. 7171040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param intent The actual Intent in the clip. 7181040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @return Returns a new ClipData containing the specified data. 7191040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn */ 720327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn static public ClipData newIntent(CharSequence label, Intent intent) { 7211040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn Item item = new Item(intent); 722327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn return new ClipData(label, MIMETYPES_TEXT_INTENT, item); 7231040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn } 7241040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn 7251040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn /** 7261040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * Create a new ClipData holding a URI. If the URI is a content: URI, 7271040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * this will query the content provider for the MIME type of its data and 7281040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * use that as the MIME type. Otherwise, it will use the MIME type 729f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * {@link ClipDescription#MIMETYPE_TEXT_URILIST}. 7301040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * 7311040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param resolver ContentResolver used to get information about the URI. 7321040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param label User-visible label for the clip data. 7331040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param uri The URI in the clip. 7341040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @return Returns a new ClipData containing the specified data. 7351040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn */ 7361040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn static public ClipData newUri(ContentResolver resolver, CharSequence label, 737327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn Uri uri) { 7381040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn Item item = new Item(uri); 7391040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn String[] mimeTypes = null; 7401040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn if ("content".equals(uri.getScheme())) { 7411040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn String realType = resolver.getType(uri); 7421040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mimeTypes = resolver.getStreamTypes(uri, "*/*"); 743f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev if (realType != null) { 744f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev if (mimeTypes == null) { 745f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev mimeTypes = new String[] { realType }; 746f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev } else { 747f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev String[] tmp = new String[mimeTypes.length + 1]; 7481040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn tmp[0] = realType; 749f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev System.arraycopy(mimeTypes, 0, tmp, 1, mimeTypes.length); 750f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev mimeTypes = tmp; 7511040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn } 7521040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn } 7531040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn } 7541040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn if (mimeTypes == null) { 7551040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mimeTypes = MIMETYPES_TEXT_URILIST; 7561040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn } 757327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn return new ClipData(label, mimeTypes, item); 7581040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn } 7591040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn 7601040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn /** 761f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * Create a new ClipData holding an URI with MIME type 762f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * {@link ClipDescription#MIMETYPE_TEXT_URILIST}. 763327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * Unlike {@link #newUri(ContentResolver, CharSequence, Uri)}, nothing 7641040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * is inferred about the URI -- if it is a content: URI holding a bitmap, 7651040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * the reported type will still be uri-list. Use this with care! 7661040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * 7671040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param label User-visible label for the clip data. 7681040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @param uri The URI in the clip. 7691040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @return Returns a new ClipData containing the specified data. 7701040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn */ 771327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn static public ClipData newRawUri(CharSequence label, Uri uri) { 7721040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn Item item = new Item(uri); 773327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn return new ClipData(label, MIMETYPES_TEXT_URILIST, item); 7741040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn } 7751040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn 776f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn /** 777f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * Return the {@link ClipDescription} associated with this data, describing 778f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn * what it contains. 779f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn */ 780f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn public ClipDescription getDescription() { 781f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn return mClipDescription; 782f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn } 783f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev 784327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn /** 785327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * Add a new Item to the overall ClipData container. 786f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev * <p> This method will <em>not</em> update the list of available MIME types in the 787f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev * {@link ClipDescription}. It should be used only when adding items which do not add new 788f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev * MIME types to this clip. If this is not the case, {@link #ClipData(CharSequence, String[], 789f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev * Item)} should be used with a complete list of MIME types. 790f67661cc7a97754ed916f328e0aed3ea8f48bc49Vladislav Kaznacheev * @param item Item to be added. 791327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn */ 7929f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public void addItem(Item item) { 7939f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn if (item == null) { 7949f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn throw new NullPointerException("item is null"); 7959f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 7969f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mItems.add(item); 7979f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 7989f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 799327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn /** @hide */ 8009f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public Bitmap getIcon() { 8019f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn return mIcon; 8029f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 8039f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 804327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn /** 805327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * Return the number of items in the clip data. 806327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn */ 8079f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public int getItemCount() { 8089f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn return mItems.size(); 8099f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 8109f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 811327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn /** 812327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * Return a single item inside of the clip data. The index can range 813327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn * from 0 to {@link #getItemCount()}-1. 814327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn */ 815327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn public Item getItemAt(int index) { 8169f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn return mItems.get(index); 8179f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 8189f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 819a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey /** 820a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey * Prepare this {@link ClipData} to leave an app process. 821a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey * 822a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey * @hide 823a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey */ 824344744b49633a7f8aa0c8e43469bbfcf9d8e2cabJeff Sharkey public void prepareToLeaveProcess(boolean leavingPackage) { 825a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey final int size = mItems.size(); 826a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey for (int i = 0; i < size; i++) { 827a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey final Item item = mItems.get(i); 828a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey if (item.mIntent != null) { 829344744b49633a7f8aa0c8e43469bbfcf9d8e2cabJeff Sharkey item.mIntent.prepareToLeaveProcess(leavingPackage); 830a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey } 831344744b49633a7f8aa0c8e43469bbfcf9d8e2cabJeff Sharkey if (item.mUri != null && StrictMode.vmFileUriExposureEnabled() && leavingPackage) { 832a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey item.mUri.checkFileUriExposed("ClipData.Item.getUri()"); 833a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey } 834d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey } 835d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey } 836d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey 837d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey /** {@hide} */ 838d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey public void prepareToEnterProcess() { 839d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey final int size = mItems.size(); 840d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey for (int i = 0; i < size; i++) { 841d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey final Item item = mItems.get(i); 842d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey if (item.mIntent != null) { 843d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey item.mIntent.prepareToEnterProcess(); 844d136e51a99df5275eaafdde407e89e78c02b829bJeff Sharkey } 845a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey } 846a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey } 847a14acd20b8d563319ea1a5974dca0e9a29f0aaefJeff Sharkey 848d1c99b1fe85ed03261a77a14ae52e7fa3a6e523aNicolas Prevot /** @hide */ 849d1c99b1fe85ed03261a77a14ae52e7fa3a6e523aNicolas Prevot public void fixUris(int contentUserHint) { 850d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot final int size = mItems.size(); 851d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot for (int i = 0; i < size; i++) { 852d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot final Item item = mItems.get(i); 853d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot if (item.mIntent != null) { 854d1c99b1fe85ed03261a77a14ae52e7fa3a6e523aNicolas Prevot item.mIntent.fixUris(contentUserHint); 855d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } 856d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot if (item.mUri != null) { 857d1c99b1fe85ed03261a77a14ae52e7fa3a6e523aNicolas Prevot item.mUri = maybeAddUserId(item.mUri, contentUserHint); 858d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } 859d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } 860d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } 861d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot 862f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot /** 863f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot * Only fixing the data field of the intents 864f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot * @hide 865f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot */ 866f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot public void fixUrisLight(int contentUserHint) { 867f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot final int size = mItems.size(); 868f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot for (int i = 0; i < size; i++) { 869f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot final Item item = mItems.get(i); 870f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot if (item.mIntent != null) { 871f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot Uri data = item.mIntent.getData(); 872f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot if (data != null) { 873f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot item.mIntent.setData(maybeAddUserId(data, contentUserHint)); 874f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot } 875f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot } 876f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot if (item.mUri != null) { 877f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot item.mUri = maybeAddUserId(item.mUri, contentUserHint); 878f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot } 879f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot } 880f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot } 881f1939901d2ed0480069f0b23be64f122fce93995Nicolas Prevot 8829f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn @Override 88321c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn public String toString() { 88421c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn StringBuilder b = new StringBuilder(128); 88521c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 88621c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append("ClipData { "); 88721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn toShortString(b); 88821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append(" }"); 88921c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 89021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn return b.toString(); 89121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 89221c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 89321c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn /** @hide */ 89421c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn public void toShortString(StringBuilder b) { 89521c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn boolean first; 89621c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn if (mClipDescription != null) { 89721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn first = !mClipDescription.toShortString(b); 89821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } else { 89921c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn first = true; 90021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 90121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn if (mIcon != null) { 90221c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn if (!first) { 90321c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append(' '); 90421c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 90521c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn first = false; 90621c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append("I:"); 90721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append(mIcon.getWidth()); 90821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append('x'); 90921c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append(mIcon.getHeight()); 91021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 91121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn for (int i=0; i<mItems.size(); i++) { 91221c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn if (!first) { 91321c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append(' '); 91421c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 91521c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn first = false; 91621c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append('{'); 91721c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn mItems.get(i).toShortString(b); 91821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn b.append('}'); 91921c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 92021c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn } 92121c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn 922ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn /** @hide */ 923ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn public void toShortStringShortItems(StringBuilder b, boolean first) { 924ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn if (mItems.size() > 0) { 925ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn if (!first) { 926ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn b.append(' '); 927ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } 928ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn mItems.get(0).toShortString(b); 929ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn if (mItems.size() > 1) { 930ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn b.append(" ..."); 931ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } 932ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } 933ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn } 934ae498721001c6cdcdb6cce1b2f3ba5abbce36f8aDianne Hackborn 9359149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev /** @hide */ 9369149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev public void collectUris(List<Uri> out) { 9379149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev for (int i = 0; i < mItems.size(); ++i) { 9389149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev ClipData.Item item = getItemAt(i); 9399149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev 9409149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev if (item.getUri() != null) { 9419149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev out.add(item.getUri()); 9429149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev } 9439149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev 9449149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev Intent intent = item.getIntent(); 9459149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev if (intent != null) { 9469149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev if (intent.getData() != null) { 9479149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev out.add(intent.getData()); 9489149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev } 9499149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev if (intent.getClipData() != null) { 9509149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev intent.getClipData().collectUris(out); 9519149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev } 9529149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev } 9539149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev } 9549149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev } 9559149d2b117aef40f38a7d62c0f8c2bb76eb4e244Vladislav Kaznacheev 95621c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn @Override 9579f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public int describeContents() { 9589f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn return 0; 9599f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 9609f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 9619f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn @Override 9629f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn public void writeToParcel(Parcel dest, int flags) { 963f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn mClipDescription.writeToParcel(dest, flags); 9649f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn if (mIcon != null) { 9659f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn dest.writeInt(1); 9669f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mIcon.writeToParcel(dest, flags); 9679f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } else { 9689f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn dest.writeInt(0); 9699f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 9709f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn final int N = mItems.size(); 9719f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn dest.writeInt(N); 9729f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn for (int i=0; i<N; i++) { 9739f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn Item item = mItems.get(i); 9749f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn TextUtils.writeToParcel(item.mText, dest, flags); 975acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn dest.writeString(item.mHtmlText); 9769f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn if (item.mIntent != null) { 9779f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn dest.writeInt(1); 9789f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn item.mIntent.writeToParcel(dest, flags); 9799f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } else { 9809f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn dest.writeInt(0); 9819f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 9829f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn if (item.mUri != null) { 9839f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn dest.writeInt(1); 9849f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn item.mUri.writeToParcel(dest, flags); 9859f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } else { 9869f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn dest.writeInt(0); 9879f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 9889f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 9899f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 9909f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 9911040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn ClipData(Parcel in) { 992f834dfabbcbbe1f209682f18c67f2e8b9d3e1dd7Dianne Hackborn mClipDescription = new ClipDescription(in); 9939f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn if (in.readInt() != 0) { 9949f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn mIcon = Bitmap.CREATOR.createFromParcel(in); 9951040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn } else { 9961040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn mIcon = null; 9979f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 99821c241e061de29a538008ca42df9c878184bcfb8Dianne Hackborn mItems = new ArrayList<Item>(); 9999f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn final int N = in.readInt(); 10009f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn for (int i=0; i<N; i++) { 10019f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn CharSequence text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 1002acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn String htmlText = in.readString(); 10039f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn Intent intent = in.readInt() != 0 ? Intent.CREATOR.createFromParcel(in) : null; 10049f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn Uri uri = in.readInt() != 0 ? Uri.CREATOR.createFromParcel(in) : null; 1005acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn mItems.add(new Item(text, htmlText, intent, uri)); 10069f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 10079f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 10089f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 10091040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn public static final Parcelable.Creator<ClipData> CREATOR = 10101040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn new Parcelable.Creator<ClipData>() { 10119f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 10121040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn public ClipData createFromParcel(Parcel source) { 10131040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn return new ClipData(source); 10149f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 10159f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn 10161040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn public ClipData[] newArray(int size) { 10171040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn return new ClipData[size]; 10189f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn } 10199f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn }; 10209f53119b72e6da865bcd53173d3dacd1eba01aeeDianne Hackborn} 1021