1b9f7aac3488873677377b36c57338d758098f78eDan Sandler/* 2b9f7aac3488873677377b36c57338d758098f78eDan Sandler * Copyright (C) 2015 The Android Open Source Project 3b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 4b9f7aac3488873677377b36c57338d758098f78eDan Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 5b9f7aac3488873677377b36c57338d758098f78eDan Sandler * you may not use this file except in compliance with the License. 6b9f7aac3488873677377b36c57338d758098f78eDan Sandler * You may obtain a copy of the License at 7b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 8b9f7aac3488873677377b36c57338d758098f78eDan Sandler * http://www.apache.org/licenses/LICENSE-2.0 9b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 10b9f7aac3488873677377b36c57338d758098f78eDan Sandler * Unless required by applicable law or agreed to in writing, software 11b9f7aac3488873677377b36c57338d758098f78eDan Sandler * distributed under the License is distributed on an "AS IS" BASIS, 12b9f7aac3488873677377b36c57338d758098f78eDan Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b9f7aac3488873677377b36c57338d758098f78eDan Sandler * See the License for the specific language governing permissions and 14b9f7aac3488873677377b36c57338d758098f78eDan Sandler * limitations under the License. 15b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 16b9f7aac3488873677377b36c57338d758098f78eDan Sandler 17b9f7aac3488873677377b36c57338d758098f78eDan Sandlerpackage android.graphics.drawable; 18b9f7aac3488873677377b36c57338d758098f78eDan Sandler 1924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandlerimport android.annotation.ColorInt; 20b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.annotation.DrawableRes; 2124f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandlerimport android.content.res.ColorStateList; 22b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.content.ContentResolver; 23cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordonimport android.content.Context; 24c7fd3462a2699f73d5f2ba6d863d8be4ddd570a9Julia Reynoldsimport android.content.pm.ApplicationInfo; 25b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.content.pm.PackageManager; 26b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.content.res.Resources; 27b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.graphics.Bitmap; 28b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.graphics.BitmapFactory; 2924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandlerimport android.graphics.PorterDuff; 30b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.net.Uri; 31b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.os.AsyncTask; 32b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.os.Handler; 33b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.os.Message; 34b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.os.Parcel; 35b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.os.Parcelable; 364e78706f439d318ae7a78927d98f734351a89f64Dan Sandlerimport android.text.TextUtils; 37b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport android.util.Log; 38b9f7aac3488873677377b36c57338d758098f78eDan Sandler 39cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordonimport java.io.DataInputStream; 40cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordonimport java.io.DataOutputStream; 41b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport java.io.File; 42b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport java.io.FileInputStream; 43b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport java.io.FileNotFoundException; 44cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordonimport java.io.IOException; 45b9f7aac3488873677377b36c57338d758098f78eDan Sandlerimport java.io.InputStream; 46cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordonimport java.io.OutputStream; 47b9f7aac3488873677377b36c57338d758098f78eDan Sandler 48b9f7aac3488873677377b36c57338d758098f78eDan Sandler/** 49b9f7aac3488873677377b36c57338d758098f78eDan Sandler * An umbrella container for several serializable graphics representations, including Bitmaps, 50b9f7aac3488873677377b36c57338d758098f78eDan Sandler * compressed bitmap images (e.g. JPG or PNG), and drawable resources (including vectors). 51b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 52b9f7aac3488873677377b36c57338d758098f78eDan Sandler * <a href="https://developer.android.com/training/displaying-bitmaps/index.html">Much ink</a> 53b9f7aac3488873677377b36c57338d758098f78eDan Sandler * has been spilled on the best way to load images, and many clients may have different needs when 54b9f7aac3488873677377b36c57338d758098f78eDan Sandler * it comes to threading and fetching. This class is therefore focused on encapsulation rather than 55b9f7aac3488873677377b36c57338d758098f78eDan Sandler * behavior. 56b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 57b9f7aac3488873677377b36c57338d758098f78eDan Sandler 58b9f7aac3488873677377b36c57338d758098f78eDan Sandlerpublic final class Icon implements Parcelable { 59b9f7aac3488873677377b36c57338d758098f78eDan Sandler private static final String TAG = "Icon"; 60b9f7aac3488873677377b36c57338d758098f78eDan Sandler 61d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** @hide */ 62d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public static final int TYPE_BITMAP = 1; 63d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** @hide */ 64d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public static final int TYPE_RESOURCE = 2; 65d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** @hide */ 66d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public static final int TYPE_DATA = 3; 67d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** @hide */ 68d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public static final int TYPE_URI = 4; 69b9f7aac3488873677377b36c57338d758098f78eDan Sandler 70cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon private static final int VERSION_STREAM_SERIALIZER = 1; 71cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon 72b9f7aac3488873677377b36c57338d758098f78eDan Sandler private final int mType; 73b9f7aac3488873677377b36c57338d758098f78eDan Sandler 7424f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler private ColorStateList mTintList; 7524f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler static final PorterDuff.Mode DEFAULT_TINT_MODE = Drawable.DEFAULT_TINT_MODE; // SRC_IN 7624f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler private PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; 7724f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler 78b9f7aac3488873677377b36c57338d758098f78eDan Sandler // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed 79b9f7aac3488873677377b36c57338d758098f78eDan Sandler // based on the value of mType. 80b9f7aac3488873677377b36c57338d758098f78eDan Sandler 81b9f7aac3488873677377b36c57338d758098f78eDan Sandler // TYPE_BITMAP: Bitmap 82b9f7aac3488873677377b36c57338d758098f78eDan Sandler // TYPE_RESOURCE: Resources 83b9f7aac3488873677377b36c57338d758098f78eDan Sandler // TYPE_DATA: DataBytes 84b9f7aac3488873677377b36c57338d758098f78eDan Sandler private Object mObj1; 85b9f7aac3488873677377b36c57338d758098f78eDan Sandler 86b9f7aac3488873677377b36c57338d758098f78eDan Sandler // TYPE_RESOURCE: package name 87b9f7aac3488873677377b36c57338d758098f78eDan Sandler // TYPE_URI: uri string 88b9f7aac3488873677377b36c57338d758098f78eDan Sandler private String mString1; 89b9f7aac3488873677377b36c57338d758098f78eDan Sandler 90b9f7aac3488873677377b36c57338d758098f78eDan Sandler // TYPE_RESOURCE: resId 91b9f7aac3488873677377b36c57338d758098f78eDan Sandler // TYPE_DATA: data length 92b9f7aac3488873677377b36c57338d758098f78eDan Sandler private int mInt1; 93b9f7aac3488873677377b36c57338d758098f78eDan Sandler 94b9f7aac3488873677377b36c57338d758098f78eDan Sandler // TYPE_DATA: data offset 95b9f7aac3488873677377b36c57338d758098f78eDan Sandler private int mInt2; 96b9f7aac3488873677377b36c57338d758098f78eDan Sandler 97d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 98d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The type of image data held in this Icon. One of 99d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * {@link #TYPE_BITMAP}, 100d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * {@link #TYPE_RESOURCE}, 101d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * {@link #TYPE_DATA}, or 102d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * {@link #TYPE_URI}. 103d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 104d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 105d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public int getType() { 106d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler return mType; 107d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler } 108d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler 109d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 110d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The {@link android.graphics.Bitmap} held by this {@link #TYPE_BITMAP} Icon. 111d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 112d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 113d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public Bitmap getBitmap() { 114b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (mType != TYPE_BITMAP) { 115b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalStateException("called getBitmap() on " + this); 116b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 117b9f7aac3488873677377b36c57338d758098f78eDan Sandler return (Bitmap) mObj1; 118b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 119b9f7aac3488873677377b36c57338d758098f78eDan Sandler 120a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi private void setBitmap(Bitmap b) { 121a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi mObj1 = b; 122a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi } 123a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi 124d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 125d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The length of the compressed bitmap byte array held by this {@link #TYPE_DATA} Icon. 126d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 127d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 128d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public int getDataLength() { 129b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (mType != TYPE_DATA) { 130b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalStateException("called getDataLength() on " + this); 131b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 132b9f7aac3488873677377b36c57338d758098f78eDan Sandler synchronized (this) { 133b9f7aac3488873677377b36c57338d758098f78eDan Sandler return mInt1; 134b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 135b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 136b9f7aac3488873677377b36c57338d758098f78eDan Sandler 137d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 138d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The offset into the byte array held by this {@link #TYPE_DATA} Icon at which 139d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * valid compressed bitmap data is found. 140d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 141d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 142d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public int getDataOffset() { 143b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (mType != TYPE_DATA) { 144b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalStateException("called getDataOffset() on " + this); 145b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 146b9f7aac3488873677377b36c57338d758098f78eDan Sandler synchronized (this) { 147b9f7aac3488873677377b36c57338d758098f78eDan Sandler return mInt2; 148b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 149b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 150b9f7aac3488873677377b36c57338d758098f78eDan Sandler 151d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 152d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The byte array held by this {@link #TYPE_DATA} Icon ctonaining compressed 153d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * bitmap data. 154d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 155d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 156d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public byte[] getDataBytes() { 157b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (mType != TYPE_DATA) { 158b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalStateException("called getDataBytes() on " + this); 159b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 160b9f7aac3488873677377b36c57338d758098f78eDan Sandler synchronized (this) { 161b9f7aac3488873677377b36c57338d758098f78eDan Sandler return (byte[]) mObj1; 162b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 163b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 164b9f7aac3488873677377b36c57338d758098f78eDan Sandler 165d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 166d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The {@link android.content.res.Resources} for this {@link #TYPE_RESOURCE} Icon. 167d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 168d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 169d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public Resources getResources() { 170b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (mType != TYPE_RESOURCE) { 171b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalStateException("called getResources() on " + this); 172b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 173b9f7aac3488873677377b36c57338d758098f78eDan Sandler return (Resources) mObj1; 174b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 175b9f7aac3488873677377b36c57338d758098f78eDan Sandler 176d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 177d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The package containing resources for this {@link #TYPE_RESOURCE} Icon. 178d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 179d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 180d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public String getResPackage() { 181b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (mType != TYPE_RESOURCE) { 182b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalStateException("called getResPackage() on " + this); 183b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 184b9f7aac3488873677377b36c57338d758098f78eDan Sandler return mString1; 185b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 186b9f7aac3488873677377b36c57338d758098f78eDan Sandler 187d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 188d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The resource ID for this {@link #TYPE_RESOURCE} Icon. 189d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 190d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 191d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public int getResId() { 192b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (mType != TYPE_RESOURCE) { 193b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalStateException("called getResId() on " + this); 194b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 195b9f7aac3488873677377b36c57338d758098f78eDan Sandler return mInt1; 196b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 197b9f7aac3488873677377b36c57338d758098f78eDan Sandler 198d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 199d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The URI (as a String) for this {@link #TYPE_URI} Icon. 200d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 201d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 202d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public String getUriString() { 203b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (mType != TYPE_URI) { 204b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalStateException("called getUriString() on " + this); 205b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 206b9f7aac3488873677377b36c57338d758098f78eDan Sandler return mString1; 207b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 208b9f7aac3488873677377b36c57338d758098f78eDan Sandler 209d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler /** 210d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @return The {@link android.net.Uri} for this {@link #TYPE_URI} Icon. 211d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler * @hide 212d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler */ 213d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler public Uri getUri() { 214b9f7aac3488873677377b36c57338d758098f78eDan Sandler return Uri.parse(getUriString()); 215b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 216b9f7aac3488873677377b36c57338d758098f78eDan Sandler 217b9f7aac3488873677377b36c57338d758098f78eDan Sandler private static final String typeToString(int x) { 218b9f7aac3488873677377b36c57338d758098f78eDan Sandler switch (x) { 219b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_BITMAP: return "BITMAP"; 220b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_DATA: return "DATA"; 221b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_RESOURCE: return "RESOURCE"; 222b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_URI: return "URI"; 223b9f7aac3488873677377b36c57338d758098f78eDan Sandler default: return "UNKNOWN"; 224b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 225b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 226b9f7aac3488873677377b36c57338d758098f78eDan Sandler 227b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 228b9f7aac3488873677377b36c57338d758098f78eDan Sandler * Invokes {@link #loadDrawable(Context)} on the given {@link android.os.Handler Handler} 229b9f7aac3488873677377b36c57338d758098f78eDan Sandler * and then sends <code>andThen</code> to the same Handler when finished. 230b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 231b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param context {@link android.content.Context Context} in which to load the drawable; see 232b9f7aac3488873677377b36c57338d758098f78eDan Sandler * {@link #loadDrawable(Context)} 233b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param andThen {@link android.os.Message} to send to its target once the drawable 234b9f7aac3488873677377b36c57338d758098f78eDan Sandler * is available. The {@link android.os.Message#obj obj} 235b9f7aac3488873677377b36c57338d758098f78eDan Sandler * property is populated with the Drawable. 236b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 237b9f7aac3488873677377b36c57338d758098f78eDan Sandler public void loadDrawableAsync(Context context, Message andThen) { 238b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (andThen.getTarget() == null) { 239b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new IllegalArgumentException("callback message must have a target handler"); 240b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 241b9f7aac3488873677377b36c57338d758098f78eDan Sandler new LoadDrawableTask(context, andThen).runAsync(); 242b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 243b9f7aac3488873677377b36c57338d758098f78eDan Sandler 244b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 245b9f7aac3488873677377b36c57338d758098f78eDan Sandler * Invokes {@link #loadDrawable(Context)} on a background thread 246b9f7aac3488873677377b36c57338d758098f78eDan Sandler * and then runs <code>andThen</code> on the UI thread when finished. 247b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 248877d696c382ecb8a97972450c8819536641a963cDan Sandler * @param context {@link Context Context} in which to load the drawable; see 249b9f7aac3488873677377b36c57338d758098f78eDan Sandler * {@link #loadDrawable(Context)} 250b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param listener a callback to run on the provided 251877d696c382ecb8a97972450c8819536641a963cDan Sandler * @param handler {@link Handler} on which to run <code>andThen</code>. 252b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 253877d696c382ecb8a97972450c8819536641a963cDan Sandler public void loadDrawableAsync(Context context, final OnDrawableLoadedListener listener, 254877d696c382ecb8a97972450c8819536641a963cDan Sandler Handler handler) { 255b9f7aac3488873677377b36c57338d758098f78eDan Sandler new LoadDrawableTask(context, handler, listener).runAsync(); 256b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 257b9f7aac3488873677377b36c57338d758098f78eDan Sandler 258b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 259b9f7aac3488873677377b36c57338d758098f78eDan Sandler * Returns a Drawable that can be used to draw the image inside this Icon, constructing it 260b9f7aac3488873677377b36c57338d758098f78eDan Sandler * if necessary. Depending on the type of image, this may not be something you want to do on 261b9f7aac3488873677377b36c57338d758098f78eDan Sandler * the UI thread, so consider using 262b9f7aac3488873677377b36c57338d758098f78eDan Sandler * {@link #loadDrawableAsync(Context, Message) loadDrawableAsync} instead. 263b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 264b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param context {@link android.content.Context Context} in which to load the drawable; used 265b9f7aac3488873677377b36c57338d758098f78eDan Sandler * to access {@link android.content.res.Resources Resources}, for example. 266b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @return A fresh instance of a drawable for this image, yours to keep. 267b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 268b9f7aac3488873677377b36c57338d758098f78eDan Sandler public Drawable loadDrawable(Context context) { 26924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler final Drawable result = loadDrawableInner(context); 27024f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler if (result != null && (mTintList != null || mTintMode != DEFAULT_TINT_MODE)) { 27124f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler result.mutate(); 27224f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler result.setTintList(mTintList); 27324f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler result.setTintMode(mTintMode); 27424f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 27524f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler return result; 27624f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 27724f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler 27824f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler /** 27924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * Do the heavy lifting of loading the drawable, but stop short of applying any tint. 28024f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler */ 28124f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler private Drawable loadDrawableInner(Context context) { 282b9f7aac3488873677377b36c57338d758098f78eDan Sandler switch (mType) { 283b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_BITMAP: 284b9f7aac3488873677377b36c57338d758098f78eDan Sandler return new BitmapDrawable(context.getResources(), getBitmap()); 285b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_RESOURCE: 286b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (getResources() == null) { 2874e78706f439d318ae7a78927d98f734351a89f64Dan Sandler // figure out where to load resources from 2884e78706f439d318ae7a78927d98f734351a89f64Dan Sandler String resPackage = getResPackage(); 2894e78706f439d318ae7a78927d98f734351a89f64Dan Sandler if (TextUtils.isEmpty(resPackage)) { 2904e78706f439d318ae7a78927d98f734351a89f64Dan Sandler // if none is specified, try the given context 2914e78706f439d318ae7a78927d98f734351a89f64Dan Sandler resPackage = context.getPackageName(); 2924e78706f439d318ae7a78927d98f734351a89f64Dan Sandler } 2934e78706f439d318ae7a78927d98f734351a89f64Dan Sandler if ("android".equals(resPackage)) { 294b9f7aac3488873677377b36c57338d758098f78eDan Sandler mObj1 = Resources.getSystem(); 295b9f7aac3488873677377b36c57338d758098f78eDan Sandler } else { 296b9f7aac3488873677377b36c57338d758098f78eDan Sandler final PackageManager pm = context.getPackageManager(); 297b9f7aac3488873677377b36c57338d758098f78eDan Sandler try { 298c7fd3462a2699f73d5f2ba6d863d8be4ddd570a9Julia Reynolds ApplicationInfo ai = pm.getApplicationInfo( 299c7fd3462a2699f73d5f2ba6d863d8be4ddd570a9Julia Reynolds resPackage, PackageManager.GET_UNINSTALLED_PACKAGES); 300c7fd3462a2699f73d5f2ba6d863d8be4ddd570a9Julia Reynolds if (ai != null) { 301c7fd3462a2699f73d5f2ba6d863d8be4ddd570a9Julia Reynolds mObj1 = pm.getResourcesForApplication(ai); 302c7fd3462a2699f73d5f2ba6d863d8be4ddd570a9Julia Reynolds } else { 303c7fd3462a2699f73d5f2ba6d863d8be4ddd570a9Julia Reynolds break; 304c7fd3462a2699f73d5f2ba6d863d8be4ddd570a9Julia Reynolds } 305b9f7aac3488873677377b36c57338d758098f78eDan Sandler } catch (PackageManager.NameNotFoundException e) { 3064e78706f439d318ae7a78927d98f734351a89f64Dan Sandler Log.e(TAG, String.format("Unable to find pkg=%s for icon %s", 3074e78706f439d318ae7a78927d98f734351a89f64Dan Sandler resPackage, this), e); 308b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 309b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 310b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 311b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 312877d696c382ecb8a97972450c8819536641a963cDan Sandler try { 313877d696c382ecb8a97972450c8819536641a963cDan Sandler return getResources().getDrawable(getResId(), context.getTheme()); 314877d696c382ecb8a97972450c8819536641a963cDan Sandler } catch (RuntimeException e) { 315877d696c382ecb8a97972450c8819536641a963cDan Sandler Log.e(TAG, String.format("Unable to load resource 0x%08x from pkg=%s", 316877d696c382ecb8a97972450c8819536641a963cDan Sandler getResId(), 317877d696c382ecb8a97972450c8819536641a963cDan Sandler getResPackage()), 318877d696c382ecb8a97972450c8819536641a963cDan Sandler e); 319877d696c382ecb8a97972450c8819536641a963cDan Sandler } 320220239e37110bf7d97aa92270be5a12ab0cf5e24Yorke Lee break; 321b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_DATA: 322b9f7aac3488873677377b36c57338d758098f78eDan Sandler return new BitmapDrawable(context.getResources(), 323b9f7aac3488873677377b36c57338d758098f78eDan Sandler BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(), getDataLength()) 324b9f7aac3488873677377b36c57338d758098f78eDan Sandler ); 325b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_URI: 326b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Uri uri = getUri(); 327b9f7aac3488873677377b36c57338d758098f78eDan Sandler final String scheme = uri.getScheme(); 328b9f7aac3488873677377b36c57338d758098f78eDan Sandler InputStream is = null; 329b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (ContentResolver.SCHEME_CONTENT.equals(scheme) 330b9f7aac3488873677377b36c57338d758098f78eDan Sandler || ContentResolver.SCHEME_FILE.equals(scheme)) { 331b9f7aac3488873677377b36c57338d758098f78eDan Sandler try { 332b9f7aac3488873677377b36c57338d758098f78eDan Sandler is = context.getContentResolver().openInputStream(uri); 333b9f7aac3488873677377b36c57338d758098f78eDan Sandler } catch (Exception e) { 334b9f7aac3488873677377b36c57338d758098f78eDan Sandler Log.w(TAG, "Unable to load image from URI: " + uri, e); 335b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 336b9f7aac3488873677377b36c57338d758098f78eDan Sandler } else { 337b9f7aac3488873677377b36c57338d758098f78eDan Sandler try { 338b9f7aac3488873677377b36c57338d758098f78eDan Sandler is = new FileInputStream(new File(mString1)); 339b9f7aac3488873677377b36c57338d758098f78eDan Sandler } catch (FileNotFoundException e) { 340b9f7aac3488873677377b36c57338d758098f78eDan Sandler Log.w(TAG, "Unable to load image from path: " + uri, e); 341b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 342b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 343b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (is != null) { 344b9f7aac3488873677377b36c57338d758098f78eDan Sandler return new BitmapDrawable(context.getResources(), 345b9f7aac3488873677377b36c57338d758098f78eDan Sandler BitmapFactory.decodeStream(is)); 346b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 347b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 348b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 349b9f7aac3488873677377b36c57338d758098f78eDan Sandler return null; 350b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 351b9f7aac3488873677377b36c57338d758098f78eDan Sandler 352877d696c382ecb8a97972450c8819536641a963cDan Sandler /** 353877d696c382ecb8a97972450c8819536641a963cDan Sandler * Load the requested resources under the given userId, if the system allows it, 354877d696c382ecb8a97972450c8819536641a963cDan Sandler * before actually loading the drawable. 355877d696c382ecb8a97972450c8819536641a963cDan Sandler * 356877d696c382ecb8a97972450c8819536641a963cDan Sandler * @hide 357877d696c382ecb8a97972450c8819536641a963cDan Sandler */ 358877d696c382ecb8a97972450c8819536641a963cDan Sandler public Drawable loadDrawableAsUser(Context context, int userId) { 359877d696c382ecb8a97972450c8819536641a963cDan Sandler if (mType == TYPE_RESOURCE) { 3604e78706f439d318ae7a78927d98f734351a89f64Dan Sandler String resPackage = getResPackage(); 3614e78706f439d318ae7a78927d98f734351a89f64Dan Sandler if (TextUtils.isEmpty(resPackage)) { 3624e78706f439d318ae7a78927d98f734351a89f64Dan Sandler resPackage = context.getPackageName(); 3634e78706f439d318ae7a78927d98f734351a89f64Dan Sandler } 3644e78706f439d318ae7a78927d98f734351a89f64Dan Sandler if (getResources() == null && !(getResPackage().equals("android"))) { 365877d696c382ecb8a97972450c8819536641a963cDan Sandler final PackageManager pm = context.getPackageManager(); 366877d696c382ecb8a97972450c8819536641a963cDan Sandler try { 3674e78706f439d318ae7a78927d98f734351a89f64Dan Sandler // assign getResources() as the correct user 3684e78706f439d318ae7a78927d98f734351a89f64Dan Sandler mObj1 = pm.getResourcesForApplicationAsUser(resPackage, userId); 369877d696c382ecb8a97972450c8819536641a963cDan Sandler } catch (PackageManager.NameNotFoundException e) { 370877d696c382ecb8a97972450c8819536641a963cDan Sandler Log.e(TAG, String.format("Unable to find pkg=%s user=%d", 371877d696c382ecb8a97972450c8819536641a963cDan Sandler getResPackage(), 372877d696c382ecb8a97972450c8819536641a963cDan Sandler userId), 373877d696c382ecb8a97972450c8819536641a963cDan Sandler e); 374877d696c382ecb8a97972450c8819536641a963cDan Sandler } 375877d696c382ecb8a97972450c8819536641a963cDan Sandler } 376877d696c382ecb8a97972450c8819536641a963cDan Sandler } 377877d696c382ecb8a97972450c8819536641a963cDan Sandler return loadDrawable(context); 378877d696c382ecb8a97972450c8819536641a963cDan Sandler } 379877d696c382ecb8a97972450c8819536641a963cDan Sandler 380cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon /** 381a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi * Puts the memory used by this instance into Ashmem memory, if possible. 382a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi * @hide 383a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi */ 384a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi public void convertToAshmem() { 385a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi if (mType == TYPE_BITMAP && getBitmap().isMutable()) { 386a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi setBitmap(getBitmap().createAshmemBitmap()); 387a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi } 388a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi } 389a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi 390a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi /** 391cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon * Writes a serialized version of an Icon to the specified stream. 392cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon * 393cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon * @param stream The stream on which to serialize the Icon. 394cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon * @hide 395cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon */ 396cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon public void writeToStream(OutputStream stream) throws IOException { 397cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon DataOutputStream dataStream = new DataOutputStream(stream); 398cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon 399cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon dataStream.writeInt(VERSION_STREAM_SERIALIZER); 400cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon dataStream.writeByte(mType); 401cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon 402cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon switch (mType) { 403cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon case TYPE_BITMAP: 404cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon getBitmap().compress(Bitmap.CompressFormat.PNG, 100, dataStream); 405cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon break; 406cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon case TYPE_DATA: 407cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon dataStream.writeInt(getDataLength()); 408cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon dataStream.write(getDataBytes(), getDataOffset(), getDataLength()); 409cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon break; 410cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon case TYPE_RESOURCE: 411cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon dataStream.writeUTF(getResPackage()); 412cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon dataStream.writeInt(getResId()); 413cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon break; 414cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon case TYPE_URI: 415cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon dataStream.writeUTF(getUriString()); 416cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon break; 417cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 418cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 419cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon 420b9f7aac3488873677377b36c57338d758098f78eDan Sandler private Icon(int mType) { 421b9f7aac3488873677377b36c57338d758098f78eDan Sandler this.mType = mType; 422b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 423b9f7aac3488873677377b36c57338d758098f78eDan Sandler 424b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 425cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon * Create an Icon from the specified stream. 426cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon * 427cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon * @param stream The input stream from which to reconstruct the Icon. 428cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon * @hide 429cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon */ 430cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon public static Icon createFromStream(InputStream stream) throws IOException { 431cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon DataInputStream inputStream = new DataInputStream(stream); 432cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon 433cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon final int version = inputStream.readInt(); 434cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon if (version >= VERSION_STREAM_SERIALIZER) { 435cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon final int type = inputStream.readByte(); 436cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon switch (type) { 437cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon case TYPE_BITMAP: 438cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon return createWithBitmap(BitmapFactory.decodeStream(inputStream)); 439cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon case TYPE_DATA: 440cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon final int length = inputStream.readInt(); 441cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon final byte[] data = new byte[length]; 442cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon inputStream.read(data, 0 /* offset */, length); 443cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon return createWithData(data, 0 /* offset */, length); 444cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon case TYPE_RESOURCE: 445cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon final String packageName = inputStream.readUTF(); 446cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon final int resId = inputStream.readInt(); 447cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon return createWithResource(packageName, resId); 448cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon case TYPE_URI: 449cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon final String uriOrPath = inputStream.readUTF(); 450cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon return createWithContentUri(uriOrPath); 451cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 452cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 453cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon return null; 454cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 455cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon 456cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon /** 457877d696c382ecb8a97972450c8819536641a963cDan Sandler * Create an Icon pointing to a drawable resource. 45802cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler * @param context The context for the application whose resources should be used to resolve the 45902cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler * given resource ID. 460877d696c382ecb8a97972450c8819536641a963cDan Sandler * @param resId ID of the drawable resource 461b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 46202cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler public static Icon createWithResource(Context context, @DrawableRes int resId) { 4634e78706f439d318ae7a78927d98f734351a89f64Dan Sandler if (context == null) { 4644e78706f439d318ae7a78927d98f734351a89f64Dan Sandler throw new IllegalArgumentException("Context must not be null."); 4654e78706f439d318ae7a78927d98f734351a89f64Dan Sandler } 46602cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler final Icon rep = new Icon(TYPE_RESOURCE); 46702cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler rep.mInt1 = resId; 46802cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler rep.mString1 = context.getPackageName(); 46902cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler return rep; 47002cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler } 47102cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler 47202cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler /** 47302cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler * Version of createWithResource that takes Resources. Do not use. 47402cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler * @hide 47502cd9f91a6bd6d06d6d1237f8b978a0ab0b8ea32Dan Sandler */ 476877d696c382ecb8a97972450c8819536641a963cDan Sandler public static Icon createWithResource(Resources res, @DrawableRes int resId) { 477cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon if (res == null) { 478cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon throw new IllegalArgumentException("Resource must not be null."); 479cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 480b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Icon rep = new Icon(TYPE_RESOURCE); 481877d696c382ecb8a97972450c8819536641a963cDan Sandler rep.mInt1 = resId; 482877d696c382ecb8a97972450c8819536641a963cDan Sandler rep.mString1 = res.getResourcePackageName(resId); 483877d696c382ecb8a97972450c8819536641a963cDan Sandler return rep; 484877d696c382ecb8a97972450c8819536641a963cDan Sandler } 485877d696c382ecb8a97972450c8819536641a963cDan Sandler 486877d696c382ecb8a97972450c8819536641a963cDan Sandler /** 487877d696c382ecb8a97972450c8819536641a963cDan Sandler * Create an Icon pointing to a drawable resource. 488877d696c382ecb8a97972450c8819536641a963cDan Sandler * @param resPackage Name of the package containing the resource in question 489877d696c382ecb8a97972450c8819536641a963cDan Sandler * @param resId ID of the drawable resource 490877d696c382ecb8a97972450c8819536641a963cDan Sandler */ 491877d696c382ecb8a97972450c8819536641a963cDan Sandler public static Icon createWithResource(String resPackage, @DrawableRes int resId) { 492cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon if (resPackage == null) { 493cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon throw new IllegalArgumentException("Resource package name must not be null."); 494cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 495877d696c382ecb8a97972450c8819536641a963cDan Sandler final Icon rep = new Icon(TYPE_RESOURCE); 496877d696c382ecb8a97972450c8819536641a963cDan Sandler rep.mInt1 = resId; 497877d696c382ecb8a97972450c8819536641a963cDan Sandler rep.mString1 = resPackage; 498b9f7aac3488873677377b36c57338d758098f78eDan Sandler return rep; 499b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 500b9f7aac3488873677377b36c57338d758098f78eDan Sandler 501b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 502877d696c382ecb8a97972450c8819536641a963cDan Sandler * Create an Icon pointing to a bitmap in memory. 503b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param bits A valid {@link android.graphics.Bitmap} object 504b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 505b9f7aac3488873677377b36c57338d758098f78eDan Sandler public static Icon createWithBitmap(Bitmap bits) { 506cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon if (bits == null) { 507cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon throw new IllegalArgumentException("Bitmap must not be null."); 508cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 509b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Icon rep = new Icon(TYPE_BITMAP); 510a0d58ae574a3a69145512e0cd92e7842f0fbf83dJorim Jaggi rep.setBitmap(bits); 511b9f7aac3488873677377b36c57338d758098f78eDan Sandler return rep; 512b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 513b9f7aac3488873677377b36c57338d758098f78eDan Sandler 514b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 515877d696c382ecb8a97972450c8819536641a963cDan Sandler * Create an Icon pointing to a compressed bitmap stored in a byte array. 516b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param data Byte array storing compressed bitmap data of a type that 517b9f7aac3488873677377b36c57338d758098f78eDan Sandler * {@link android.graphics.BitmapFactory} 518b9f7aac3488873677377b36c57338d758098f78eDan Sandler * can decode (see {@link android.graphics.Bitmap.CompressFormat}). 519b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param offset Offset into <code>data</code> at which the bitmap data starts 520b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param length Length of the bitmap data 521b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 522b9f7aac3488873677377b36c57338d758098f78eDan Sandler public static Icon createWithData(byte[] data, int offset, int length) { 523cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon if (data == null) { 524cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon throw new IllegalArgumentException("Data must not be null."); 525cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 526b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Icon rep = new Icon(TYPE_DATA); 527b9f7aac3488873677377b36c57338d758098f78eDan Sandler rep.mObj1 = data; 528b9f7aac3488873677377b36c57338d758098f78eDan Sandler rep.mInt1 = length; 529b9f7aac3488873677377b36c57338d758098f78eDan Sandler rep.mInt2 = offset; 530b9f7aac3488873677377b36c57338d758098f78eDan Sandler return rep; 531b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 532b9f7aac3488873677377b36c57338d758098f78eDan Sandler 533b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 534877d696c382ecb8a97972450c8819536641a963cDan Sandler * Create an Icon pointing to an image file specified by URI. 535b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 536b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param uri A uri referring to local content:// or file:// image data. 537b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 538b9f7aac3488873677377b36c57338d758098f78eDan Sandler public static Icon createWithContentUri(String uri) { 539cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon if (uri == null) { 540cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon throw new IllegalArgumentException("Uri must not be null."); 541cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 542b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Icon rep = new Icon(TYPE_URI); 543b9f7aac3488873677377b36c57338d758098f78eDan Sandler rep.mString1 = uri; 544b9f7aac3488873677377b36c57338d758098f78eDan Sandler return rep; 545b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 546b9f7aac3488873677377b36c57338d758098f78eDan Sandler 547b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 548877d696c382ecb8a97972450c8819536641a963cDan Sandler * Create an Icon pointing to an image file specified by URI. 549b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 550b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param uri A uri referring to local content:// or file:// image data. 551b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 552b9f7aac3488873677377b36c57338d758098f78eDan Sandler public static Icon createWithContentUri(Uri uri) { 553cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon if (uri == null) { 554cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon throw new IllegalArgumentException("Uri must not be null."); 555cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 556b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Icon rep = new Icon(TYPE_URI); 557b9f7aac3488873677377b36c57338d758098f78eDan Sandler rep.mString1 = uri.toString(); 558b9f7aac3488873677377b36c57338d758098f78eDan Sandler return rep; 559b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 560b9f7aac3488873677377b36c57338d758098f78eDan Sandler 561b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 56224f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * Store a color to use whenever this Icon is drawn. 56324f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * 56424f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * @param tint a color, as in {@link Drawable#setTint(int)} 56524f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * @return this same object, for use in chained construction 56624f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler */ 56724f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler public Icon setTint(@ColorInt int tint) { 56824f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler return setTintList(ColorStateList.valueOf(tint)); 56924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 57024f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler 57124f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler /** 57224f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * Store a color to use whenever this Icon is drawn. 57324f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * 57424f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * @param tintList as in {@link Drawable#setTintList(ColorStateList)}, null to remove tint 57524f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * @return this same object, for use in chained construction 57624f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler */ 57724f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler public Icon setTintList(ColorStateList tintList) { 57824f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler mTintList = tintList; 57924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler return this; 58024f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 58124f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler 58224f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler /** 58324f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * Store a blending mode to use whenever this Icon is drawn. 58424f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * 58524f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null 58624f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler * @return this same object, for use in chained construction 58724f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler */ 58824f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler public Icon setTintMode(PorterDuff.Mode mode) { 58924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler mTintMode = mode; 59024f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler return this; 59124f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 59224f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler 59324f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler /** 594877d696c382ecb8a97972450c8819536641a963cDan Sandler * Create an Icon pointing to an image file specified by path. 595b9f7aac3488873677377b36c57338d758098f78eDan Sandler * 596b9f7aac3488873677377b36c57338d758098f78eDan Sandler * @param path A path to a file that contains compressed bitmap data of 597b9f7aac3488873677377b36c57338d758098f78eDan Sandler * a type that {@link android.graphics.BitmapFactory} can decode. 598b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 599b9f7aac3488873677377b36c57338d758098f78eDan Sandler public static Icon createWithFilePath(String path) { 600cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon if (path == null) { 601cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon throw new IllegalArgumentException("Path must not be null."); 602cad84a2070b68093ab31b05389685fdbcd0d9f85Santos Cordon } 603b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Icon rep = new Icon(TYPE_URI); 604b9f7aac3488873677377b36c57338d758098f78eDan Sandler rep.mString1 = path; 605b9f7aac3488873677377b36c57338d758098f78eDan Sandler return rep; 606b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 607b9f7aac3488873677377b36c57338d758098f78eDan Sandler 608b9f7aac3488873677377b36c57338d758098f78eDan Sandler @Override 609b9f7aac3488873677377b36c57338d758098f78eDan Sandler public String toString() { 610b9f7aac3488873677377b36c57338d758098f78eDan Sandler final StringBuilder sb = new StringBuilder("Icon(typ=").append(typeToString(mType)); 611b9f7aac3488873677377b36c57338d758098f78eDan Sandler switch (mType) { 612b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_BITMAP: 613b9f7aac3488873677377b36c57338d758098f78eDan Sandler sb.append(" size=") 614b9f7aac3488873677377b36c57338d758098f78eDan Sandler .append(getBitmap().getWidth()) 615b9f7aac3488873677377b36c57338d758098f78eDan Sandler .append("x") 616b9f7aac3488873677377b36c57338d758098f78eDan Sandler .append(getBitmap().getHeight()); 617b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 618b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_RESOURCE: 619b9f7aac3488873677377b36c57338d758098f78eDan Sandler sb.append(" pkg=") 620b9f7aac3488873677377b36c57338d758098f78eDan Sandler .append(getResPackage()) 621b9f7aac3488873677377b36c57338d758098f78eDan Sandler .append(" id=") 622d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler .append(String.format("0x%08x", getResId())); 623b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 624b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_DATA: 625b9f7aac3488873677377b36c57338d758098f78eDan Sandler sb.append(" len=").append(getDataLength()); 626b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (getDataOffset() != 0) { 627b9f7aac3488873677377b36c57338d758098f78eDan Sandler sb.append(" off=").append(getDataOffset()); 628b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 629b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 630b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_URI: 631b9f7aac3488873677377b36c57338d758098f78eDan Sandler sb.append(" uri=").append(getUriString()); 632b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 633b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 63424f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler if (mTintList != null) { 63524f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler sb.append(" tint="); 63624f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler String sep = ""; 63724f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler for (int c : mTintList.getColors()) { 63824f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler sb.append(String.format("%s0x%08x", sep, c)); 63924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler sep = "|"; 64024f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 64124f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 64224f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler if (mTintMode != DEFAULT_TINT_MODE) sb.append(" mode=").append(mTintMode); 643b9f7aac3488873677377b36c57338d758098f78eDan Sandler sb.append(")"); 644b9f7aac3488873677377b36c57338d758098f78eDan Sandler return sb.toString(); 645b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 646b9f7aac3488873677377b36c57338d758098f78eDan Sandler 647b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 648b9f7aac3488873677377b36c57338d758098f78eDan Sandler * Parcelable interface 649b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 650b9f7aac3488873677377b36c57338d758098f78eDan Sandler public int describeContents() { 651b9f7aac3488873677377b36c57338d758098f78eDan Sandler return (mType == TYPE_BITMAP || mType == TYPE_DATA) 652b9f7aac3488873677377b36c57338d758098f78eDan Sandler ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0; 653b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 654b9f7aac3488873677377b36c57338d758098f78eDan Sandler 655b9f7aac3488873677377b36c57338d758098f78eDan Sandler // ===== Parcelable interface ====== 656b9f7aac3488873677377b36c57338d758098f78eDan Sandler 657b9f7aac3488873677377b36c57338d758098f78eDan Sandler private Icon(Parcel in) { 658b9f7aac3488873677377b36c57338d758098f78eDan Sandler this(in.readInt()); 659b9f7aac3488873677377b36c57338d758098f78eDan Sandler switch (mType) { 660b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_BITMAP: 661b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Bitmap bits = Bitmap.CREATOR.createFromParcel(in); 662b9f7aac3488873677377b36c57338d758098f78eDan Sandler mObj1 = bits; 663b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 664b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_RESOURCE: 665b9f7aac3488873677377b36c57338d758098f78eDan Sandler final String pkg = in.readString(); 666b9f7aac3488873677377b36c57338d758098f78eDan Sandler final int resId = in.readInt(); 667b9f7aac3488873677377b36c57338d758098f78eDan Sandler mString1 = pkg; 668b9f7aac3488873677377b36c57338d758098f78eDan Sandler mInt1 = resId; 669b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 670b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_DATA: 671b9f7aac3488873677377b36c57338d758098f78eDan Sandler final int len = in.readInt(); 672b9f7aac3488873677377b36c57338d758098f78eDan Sandler final byte[] a = in.readBlob(); 673b9f7aac3488873677377b36c57338d758098f78eDan Sandler if (len != a.length) { 674b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new RuntimeException("internal unparceling error: blob length (" 675b9f7aac3488873677377b36c57338d758098f78eDan Sandler + a.length + ") != expected length (" + len + ")"); 676b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 677b9f7aac3488873677377b36c57338d758098f78eDan Sandler mInt1 = len; 678b9f7aac3488873677377b36c57338d758098f78eDan Sandler mObj1 = a; 679b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 680b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_URI: 681b9f7aac3488873677377b36c57338d758098f78eDan Sandler final String uri = in.readString(); 682b9f7aac3488873677377b36c57338d758098f78eDan Sandler mString1 = uri; 683b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 684b9f7aac3488873677377b36c57338d758098f78eDan Sandler default: 685b9f7aac3488873677377b36c57338d758098f78eDan Sandler throw new RuntimeException("invalid " 686b9f7aac3488873677377b36c57338d758098f78eDan Sandler + this.getClass().getSimpleName() + " type in parcel: " + mType); 687b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 68824f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler if (in.readInt() == 1) { 68924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler mTintList = ColorStateList.CREATOR.createFromParcel(in); 69024f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 69124f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler mTintMode = PorterDuff.intToMode(in.readInt()); 692b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 693b9f7aac3488873677377b36c57338d758098f78eDan Sandler 694b9f7aac3488873677377b36c57338d758098f78eDan Sandler @Override 695b9f7aac3488873677377b36c57338d758098f78eDan Sandler public void writeToParcel(Parcel dest, int flags) { 69624f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler dest.writeInt(mType); 697b9f7aac3488873677377b36c57338d758098f78eDan Sandler switch (mType) { 698b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_BITMAP: 699b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Bitmap bits = getBitmap(); 700b9f7aac3488873677377b36c57338d758098f78eDan Sandler getBitmap().writeToParcel(dest, flags); 701b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 702b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_RESOURCE: 703b9f7aac3488873677377b36c57338d758098f78eDan Sandler dest.writeString(getResPackage()); 704b9f7aac3488873677377b36c57338d758098f78eDan Sandler dest.writeInt(getResId()); 705b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 706b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_DATA: 707b9f7aac3488873677377b36c57338d758098f78eDan Sandler dest.writeInt(getDataLength()); 708b9f7aac3488873677377b36c57338d758098f78eDan Sandler dest.writeBlob(getDataBytes(), getDataOffset(), getDataLength()); 709b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 710b9f7aac3488873677377b36c57338d758098f78eDan Sandler case TYPE_URI: 711b9f7aac3488873677377b36c57338d758098f78eDan Sandler dest.writeString(getUriString()); 712b9f7aac3488873677377b36c57338d758098f78eDan Sandler break; 713b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 71424f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler if (mTintList == null) { 71524f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler dest.writeInt(0); 71624f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } else { 71724f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler dest.writeInt(1); 71824f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler mTintList.writeToParcel(dest, flags); 71924f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler } 72024f11b1871f9def5d802d107897658c4b2b66ab5Dan Sandler dest.writeInt(PorterDuff.modeToInt(mTintMode)); 721b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 722b9f7aac3488873677377b36c57338d758098f78eDan Sandler 723b9f7aac3488873677377b36c57338d758098f78eDan Sandler public static final Parcelable.Creator<Icon> CREATOR 724b9f7aac3488873677377b36c57338d758098f78eDan Sandler = new Parcelable.Creator<Icon>() { 725b9f7aac3488873677377b36c57338d758098f78eDan Sandler public Icon createFromParcel(Parcel in) { 726b9f7aac3488873677377b36c57338d758098f78eDan Sandler return new Icon(in); 727b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 728b9f7aac3488873677377b36c57338d758098f78eDan Sandler 729b9f7aac3488873677377b36c57338d758098f78eDan Sandler public Icon[] newArray(int size) { 730b9f7aac3488873677377b36c57338d758098f78eDan Sandler return new Icon[size]; 731b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 732b9f7aac3488873677377b36c57338d758098f78eDan Sandler }; 733b9f7aac3488873677377b36c57338d758098f78eDan Sandler 734b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 735877d696c382ecb8a97972450c8819536641a963cDan Sandler * Implement this interface to receive a callback when 736877d696c382ecb8a97972450c8819536641a963cDan Sandler * {@link #loadDrawableAsync(Context, OnDrawableLoadedListener, Handler) loadDrawableAsync} 737b9f7aac3488873677377b36c57338d758098f78eDan Sandler * is finished and your Drawable is ready. 738b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 739b9f7aac3488873677377b36c57338d758098f78eDan Sandler public interface OnDrawableLoadedListener { 740b9f7aac3488873677377b36c57338d758098f78eDan Sandler void onDrawableLoaded(Drawable d); 741b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 742b9f7aac3488873677377b36c57338d758098f78eDan Sandler 743b9f7aac3488873677377b36c57338d758098f78eDan Sandler /** 744b9f7aac3488873677377b36c57338d758098f78eDan Sandler * Wrapper around loadDrawable that does its work on a pooled thread and then 745b9f7aac3488873677377b36c57338d758098f78eDan Sandler * fires back the given (targeted) Message. 746b9f7aac3488873677377b36c57338d758098f78eDan Sandler */ 747b9f7aac3488873677377b36c57338d758098f78eDan Sandler private class LoadDrawableTask implements Runnable { 748b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Context mContext; 749b9f7aac3488873677377b36c57338d758098f78eDan Sandler final Message mMessage; 750b9f7aac3488873677377b36c57338d758098f78eDan Sandler 751b9f7aac3488873677377b36c57338d758098f78eDan Sandler public LoadDrawableTask(Context context, final Handler handler, 752b9f7aac3488873677377b36c57338d758098f78eDan Sandler final OnDrawableLoadedListener listener) { 753b9f7aac3488873677377b36c57338d758098f78eDan Sandler mContext = context; 754b9f7aac3488873677377b36c57338d758098f78eDan Sandler mMessage = Message.obtain(handler, new Runnable() { 755b9f7aac3488873677377b36c57338d758098f78eDan Sandler @Override 756b9f7aac3488873677377b36c57338d758098f78eDan Sandler public void run() { 757b9f7aac3488873677377b36c57338d758098f78eDan Sandler listener.onDrawableLoaded((Drawable) mMessage.obj); 758b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 759b9f7aac3488873677377b36c57338d758098f78eDan Sandler }); 760b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 761b9f7aac3488873677377b36c57338d758098f78eDan Sandler 762b9f7aac3488873677377b36c57338d758098f78eDan Sandler public LoadDrawableTask(Context context, Message message) { 763b9f7aac3488873677377b36c57338d758098f78eDan Sandler mContext = context; 764b9f7aac3488873677377b36c57338d758098f78eDan Sandler mMessage = message; 765b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 766b9f7aac3488873677377b36c57338d758098f78eDan Sandler 767b9f7aac3488873677377b36c57338d758098f78eDan Sandler @Override 768b9f7aac3488873677377b36c57338d758098f78eDan Sandler public void run() { 769b9f7aac3488873677377b36c57338d758098f78eDan Sandler mMessage.obj = loadDrawable(mContext); 770b9f7aac3488873677377b36c57338d758098f78eDan Sandler mMessage.sendToTarget(); 771b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 772b9f7aac3488873677377b36c57338d758098f78eDan Sandler 773b9f7aac3488873677377b36c57338d758098f78eDan Sandler public void runAsync() { 774b9f7aac3488873677377b36c57338d758098f78eDan Sandler AsyncTask.THREAD_POOL_EXECUTOR.execute(this); 775b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 776b9f7aac3488873677377b36c57338d758098f78eDan Sandler } 777b9f7aac3488873677377b36c57338d758098f78eDan Sandler} 778