Attachment.java revision b334c9035e9b7a38766bb66c29da2208525d1e11
17b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira/** 27b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Copyright (c) 2011, Google Inc. 37b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * 47b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 57b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * you may not use this file except in compliance with the License. 67b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * You may obtain a copy of the License at 77b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * 87b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 97b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * 107b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Unless required by applicable law or agreed to in writing, software 117b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 127b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * See the License for the specific language governing permissions and 147b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * limitations under the License. 157b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira */ 1630e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.providers; 177b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 1888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport android.content.Intent; 1988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport android.database.Cursor; 2088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport android.net.Uri; 217aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereiraimport android.os.Parcel; 227aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereiraimport android.os.Parcelable; 23f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereiraimport android.text.TextUtils; 24f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 2588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentColumns; 2688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentDestination; 2788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentState; 28b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 295a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport com.android.mail.utils.LogUtils; 304c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sappersteinimport com.google.common.collect.Lists; 315a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 325a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONArray; 335a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONException; 345a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONObject; 357b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 365a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport java.util.Collection; 375a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport java.util.List; 384401c9049f0327019b0bfed554bf8ff5cdaa20e2Mindy Pereira 397aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereirapublic class Attachment implements Parcelable { 40f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira public static final int SERVER_ATTACHMENT = 0; 41f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira /** Extras are "<path>". */ 42f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira public static final int LOCAL_FILE = 1; 43f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 44b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook public static final String LOG_TAG = LogTag.getLogTag(); 455a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 467aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 4788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang * Attachment file name. See {@link AttachmentColumns#NAME}. 487aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 497aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public String name; 50f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 5188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 5288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang * Attachment size in bytes. See {@link AttachmentColumns#SIZE}. 5388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 5488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int size; 55f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 567aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 575c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * The provider-generated URI for this Attachment. Must be globally unique. For local 585c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * attachments generated by the Compose UI prior to send/save, this field will be null. 595c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 605c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang *@see AttachmentColumns#URI 617aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 6288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public Uri uri; 6388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 647aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 655c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * MIME type of the file. 665c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 675c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#CONTENT_TYPE 687aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 691eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang public String contentType; 7088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 7188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 725c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#STATE 7388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 7488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int state; 7588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 7688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 775c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#DESTINATION 7888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 7988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int destination; 8088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 817aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 825c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#DOWNLOADED_SIZE 837aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 8488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int downloadedSize; 8588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 8688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 875c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#CONTENT_URI 8888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 891eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang public Uri contentUri; 9088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 9188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 925c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * Might be null. 935c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 945c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#THUMBNAIL_URI 9588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 9688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public Uri thumbnailUri; 9788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 9888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang /** 995c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * Might be null. 1005c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 1015c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * @see AttachmentColumns#PREVIEW_INTENT 10288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang */ 10388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public Intent previewIntent; 10488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1057aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 1067aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira * Part id of the attachment. 1077aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 1085c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang @Deprecated 1095c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang // partId is provider implementation specific. providers must uniquely identify Attachments 1105c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang // by uri. 1117aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public String partId; 11288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1135c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang @Deprecated 1145c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang // this is a local file iff the provider 'uri' field is null. 11588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public int origin; 11688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1177aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira /** 11888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang * Attachment origin info. 11988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang * TODO: do we want this? Or location? 1207aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira */ 1215c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang @Deprecated 12288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public String originExtras; 1237b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 1247aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public Attachment(Parcel in) { 1257aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira name = in.readString(); 12688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang size = in.readInt(); 12788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang uri = in.readParcelable(null); 1281eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang contentType = in.readString(); 12988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang state = in.readInt(); 13088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang destination = in.readInt(); 13188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang downloadedSize = in.readInt(); 1321eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang contentUri = in.readParcelable(null); 13388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang thumbnailUri = in.readParcelable(null); 13488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang previewIntent = in.readParcelable(null); 1357aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira partId = in.readString(); 136f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira origin = in.readInt(); 13788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang originExtras = in.readString(); 1387aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 1397b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 1407aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public Attachment() { 1417aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 1427b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 14388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public Attachment(Cursor cursor) { 14488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang if (cursor == null) { 14588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return; 14688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 14788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1484c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein name = cursor.getString(cursor.getColumnIndex(AttachmentColumns.NAME)); 1494c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein size = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.SIZE)); 1504c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein uri = Uri.parse(cursor.getString(cursor.getColumnIndex(AttachmentColumns.URI))); 1514c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein contentType = cursor.getString(cursor.getColumnIndex(AttachmentColumns.CONTENT_TYPE)); 1524c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein state = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.STATE)); 1534c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein destination = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.DESTINATION)); 1544c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein downloadedSize = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.DOWNLOADED_SIZE)); 1554c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein contentUri = parseOptionalUri( 1564c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein cursor.getString(cursor.getColumnIndex(AttachmentColumns.CONTENT_URI))); 15788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang thumbnailUri = parseOptionalUri( 1584c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein cursor.getString(cursor.getColumnIndex(AttachmentColumns.THUMBNAIL_URI))); 15988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang previewIntent = getOptionalIntentFromBlob( 1604c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein cursor.getBlob(cursor.getColumnIndex(AttachmentColumns.PREVIEW_INTENT))); 16188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 16288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang // TODO: ensure that local files attached to a draft have sane values, like SAVED/EXTERNAL 16388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang // and that contentUri is populated 16488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 16588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1665c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang @Deprecated 167f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira public Attachment(String attachmentString) { 1685e1a5b7a9d694ff812e65f4b1240366252cdcde7Paul Westbrook String[] attachmentValues = TextUtils.split(attachmentString, "\\|"); 169f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira if (attachmentValues != null) { 170f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira partId = attachmentValues[0]; 171f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira name = attachmentValues[1]; 1721eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang contentType = attachmentValues[2]; 173f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira try { 17488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang size = Integer.parseInt(attachmentValues[3]); 175f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } catch (NumberFormatException e) { 176f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira size = 0; 177f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } 1781eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang contentType = attachmentValues[4]; 179f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira origin = Integer.parseInt(attachmentValues[5]); 1801eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang contentUri = parseOptionalUri(attachmentValues[6]); 181f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira originExtras = attachmentValues[7]; 182f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } 183f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } 184f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 1855c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang @Deprecated 18688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public String toJoinedString() { 1871eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang // FIXME: contentType is read/written twice 18888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return TextUtils.join("|", Lists.newArrayList(partId == null ? "" : partId, 1891eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang name == null ? "" : name.replaceAll("[|\n]", ""), contentType, size, contentType, 1905c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang contentUri != null ? LOCAL_FILE : SERVER_ATTACHMENT, contentUri, 1915c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang originExtras == null ? "" : originExtras, "")); 19288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 19388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 19488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang private static Intent getOptionalIntentFromBlob(byte[] blob) { 19588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang if (blob == null) { 19688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return null; 19788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 19888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang final Parcel intentParcel = Parcel.obtain(); 19988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang intentParcel.unmarshall(blob, 0, blob.length); 20088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang final Intent intent = new Intent(); 20188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang intent.readFromParcel(intentParcel); 20288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return intent; 20388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 20488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 20588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang private static Uri parseOptionalUri(String uriString) { 20688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return uriString == null ? null : Uri.parse(uriString); 20788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 20888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 2097aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira @Override 2107aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public int describeContents() { 2117aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira return 0; 2127aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 2137b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 2147aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira @Override 2157aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public void writeToParcel(Parcel dest, int flags) { 2167aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira dest.writeString(name); 21788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang dest.writeInt(size); 21888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang dest.writeParcelable(uri, flags); 2191eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang dest.writeString(contentType); 22088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang dest.writeInt(state); 22188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang dest.writeInt(destination); 22288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang dest.writeInt(downloadedSize); 2231eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang dest.writeParcelable(contentUri, flags); 22488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang dest.writeParcelable(thumbnailUri, flags); 22588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang dest.writeParcelable(previewIntent, flags); 2267aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira dest.writeString(partId); 227f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira dest.writeInt(origin); 22888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang dest.writeString(originExtras); 2297aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 2307b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 2317aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public static final Creator<Attachment> CREATOR = new Creator<Attachment>() { 2327aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira @Override 2337aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public Attachment createFromParcel(Parcel source) { 2347aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira return new Attachment(source); 2357aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 2367b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 2377aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira @Override 2387aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira public Attachment[] newArray(int size) { 2397aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira return new Attachment[size]; 2407aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira } 2417aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira }; 242f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 24388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public boolean isImage() { 244ac57b84f62110b1897176807ef1a02bd11675e71Mindy Pereira return !TextUtils.isEmpty(contentType) ? contentType.startsWith("image/") : false; 24588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 246f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 24788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public boolean isDownloading() { 24888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return state == AttachmentState.DOWNLOADING; 249f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } 250f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira 25188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public boolean isPresentLocally() { 25288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return state == AttachmentState.SAVED || origin == LOCAL_FILE; 25388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 25488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 25588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public boolean isSavedToExternal() { 25688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang return state == AttachmentState.SAVED && destination == AttachmentDestination.EXTERNAL; 257f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira } 2584401c9049f0327019b0bfed554bf8ff5cdaa20e2Mindy Pereira 25988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang public boolean canSave() { 260c6663c4f87b458aefef3213599ddea65e87ae223Andy Huang return origin != LOCAL_FILE && state != AttachmentState.DOWNLOADING && 261c6663c4f87b458aefef3213599ddea65e87ae223Andy Huang !isSavedToExternal(); 26288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang } 2634401c9049f0327019b0bfed554bf8ff5cdaa20e2Mindy Pereira 264d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang /** 265d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang * If this attachment is an image, returns a Uri pointing to the image that can be used as a 266d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang * thumbnail. If the provider supports dedicated thumbnails, it will be relatively small, but 267d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang * if not, the image may be arbitrarily large. Client code must handle this efficiently. For 268d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang * non-image attachments, this method will return null. This method may also return null if the 269d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang * attachment is not yet downloaded. 270d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang */ 271d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang public Uri getImageUri() { 272d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang if (!isImage()) { 273d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang return null; 274d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang } 275d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang 276d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang return (thumbnailUri != null) ? thumbnailUri : contentUri; 277d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang } 278d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang 2795a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang // Methods to support JSON [de-]serialization of Attachment data 2805a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang // TODO: add support for origin/originExtras (and possibly partId?) or fold those fields into 2815a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang // other fields so Compose View can use JSON objects 2825a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 2835a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang public JSONObject toJSON() throws JSONException { 2845c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang return toJSON(name, size, uri, contentUri, contentType); 2855a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 2865a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 2875c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang public static JSONObject toJSON(String name, int size, Uri uri, Uri contentUri, 2885c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang String contentType) throws JSONException { 2895a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang final JSONObject result = new JSONObject(); 2905a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 2915a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang result.putOpt(AttachmentColumns.NAME, name); 2925a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang result.putOpt(AttachmentColumns.SIZE, size); 2935a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang if (uri != null) { 2945a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang result.putOpt(AttachmentColumns.URI, uri.toString()); 2955a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 2965c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang if (contentUri != null) { 2975c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang result.putOpt(AttachmentColumns.CONTENT_URI, contentUri.toString()); 2985c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } 2995a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang result.putOpt(AttachmentColumns.CONTENT_TYPE, contentType); 3005a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 3015a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang return result; 3025a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3035a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 3045a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang public Attachment(JSONObject srcJson) { 3055a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang name = srcJson.optString(AttachmentColumns.NAME, null); 3065a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang size = srcJson.optInt(AttachmentColumns.SIZE); 3075a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang uri = parseOptionalUri(srcJson, AttachmentColumns.URI); 3085c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang contentUri = parseOptionalUri(srcJson, AttachmentColumns.CONTENT_URI); 3095a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang contentType = srcJson.optString(AttachmentColumns.CONTENT_TYPE, null); 3105a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3115a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 3125a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang private static Uri parseOptionalUri(JSONObject srcJson, String key) { 3135a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang final String uriStr = srcJson.optString(key, null); 3145a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang return uriStr == null ? null : Uri.parse(uriStr); 3155a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3165a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 3175a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang public static String toJSONArray(Collection<Attachment> attachments) { 3185a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang final JSONArray result = new JSONArray(); 3195a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang try { 3205a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang for (Attachment attachment : attachments) { 3215a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang result.put(attachment.toJSON()); 3225a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3235a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } catch (JSONException e) { 3245a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang throw new IllegalArgumentException(e); 3255a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3265a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang return result.toString(); 3275a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3285a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 3295a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang public static List<Attachment> fromJSONArray(String jsonArrayStr) { 3305a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang final List<Attachment> results = Lists.newArrayList(); 3315a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang try { 3325a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang final JSONArray arr = new JSONArray(jsonArrayStr); 3335a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 3345a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang for (int i = 0; i < arr.length(); i++) { 3355a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang results.add(new Attachment(arr.getJSONObject(i))); 3365a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3375a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 3385a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } catch (JSONException e) { 3395a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang throw new IllegalArgumentException(e); 3405a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3415a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang return results; 3425a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang } 3435a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang 3447b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira} 345