• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
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 
17 package android.content;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 import android.os.PersistableBundle;
22 import android.text.TextUtils;
23 import android.util.TimeUtils;
24 
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 
28 /**
29  * Meta-data describing the contents of a {@link ClipData}.  Provides enough
30  * information to know if you can handle the ClipData, but not the data
31  * itself.
32  *
33  * <div class="special reference">
34  * <h3>Developer Guides</h3>
35  * <p>For more information about using the clipboard framework, read the
36  * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a>
37  * developer guide.</p>
38  * </div>
39  */
40 public class ClipDescription implements Parcelable {
41     /**
42      * The MIME type for a clip holding plain text.
43      */
44     public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
45 
46     /**
47      * The MIME type for a clip holding HTML text.
48      */
49     public static final String MIMETYPE_TEXT_HTML = "text/html";
50 
51     /**
52      * The MIME type for a clip holding one or more URIs.  This should be
53      * used for URIs that are meaningful to a user (such as an http: URI).
54      * It should <em>not</em> be used for a content: URI that references some
55      * other piece of data; in that case the MIME type should be the type
56      * of the referenced data.
57      */
58     public static final String MIMETYPE_TEXT_URILIST = "text/uri-list";
59 
60     /**
61      * The MIME type for a clip holding an Intent.
62      */
63     public static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
64 
65     /**
66      * The name of the extra used to define a component name when copying/dragging
67      * an app icon from Launcher.
68      * <p>
69      * Type: String
70      * </p>
71      * <p>
72      * Use {@link ComponentName#unflattenFromString(String)}
73      * and {@link ComponentName#flattenToString()} to convert the extra value
74      * to/from {@link ComponentName}.
75      * </p>
76      * @hide
77      */
78     public static final String EXTRA_TARGET_COMPONENT_NAME =
79             "android.content.extra.TARGET_COMPONENT_NAME";
80 
81     /**
82      * The name of the extra used to define a user serial number when copying/dragging
83      * an app icon from Launcher.
84      * <p>
85      * Type: long
86      * </p>
87      * @hide
88      */
89     public static final String EXTRA_USER_SERIAL_NUMBER =
90             "android.content.extra.USER_SERIAL_NUMBER";
91 
92 
93     final CharSequence mLabel;
94     private final ArrayList<String> mMimeTypes;
95     private PersistableBundle mExtras;
96     private long mTimeStamp;
97 
98     /**
99      * Create a new clip.
100      *
101      * @param label Label to show to the user describing this clip.
102      * @param mimeTypes An array of MIME types this data is available as.
103      */
ClipDescription(CharSequence label, String[] mimeTypes)104     public ClipDescription(CharSequence label, String[] mimeTypes) {
105         if (mimeTypes == null) {
106             throw new NullPointerException("mimeTypes is null");
107         }
108         mLabel = label;
109         mMimeTypes = new ArrayList<String>(Arrays.asList(mimeTypes));
110     }
111 
112     /**
113      * Create a copy of a ClipDescription.
114      */
ClipDescription(ClipDescription o)115     public ClipDescription(ClipDescription o) {
116         mLabel = o.mLabel;
117         mMimeTypes = new ArrayList<String>(o.mMimeTypes);
118         mTimeStamp = o.mTimeStamp;
119     }
120 
121     /**
122      * Helper to compare two MIME types, where one may be a pattern.
123      * @param concreteType A fully-specified MIME type.
124      * @param desiredType A desired MIME type that may be a pattern such as *&#47;*.
125      * @return Returns true if the two MIME types match.
126      */
compareMimeTypes(String concreteType, String desiredType)127     public static boolean compareMimeTypes(String concreteType, String desiredType) {
128         final int typeLength = desiredType.length();
129         if (typeLength == 3 && desiredType.equals("*/*")) {
130             return true;
131         }
132 
133         final int slashpos = desiredType.indexOf('/');
134         if (slashpos > 0) {
135             if (typeLength == slashpos+2 && desiredType.charAt(slashpos+1) == '*') {
136                 if (desiredType.regionMatches(0, concreteType, 0, slashpos+1)) {
137                     return true;
138                 }
139             } else if (desiredType.equals(concreteType)) {
140                 return true;
141             }
142         }
143 
144         return false;
145     }
146 
147     /**
148      * Used for setting the timestamp at which the associated {@link ClipData} is copied to
149      * global clipboard.
150      *
151      * @param timeStamp at which the associated {@link ClipData} is copied to clipboard in
152      *                  {@link System#currentTimeMillis()} time base.
153      * @hide
154      */
setTimestamp(long timeStamp)155     public void setTimestamp(long timeStamp) {
156         mTimeStamp = timeStamp;
157     }
158 
159     /**
160      * Return the timestamp at which the associated {@link ClipData} is copied to global clipboard
161      * in the {@link System#currentTimeMillis()} time base.
162      *
163      * @return timestamp at which the associated {@link ClipData} is copied to global clipboard
164      *         or {@code 0} if it is not copied to clipboard.
165      */
getTimestamp()166     public long getTimestamp() {
167         return mTimeStamp;
168     }
169 
170     /**
171      * Return the label for this clip.
172      */
getLabel()173     public CharSequence getLabel() {
174         return mLabel;
175     }
176 
177     /**
178      * Check whether the clip description contains the given MIME type.
179      *
180      * @param mimeType The desired MIME type.  May be a pattern.
181      * @return Returns true if one of the MIME types in the clip description
182      * matches the desired MIME type, else false.
183      */
hasMimeType(String mimeType)184     public boolean hasMimeType(String mimeType) {
185         final int size = mMimeTypes.size();
186         for (int i=0; i<size; i++) {
187             if (compareMimeTypes(mMimeTypes.get(i), mimeType)) {
188                 return true;
189             }
190         }
191         return false;
192     }
193 
194     /**
195      * Filter the clip description MIME types by the given MIME type.  Returns
196      * all MIME types in the clip that match the given MIME type.
197      *
198      * @param mimeType The desired MIME type.  May be a pattern.
199      * @return Returns an array of all matching MIME types.  If there are no
200      * matching MIME types, null is returned.
201      */
filterMimeTypes(String mimeType)202     public String[] filterMimeTypes(String mimeType) {
203         ArrayList<String> array = null;
204         final int size = mMimeTypes.size();
205         for (int i=0; i<size; i++) {
206             if (compareMimeTypes(mMimeTypes.get(i), mimeType)) {
207                 if (array == null) {
208                     array = new ArrayList<String>();
209                 }
210                 array.add(mMimeTypes.get(i));
211             }
212         }
213         if (array == null) {
214             return null;
215         }
216         String[] rawArray = new String[array.size()];
217         array.toArray(rawArray);
218         return rawArray;
219     }
220 
221     /**
222      * Return the number of MIME types the clip is available in.
223      */
getMimeTypeCount()224     public int getMimeTypeCount() {
225         return mMimeTypes.size();
226     }
227 
228     /**
229      * Return one of the possible clip MIME types.
230      */
getMimeType(int index)231     public String getMimeType(int index) {
232         return mMimeTypes.get(index);
233     }
234 
235     /**
236      * Add MIME types to the clip description.
237      */
addMimeTypes(String[] mimeTypes)238     void addMimeTypes(String[] mimeTypes) {
239         for (int i=0; i!=mimeTypes.length; i++) {
240             final String mimeType = mimeTypes[i];
241             if (!mMimeTypes.contains(mimeType)) {
242                 mMimeTypes.add(mimeType);
243             }
244         }
245     }
246 
247     /**
248      * Retrieve extended data from the clip description.
249      *
250      * @return the bundle containing extended data previously set with
251      * {@link #setExtras(PersistableBundle)}, or null if no extras have been set.
252      *
253      * @see #setExtras(PersistableBundle)
254      */
getExtras()255     public PersistableBundle getExtras() {
256         return mExtras;
257     }
258 
259     /**
260      * Add extended data to the clip description.
261      *
262      * @see #getExtras()
263      */
setExtras(PersistableBundle extras)264     public void setExtras(PersistableBundle extras) {
265         mExtras = new PersistableBundle(extras);
266     }
267 
268     /** @hide */
validate()269     public void validate() {
270         if (mMimeTypes == null) {
271             throw new NullPointerException("null mime types");
272         }
273         final int size = mMimeTypes.size();
274         if (size <= 0) {
275             throw new IllegalArgumentException("must have at least 1 mime type");
276         }
277         for (int i=0; i<size; i++) {
278             if (mMimeTypes.get(i) == null) {
279                 throw new NullPointerException("mime type at " + i + " is null");
280             }
281         }
282     }
283 
284     @Override
toString()285     public String toString() {
286         StringBuilder b = new StringBuilder(128);
287 
288         b.append("ClipDescription { ");
289         toShortString(b);
290         b.append(" }");
291 
292         return b.toString();
293     }
294 
295     /** @hide */
toShortString(StringBuilder b)296     public boolean toShortString(StringBuilder b) {
297         boolean first = !toShortStringTypesOnly(b);
298         if (mLabel != null) {
299             if (!first) {
300                 b.append(' ');
301             }
302             first = false;
303             b.append('"');
304             b.append(mLabel);
305             b.append('"');
306         }
307         if (mExtras != null) {
308             if (!first) {
309                 b.append(' ');
310             }
311             first = false;
312             b.append(mExtras.toString());
313         }
314         if (mTimeStamp > 0) {
315             if (!first) {
316                 b.append(' ');
317             }
318             first = false;
319             b.append('<');
320             b.append(TimeUtils.logTimeOfDay(mTimeStamp));
321             b.append('>');
322         }
323         return !first;
324     }
325 
326     /** @hide */
toShortStringTypesOnly(StringBuilder b)327     public boolean toShortStringTypesOnly(StringBuilder b) {
328         boolean first = true;
329         final int size = mMimeTypes.size();
330         for (int i=0; i<size; i++) {
331             if (!first) {
332                 b.append(' ');
333             }
334             first = false;
335             b.append(mMimeTypes.get(i));
336         }
337         return !first;
338     }
339 
340     @Override
describeContents()341     public int describeContents() {
342         return 0;
343     }
344 
345     @Override
writeToParcel(Parcel dest, int flags)346     public void writeToParcel(Parcel dest, int flags) {
347         TextUtils.writeToParcel(mLabel, dest, flags);
348         dest.writeStringList(mMimeTypes);
349         dest.writePersistableBundle(mExtras);
350         dest.writeLong(mTimeStamp);
351     }
352 
ClipDescription(Parcel in)353     ClipDescription(Parcel in) {
354         mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
355         mMimeTypes = in.createStringArrayList();
356         mExtras = in.readPersistableBundle();
357         mTimeStamp = in.readLong();
358     }
359 
360     public static final Parcelable.Creator<ClipDescription> CREATOR =
361         new Parcelable.Creator<ClipDescription>() {
362 
363             public ClipDescription createFromParcel(Parcel source) {
364                 return new ClipDescription(source);
365             }
366 
367             public ClipDescription[] newArray(int size) {
368                 return new ClipDescription[size];
369             }
370         };
371 }
372