blob: 461d1e04e52460d199cc4d8a1119610896ec9164 [file] [log] [blame]
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001/**
2 * Copyright (c) 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content;
18
19import android.os.Parcel;
20import android.os.Parcelable;
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -080021import android.os.PersistableBundle;
Dianne Hackborn1040dc42010-08-26 22:11:06 -070022import android.text.TextUtils;
23
24import java.util.ArrayList;
25
26/**
Dianne Hackbornf6d952b2010-08-27 15:41:13 -070027 * Meta-data describing the contents of a {@link ClipData}. Provides enough
Dianne Hackborn1040dc42010-08-26 22:11:06 -070028 * information to know if you can handle the ClipData, but not the data
29 * itself.
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080030 *
31 * <div class="special reference">
32 * <h3>Developer Guides</h3>
33 * <p>For more information about using the clipboard framework, read the
34 * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a>
35 * developer guide.</p>
36 * </div>
Dianne Hackborn1040dc42010-08-26 22:11:06 -070037 */
38public class ClipDescription implements Parcelable {
39 /**
40 * The MIME type for a clip holding plain text.
41 */
42 public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
43
44 /**
Dianne Hackbornacb69bb2012-04-13 15:36:06 -070045 * The MIME type for a clip holding HTML text.
46 */
47 public static final String MIMETYPE_TEXT_HTML = "text/html";
48
49 /**
Dianne Hackborn1040dc42010-08-26 22:11:06 -070050 * The MIME type for a clip holding one or more URIs. This should be
51 * used for URIs that are meaningful to a user (such as an http: URI).
52 * It should <em>not</em> be used for a content: URI that references some
53 * other piece of data; in that case the MIME type should be the type
54 * of the referenced data.
55 */
56 public static final String MIMETYPE_TEXT_URILIST = "text/uri-list";
57
58 /**
59 * The MIME type for a clip holding an Intent.
60 */
61 public static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
62
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -080063 /**
64 * The name of the extra used to define a component name when copying/dragging
65 * an app icon from Launcher.
66 * <p>
67 * Type: String
68 * </p>
69 * <p>
70 * Use {@link ComponentName#unflattenFromString(String)}
71 * and {@link ComponentName#flattenToString()} to convert the extra value
72 * to/from {@link ComponentName}.
73 * </p>
Vladislav Kaznacheev5d196672016-04-05 17:12:25 -070074 * @hide
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -080075 */
76 public static final String EXTRA_TARGET_COMPONENT_NAME =
77 "android.content.extra.TARGET_COMPONENT_NAME";
78
79 /**
80 * The name of the extra used to define a user serial number when copying/dragging
81 * an app icon from Launcher.
82 * <p>
83 * Type: long
84 * </p>
Vladislav Kaznacheev5d196672016-04-05 17:12:25 -070085 * @hide
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -080086 */
87 public static final String EXTRA_USER_SERIAL_NUMBER =
88 "android.content.extra.USER_SERIAL_NUMBER";
89
90
Dianne Hackborn1040dc42010-08-26 22:11:06 -070091 final CharSequence mLabel;
92 final String[] mMimeTypes;
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -080093 private PersistableBundle mExtras;
Dianne Hackborn1040dc42010-08-26 22:11:06 -070094
95 /**
96 * Create a new clip.
97 *
98 * @param label Label to show to the user describing this clip.
99 * @param mimeTypes An array of MIME types this data is available as.
100 */
101 public ClipDescription(CharSequence label, String[] mimeTypes) {
102 if (mimeTypes == null) {
103 throw new NullPointerException("mimeTypes is null");
104 }
105 mLabel = label;
106 mMimeTypes = mimeTypes;
107 }
108
109 /**
110 * Create a copy of a ClipDescription.
111 */
112 public ClipDescription(ClipDescription o) {
113 mLabel = o.mLabel;
114 mMimeTypes = o.mMimeTypes;
115 }
116
117 /**
118 * Helper to compare two MIME types, where one may be a pattern.
119 * @param concreteType A fully-specified MIME type.
John Spurlock33900182014-01-02 11:04:18 -0500120 * @param desiredType A desired MIME type that may be a pattern such as *&#47;*.
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700121 * @return Returns true if the two MIME types match.
122 */
123 public static boolean compareMimeTypes(String concreteType, String desiredType) {
124 final int typeLength = desiredType.length();
125 if (typeLength == 3 && desiredType.equals("*/*")) {
126 return true;
127 }
128
129 final int slashpos = desiredType.indexOf('/');
130 if (slashpos > 0) {
131 if (typeLength == slashpos+2 && desiredType.charAt(slashpos+1) == '*') {
132 if (desiredType.regionMatches(0, concreteType, 0, slashpos+1)) {
133 return true;
134 }
135 } else if (desiredType.equals(concreteType)) {
136 return true;
137 }
138 }
139
140 return false;
141 }
142
143 /**
144 * Return the label for this clip.
145 */
146 public CharSequence getLabel() {
147 return mLabel;
148 }
149
150 /**
151 * Check whether the clip description contains the given MIME type.
152 *
153 * @param mimeType The desired MIME type. May be a pattern.
154 * @return Returns true if one of the MIME types in the clip description
155 * matches the desired MIME type, else false.
156 */
157 public boolean hasMimeType(String mimeType) {
158 for (int i=0; i<mMimeTypes.length; i++) {
159 if (compareMimeTypes(mMimeTypes[i], mimeType)) {
160 return true;
161 }
162 }
163 return false;
164 }
165
166 /**
167 * Filter the clip description MIME types by the given MIME type. Returns
168 * all MIME types in the clip that match the given MIME type.
169 *
170 * @param mimeType The desired MIME type. May be a pattern.
171 * @return Returns an array of all matching MIME types. If there are no
172 * matching MIME types, null is returned.
173 */
174 public String[] filterMimeTypes(String mimeType) {
175 ArrayList<String> array = null;
176 for (int i=0; i<mMimeTypes.length; i++) {
177 if (compareMimeTypes(mMimeTypes[i], mimeType)) {
178 if (array == null) {
179 array = new ArrayList<String>();
180 }
181 array.add(mMimeTypes[i]);
182 }
183 }
184 if (array == null) {
185 return null;
186 }
187 String[] rawArray = new String[array.size()];
188 array.toArray(rawArray);
189 return rawArray;
190 }
191
192 /**
193 * Return the number of MIME types the clip is available in.
194 */
195 public int getMimeTypeCount() {
196 return mMimeTypes.length;
197 }
198
199 /**
200 * Return one of the possible clip MIME types.
201 */
202 public String getMimeType(int index) {
203 return mMimeTypes[index];
204 }
205
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -0800206 /**
207 * Retrieve extended data from the clip description.
208 *
209 * @return the bundle containing extended data previously set with
210 * {@link #setExtras(PersistableBundle)}, or null if no extras have been set.
211 *
212 * @see #setExtras(PersistableBundle)
213 */
214 public PersistableBundle getExtras() {
215 return mExtras;
216 }
217
218 /**
219 * Add extended data to the clip description.
220 *
221 * @see #getExtras()
222 */
223 public void setExtras(PersistableBundle extras) {
224 mExtras = new PersistableBundle(extras);
225 }
226
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700227 /** @hide */
228 public void validate() {
229 if (mMimeTypes == null) {
230 throw new NullPointerException("null mime types");
231 }
232 if (mMimeTypes.length <= 0) {
233 throw new IllegalArgumentException("must have at least 1 mime type");
234 }
235 for (int i=0; i<mMimeTypes.length; i++) {
236 if (mMimeTypes[i] == null) {
237 throw new NullPointerException("mime type at " + i + " is null");
238 }
239 }
240 }
241
242 @Override
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800243 public String toString() {
244 StringBuilder b = new StringBuilder(128);
245
246 b.append("ClipDescription { ");
247 toShortString(b);
248 b.append(" }");
249
250 return b.toString();
251 }
252
253 /** @hide */
254 public boolean toShortString(StringBuilder b) {
Dianne Hackbornae498722015-08-14 13:29:47 -0700255 boolean first = !toShortStringTypesOnly(b);
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800256 if (mLabel != null) {
257 if (!first) {
258 b.append(' ');
259 }
260 first = false;
261 b.append('"');
262 b.append(mLabel);
263 b.append('"');
264 }
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -0800265 if (mExtras != null) {
266 if (!first) {
267 b.append(' ');
268 }
269 first = false;
270 b.append(mExtras.toString());
271 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800272 return !first;
273 }
274
Dianne Hackbornae498722015-08-14 13:29:47 -0700275 /** @hide */
276 public boolean toShortStringTypesOnly(StringBuilder b) {
277 boolean first = true;
278 for (int i=0; i<mMimeTypes.length; i++) {
279 if (!first) {
280 b.append(' ');
281 }
282 first = false;
283 b.append(mMimeTypes[i]);
284 }
285 return !first;
286 }
287
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800288 @Override
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700289 public int describeContents() {
290 return 0;
291 }
292
293 @Override
294 public void writeToParcel(Parcel dest, int flags) {
295 TextUtils.writeToParcel(mLabel, dest, flags);
296 dest.writeStringArray(mMimeTypes);
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -0800297 dest.writePersistableBundle(mExtras);
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700298 }
299
300 ClipDescription(Parcel in) {
301 mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
302 mMimeTypes = in.createStringArray();
Vladislav Kaznacheevddb4bde2015-11-24 11:24:12 -0800303 mExtras = in.readPersistableBundle();
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700304 }
305
306 public static final Parcelable.Creator<ClipDescription> CREATOR =
307 new Parcelable.Creator<ClipDescription>() {
308
309 public ClipDescription createFromParcel(Parcel source) {
310 return new ClipDescription(source);
311 }
312
313 public ClipDescription[] newArray(int size) {
314 return new ClipDescription[size];
315 }
316 };
317}