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.text.TextUtils; 22 23 import java.util.ArrayList; 24 25 /** 26 * Meta-data describing the contents of a {@link ClipData}. Provides enough 27 * information to know if you can handle the ClipData, but not the data 28 * itself. 29 * 30 * <div class="special reference"> 31 * <h3>Developer Guides</h3> 32 * <p>For more information about using the clipboard framework, read the 33 * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a> 34 * developer guide.</p> 35 * </div> 36 */ 37 public class ClipDescription implements Parcelable { 38 /** 39 * The MIME type for a clip holding plain text. 40 */ 41 public static final String MIMETYPE_TEXT_PLAIN = "text/plain"; 42 43 /** 44 * The MIME type for a clip holding HTML text. 45 */ 46 public static final String MIMETYPE_TEXT_HTML = "text/html"; 47 48 /** 49 * The MIME type for a clip holding one or more URIs. This should be 50 * used for URIs that are meaningful to a user (such as an http: URI). 51 * It should <em>not</em> be used for a content: URI that references some 52 * other piece of data; in that case the MIME type should be the type 53 * of the referenced data. 54 */ 55 public static final String MIMETYPE_TEXT_URILIST = "text/uri-list"; 56 57 /** 58 * The MIME type for a clip holding an Intent. 59 */ 60 public static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent"; 61 62 final CharSequence mLabel; 63 final String[] mMimeTypes; 64 65 /** 66 * Create a new clip. 67 * 68 * @param label Label to show to the user describing this clip. 69 * @param mimeTypes An array of MIME types this data is available as. 70 */ ClipDescription(CharSequence label, String[] mimeTypes)71 public ClipDescription(CharSequence label, String[] mimeTypes) { 72 if (mimeTypes == null) { 73 throw new NullPointerException("mimeTypes is null"); 74 } 75 mLabel = label; 76 mMimeTypes = mimeTypes; 77 } 78 79 /** 80 * Create a copy of a ClipDescription. 81 */ ClipDescription(ClipDescription o)82 public ClipDescription(ClipDescription o) { 83 mLabel = o.mLabel; 84 mMimeTypes = o.mMimeTypes; 85 } 86 87 /** 88 * Helper to compare two MIME types, where one may be a pattern. 89 * @param concreteType A fully-specified MIME type. 90 * @param desiredType A desired MIME type that may be a pattern such as *\/*. 91 * @return Returns true if the two MIME types match. 92 */ compareMimeTypes(String concreteType, String desiredType)93 public static boolean compareMimeTypes(String concreteType, String desiredType) { 94 final int typeLength = desiredType.length(); 95 if (typeLength == 3 && desiredType.equals("*/*")) { 96 return true; 97 } 98 99 final int slashpos = desiredType.indexOf('/'); 100 if (slashpos > 0) { 101 if (typeLength == slashpos+2 && desiredType.charAt(slashpos+1) == '*') { 102 if (desiredType.regionMatches(0, concreteType, 0, slashpos+1)) { 103 return true; 104 } 105 } else if (desiredType.equals(concreteType)) { 106 return true; 107 } 108 } 109 110 return false; 111 } 112 113 /** 114 * Return the label for this clip. 115 */ getLabel()116 public CharSequence getLabel() { 117 return mLabel; 118 } 119 120 /** 121 * Check whether the clip description contains the given MIME type. 122 * 123 * @param mimeType The desired MIME type. May be a pattern. 124 * @return Returns true if one of the MIME types in the clip description 125 * matches the desired MIME type, else false. 126 */ hasMimeType(String mimeType)127 public boolean hasMimeType(String mimeType) { 128 for (int i=0; i<mMimeTypes.length; i++) { 129 if (compareMimeTypes(mMimeTypes[i], mimeType)) { 130 return true; 131 } 132 } 133 return false; 134 } 135 136 /** 137 * Filter the clip description MIME types by the given MIME type. Returns 138 * all MIME types in the clip that match the given MIME type. 139 * 140 * @param mimeType The desired MIME type. May be a pattern. 141 * @return Returns an array of all matching MIME types. If there are no 142 * matching MIME types, null is returned. 143 */ filterMimeTypes(String mimeType)144 public String[] filterMimeTypes(String mimeType) { 145 ArrayList<String> array = null; 146 for (int i=0; i<mMimeTypes.length; i++) { 147 if (compareMimeTypes(mMimeTypes[i], mimeType)) { 148 if (array == null) { 149 array = new ArrayList<String>(); 150 } 151 array.add(mMimeTypes[i]); 152 } 153 } 154 if (array == null) { 155 return null; 156 } 157 String[] rawArray = new String[array.size()]; 158 array.toArray(rawArray); 159 return rawArray; 160 } 161 162 /** 163 * Return the number of MIME types the clip is available in. 164 */ getMimeTypeCount()165 public int getMimeTypeCount() { 166 return mMimeTypes.length; 167 } 168 169 /** 170 * Return one of the possible clip MIME types. 171 */ getMimeType(int index)172 public String getMimeType(int index) { 173 return mMimeTypes[index]; 174 } 175 176 /** @hide */ validate()177 public void validate() { 178 if (mMimeTypes == null) { 179 throw new NullPointerException("null mime types"); 180 } 181 if (mMimeTypes.length <= 0) { 182 throw new IllegalArgumentException("must have at least 1 mime type"); 183 } 184 for (int i=0; i<mMimeTypes.length; i++) { 185 if (mMimeTypes[i] == null) { 186 throw new NullPointerException("mime type at " + i + " is null"); 187 } 188 } 189 } 190 191 @Override toString()192 public String toString() { 193 StringBuilder b = new StringBuilder(128); 194 195 b.append("ClipDescription { "); 196 toShortString(b); 197 b.append(" }"); 198 199 return b.toString(); 200 } 201 202 /** @hide */ toShortString(StringBuilder b)203 public boolean toShortString(StringBuilder b) { 204 boolean first = true; 205 for (int i=0; i<mMimeTypes.length; i++) { 206 if (!first) { 207 b.append(' '); 208 } 209 first = false; 210 b.append(mMimeTypes[i]); 211 } 212 if (mLabel != null) { 213 if (!first) { 214 b.append(' '); 215 } 216 first = false; 217 b.append('"'); 218 b.append(mLabel); 219 b.append('"'); 220 } 221 return !first; 222 } 223 224 @Override describeContents()225 public int describeContents() { 226 return 0; 227 } 228 229 @Override writeToParcel(Parcel dest, int flags)230 public void writeToParcel(Parcel dest, int flags) { 231 TextUtils.writeToParcel(mLabel, dest, flags); 232 dest.writeStringArray(mMimeTypes); 233 } 234 ClipDescription(Parcel in)235 ClipDescription(Parcel in) { 236 mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 237 mMimeTypes = in.createStringArray(); 238 } 239 240 public static final Parcelable.Creator<ClipDescription> CREATOR = 241 new Parcelable.Creator<ClipDescription>() { 242 243 public ClipDescription createFromParcel(Parcel source) { 244 return new ClipDescription(source); 245 } 246 247 public ClipDescription[] newArray(int size) { 248 return new ClipDescription[size]; 249 } 250 }; 251 } 252