Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2015 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 package com.android.messaging.datamodel.media;
     17 
     18 import android.content.Intent;
     19 import android.content.res.Resources;
     20 import android.content.res.Resources.NotFoundException;
     21 import android.net.Uri;
     22 import android.provider.ContactsContract.CommonDataKinds.Im;
     23 import android.provider.ContactsContract.CommonDataKinds.Organization;
     24 import android.provider.ContactsContract.CommonDataKinds.Phone;
     25 import android.support.v4.util.ArrayMap;
     26 import android.text.TextUtils;
     27 
     28 import com.android.messaging.Factory;
     29 import com.android.messaging.R;
     30 import com.android.messaging.datamodel.MediaScratchFileProvider;
     31 import com.android.messaging.datamodel.data.PersonItemData;
     32 import com.android.messaging.util.ContactUtil;
     33 import com.android.messaging.util.LogUtil;
     34 import com.android.messaging.util.SafeAsyncTask;
     35 import com.android.vcard.VCardEntry;
     36 import com.android.vcard.VCardEntry.EmailData;
     37 import com.android.vcard.VCardEntry.ImData;
     38 import com.android.vcard.VCardEntry.NoteData;
     39 import com.android.vcard.VCardEntry.OrganizationData;
     40 import com.android.vcard.VCardEntry.PhoneData;
     41 import com.android.vcard.VCardEntry.PostalData;
     42 import com.android.vcard.VCardEntry.WebsiteData;
     43 import com.android.vcard.VCardProperty;
     44 
     45 import java.io.UnsupportedEncodingException;
     46 import java.net.URLEncoder;
     47 import java.util.ArrayList;
     48 import java.util.List;
     49 
     50 /**
     51  * Holds one entry item (i.e. a single contact) within a VCard resource. It is able to take
     52  * a VCardEntry and extract relevant information from it.
     53  */
     54 public class VCardResourceEntry {
     55     public static final String PROPERTY_KIND = "KIND";
     56 
     57     public static final String KIND_LOCATION = "location";
     58 
     59     private final List<VCardResourceEntry.VCardResourceEntryDestinationItem> mContactInfo;
     60     private final Uri mAvatarUri;
     61     private final String mDisplayName;
     62     private final CustomVCardEntry mVCard;
     63 
     64     public VCardResourceEntry(final CustomVCardEntry vcard, final Uri avatarUri) {
     65         mContactInfo = getContactInfoFromVCardEntry(vcard);
     66         mDisplayName = getDisplayNameFromVCardEntry(vcard);
     67         mAvatarUri = avatarUri;
     68         mVCard = vcard;
     69     }
     70 
     71     void close() {
     72         // If the avatar image was temporarily saved in the scratch folder, remove that.
     73         if (MediaScratchFileProvider.isMediaScratchSpaceUri(mAvatarUri)) {
     74             SafeAsyncTask.executeOnThreadPool(new Runnable() {
     75                 @Override
     76                 public void run() {
     77                     Factory.get().getApplicationContext().getContentResolver().delete(
     78                             mAvatarUri, null, null);
     79                 }
     80             });
     81         }
     82     }
     83 
     84     public String getKind() {
     85         VCardProperty kindProperty = mVCard.getProperty(PROPERTY_KIND);
     86         return kindProperty == null ? null : kindProperty.getRawValue();
     87     }
     88 
     89     public Uri getAvatarUri() {
     90         return mAvatarUri;
     91     }
     92 
     93     public String getDisplayName() {
     94         return mDisplayName;
     95     }
     96 
     97     public String getDisplayAddress() {
     98         List<PostalData> postalList = mVCard.getPostalList();
     99         if (postalList == null || postalList.size() < 1) {
    100             return null;
    101         }
    102 
    103         return formatAddress(postalList.get(0));
    104     }
    105 
    106     public String getNotes() {
    107         List<NoteData> notes = mVCard.getNotes();
    108         if (notes == null || notes.size() == 0) {
    109             return null;
    110         }
    111         StringBuilder noteBuilder = new StringBuilder();
    112         for (NoteData note : notes) {
    113             noteBuilder.append(note.getNote());
    114         }
    115         return noteBuilder.toString();
    116     }
    117 
    118     /**
    119      * Returns a UI-facing representation that can be bound and consumed by the UI layer to display
    120      * this VCard resource entry.
    121      */
    122     public PersonItemData getDisplayItem() {
    123         return new PersonItemData() {
    124             @Override
    125             public Uri getAvatarUri() {
    126                 return VCardResourceEntry.this.getAvatarUri();
    127             }
    128 
    129             @Override
    130             public String getDisplayName() {
    131                 return VCardResourceEntry.this.getDisplayName();
    132             }
    133 
    134             @Override
    135             public String getDetails() {
    136                 return null;
    137             }
    138 
    139             @Override
    140             public Intent getClickIntent() {
    141                 return null;
    142             }
    143 
    144             @Override
    145             public long getContactId() {
    146                 return ContactUtil.INVALID_CONTACT_ID;
    147             }
    148 
    149             @Override
    150             public String getLookupKey() {
    151                 return null;
    152             }
    153 
    154             @Override
    155             public String getNormalizedDestination() {
    156                 return null;
    157             }
    158         };
    159     }
    160 
    161     public List<VCardResourceEntry.VCardResourceEntryDestinationItem> getContactInfo() {
    162         return mContactInfo;
    163     }
    164 
    165     private static List<VCardResourceEntryDestinationItem> getContactInfoFromVCardEntry(
    166             final VCardEntry vcard) {
    167         final Resources resources = Factory.get().getApplicationContext().getResources();
    168         final List<VCardResourceEntry.VCardResourceEntryDestinationItem> retList =
    169                 new ArrayList<VCardResourceEntry.VCardResourceEntryDestinationItem>();
    170         if (vcard.getPhoneList() != null) {
    171             for (final PhoneData phone : vcard.getPhoneList()) {
    172                 final Intent intent = new Intent(Intent.ACTION_DIAL);
    173                 intent.setData(Uri.parse("tel:" + phone.getNumber()));
    174                 retList.add(new VCardResourceEntryDestinationItem(phone.getNumber(),
    175                         Phone.getTypeLabel(resources, phone.getType(), phone.getLabel()).toString(),
    176                         intent));
    177             }
    178         }
    179 
    180         if (vcard.getEmailList() != null) {
    181             for (final EmailData email : vcard.getEmailList()) {
    182                 final Intent intent = new Intent(Intent.ACTION_SENDTO);
    183                 intent.setData(Uri.parse("mailto:"));
    184                 intent.putExtra(Intent.EXTRA_EMAIL, new String[] { email.getAddress() });
    185                 retList.add(new VCardResourceEntryDestinationItem(email.getAddress(),
    186                         Phone.getTypeLabel(resources, email.getType(),
    187                                 email.getLabel()).toString(), intent));
    188             }
    189         }
    190 
    191         if (vcard.getPostalList() != null) {
    192             for (final PostalData postalData : vcard.getPostalList()) {
    193                 String type;
    194                 try {
    195                     type = resources.
    196                             getStringArray(android.R.array.postalAddressTypes)
    197                             [postalData.getType() - 1];
    198                 } catch (final NotFoundException ex) {
    199                     type = resources.getStringArray(android.R.array.postalAddressTypes)[2];
    200                 } catch (final Exception e) {
    201                     LogUtil.e(LogUtil.BUGLE_TAG, "createContactItem postal Exception:" + e);
    202                     type = resources.getStringArray(android.R.array.postalAddressTypes)[2];
    203                 }
    204                 Intent intent = new Intent(Intent.ACTION_VIEW);
    205                 final String address = formatAddress(postalData);
    206                 try {
    207                     intent.setData(Uri.parse("geo:0,0?q=" + URLEncoder.encode(address, "UTF-8")));
    208                 } catch (UnsupportedEncodingException e) {
    209                     intent = null;
    210                 }
    211 
    212                 retList.add(new VCardResourceEntryDestinationItem(address, type, intent));
    213             }
    214         }
    215 
    216         if (vcard.getImList() != null) {
    217             for (final ImData imData : vcard.getImList()) {
    218                 String type = null;
    219                 try {
    220                     type = resources.
    221                             getString(Im.getProtocolLabelResource(imData.getProtocol()));
    222                 } catch (final NotFoundException ex) {
    223                     // Do nothing since this implies an empty label.
    224                 }
    225                 retList.add(new VCardResourceEntryDestinationItem(imData.getAddress(), type, null));
    226             }
    227         }
    228 
    229         if (vcard.getOrganizationList() != null) {
    230             for (final OrganizationData organtization : vcard.getOrganizationList()) {
    231                 String type = null;
    232                 try {
    233                      type = resources.getString(Organization.getTypeLabelResource(
    234                                     organtization.getType()));
    235                 } catch (final NotFoundException ex) {
    236                     //set other kind as "other"
    237                     type = resources.getStringArray(android.R.array.organizationTypes)[1];
    238                 } catch (final Exception e) {
    239                     LogUtil.e(LogUtil.BUGLE_TAG, "createContactItem org Exception:" + e);
    240                     type = resources.getStringArray(android.R.array.organizationTypes)[1];
    241                 }
    242                 retList.add(new VCardResourceEntryDestinationItem(
    243                         organtization.getOrganizationName(), type, null));
    244             }
    245         }
    246 
    247         if (vcard.getWebsiteList() != null) {
    248             for (final WebsiteData web : vcard.getWebsiteList()) {
    249                 if (web != null && TextUtils.isGraphic(web.getWebsite())){
    250                     String website = web.getWebsite();
    251                     if (!website.startsWith("http://") && !website.startsWith("https://")) {
    252                         // Prefix required for parsing to end up with a scheme and result in
    253                         // navigation
    254                         website = "http://" + website;
    255                     }
    256                     final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(website));
    257                     retList.add(new VCardResourceEntryDestinationItem(web.getWebsite(), null,
    258                             intent));
    259                 }
    260             }
    261         }
    262 
    263         if (vcard.getBirthday() != null) {
    264              final String birthday = vcard.getBirthday();
    265              if (TextUtils.isGraphic(birthday)){
    266                  retList.add(new VCardResourceEntryDestinationItem(birthday,
    267                          resources.getString(R.string.vcard_detail_birthday_label), null));
    268              }
    269         }
    270 
    271         if (vcard.getNotes() != null) {
    272             for (final NoteData note : vcard.getNotes()) {
    273                  final ArrayMap<String, String> curChildMap = new ArrayMap<String, String>();
    274                  if (TextUtils.isGraphic(note.getNote())){
    275                      retList.add(new VCardResourceEntryDestinationItem(note.getNote(),
    276                              resources.getString(R.string.vcard_detail_notes_label), null));
    277                  }
    278              }
    279         }
    280         return retList;
    281     }
    282 
    283     private static String formatAddress(final PostalData postalData) {
    284         final StringBuilder sb = new StringBuilder();
    285         final String poBox = postalData.getPobox();
    286         if (!TextUtils.isEmpty(poBox)) {
    287             sb.append(poBox);
    288             sb.append(" ");
    289         }
    290         final String extendedAddress = postalData.getExtendedAddress();
    291         if (!TextUtils.isEmpty(extendedAddress)) {
    292             sb.append(extendedAddress);
    293             sb.append(" ");
    294         }
    295         final String street = postalData.getStreet();
    296         if (!TextUtils.isEmpty(street)) {
    297             sb.append(street);
    298             sb.append(" ");
    299         }
    300         final String localty = postalData.getLocalty();
    301         if (!TextUtils.isEmpty(localty)) {
    302             sb.append(localty);
    303             sb.append(" ");
    304         }
    305         final String region = postalData.getRegion();
    306         if (!TextUtils.isEmpty(region)) {
    307             sb.append(region);
    308             sb.append(" ");
    309         }
    310         final String postalCode = postalData.getPostalCode();
    311         if (!TextUtils.isEmpty(postalCode)) {
    312             sb.append(postalCode);
    313             sb.append(" ");
    314         }
    315         final String country = postalData.getCountry();
    316         if (!TextUtils.isEmpty(country)) {
    317             sb.append(country);
    318         }
    319         return sb.toString();
    320     }
    321 
    322     private static String getDisplayNameFromVCardEntry(final VCardEntry vcard) {
    323         String name = vcard.getDisplayName();
    324         if (name == null) {
    325             vcard.consolidateFields();
    326             name = vcard.getDisplayName();
    327         }
    328         return name;
    329     }
    330 
    331     /**
    332      * Represents one entry line (e.g. phone number and phone label) for a single contact. Each
    333      * VCardResourceEntry may hold one or more VCardResourceEntryDestinationItem's.
    334      */
    335     public static class VCardResourceEntryDestinationItem {
    336         private final String mDisplayDestination;
    337         private final String mDestinationType;
    338         private final Intent mClickIntent;
    339         public VCardResourceEntryDestinationItem(final String displayDestination,
    340                 final String destinationType, final Intent clickIntent) {
    341             mDisplayDestination = displayDestination;
    342             mDestinationType = destinationType;
    343             mClickIntent = clickIntent;
    344         }
    345 
    346         /**
    347          * Returns a UI-facing representation that can be bound and consumed by the UI layer to
    348          * display this VCard resource destination entry.
    349          */
    350         public PersonItemData getDisplayItem() {
    351             return new PersonItemData() {
    352                 @Override
    353                 public Uri getAvatarUri() {
    354                     return null;
    355                 }
    356 
    357                 @Override
    358                 public String getDisplayName() {
    359                     return mDisplayDestination;
    360                 }
    361 
    362                 @Override
    363                 public String getDetails() {
    364                     return mDestinationType;
    365                 }
    366 
    367                 @Override
    368                 public Intent getClickIntent() {
    369                     return mClickIntent;
    370                 }
    371 
    372                 @Override
    373                 public long getContactId() {
    374                     return ContactUtil.INVALID_CONTACT_ID;
    375                 }
    376 
    377                 @Override
    378                 public String getLookupKey() {
    379                     return null;
    380                 }
    381 
    382                 @Override
    383                 public String getNormalizedDestination() {
    384                     return null;
    385                 }
    386             };
    387         }
    388     }
    389 }
    390