summaryrefslogtreecommitdiffstats
path: root/java/com/android/dialer/lookup/ContactBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/lookup/ContactBuilder.java')
-rw-r--r--java/com/android/dialer/lookup/ContactBuilder.java524
1 files changed, 524 insertions, 0 deletions
diff --git a/java/com/android/dialer/lookup/ContactBuilder.java b/java/com/android/dialer/lookup/ContactBuilder.java
new file mode 100644
index 000000000..12d4206b9
--- /dev/null
+++ b/java/com/android/dialer/lookup/ContactBuilder.java
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2014 Xiao-Long Chen <chillermillerlong@hotmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dialer.lookup;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.provider.ContactsContract.CommonDataKinds.Website;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
+import android.provider.ContactsContract.DisplayNameSources;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.contacts.common.util.Constants;
+import com.android.dialer.phonenumbercache.ContactInfo;
+import com.android.dialer.R;
+
+import java.sql.Struct;
+import java.util.ArrayList;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONTokener;
+import org.w3c.dom.Text;
+
+public class ContactBuilder {
+ private static final String TAG =
+ ContactBuilder.class.getSimpleName();
+
+ private static final boolean DEBUG = false;
+
+ /** Used to choose the proper directory ID */
+ public static final int FORWARD_LOOKUP = 0;
+ public static final int PEOPLE_LOOKUP = 1;
+ public static final int REVERSE_LOOKUP = 2;
+
+ /** Default photo for businesses if no other image is found */
+ public static final String PHOTO_URI_BUSINESS =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority("com.android.dialer")
+ .appendPath(String.valueOf(
+ R.drawable.ic_places_picture_180_holo_light))
+ .build()
+ .toString();
+
+ private ArrayList<Address> mAddresses = new ArrayList<Address>();
+ private ArrayList<PhoneNumber> mPhoneNumbers
+ = new ArrayList<PhoneNumber>();
+ private ArrayList<WebsiteUrl> mWebsites
+ = new ArrayList<WebsiteUrl>();
+
+ private int mDirectoryType;
+ private long mDirectoryId = DirectoryId.DEFAULT;
+
+ private Name mName;
+
+ private String mNormalizedNumber;
+ private String mFormattedNumber;
+ private int mDisplayNameSource = DisplayNameSources.ORGANIZATION;
+ private Uri mPhotoUri;
+
+ private boolean mIsBusiness;
+
+ public ContactBuilder(int directoryType, String normalizedNumber,
+ String formattedNumber) {
+ mDirectoryType = directoryType;
+ mNormalizedNumber = normalizedNumber;
+ mFormattedNumber = formattedNumber;
+ }
+
+ public ContactBuilder(Uri encodedContactUri) throws JSONException {
+ String jsonData = encodedContactUri.getEncodedFragment();
+ String directoryId =
+ encodedContactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
+ if (!TextUtils.isEmpty(directoryId)) {
+ try {
+ mDirectoryId = Long.parseLong(directoryId);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Error parsing directory id of uri " + encodedContactUri, e);
+ }
+ }
+ try {
+ // name
+ JSONObject json = new JSONObject(jsonData);
+ JSONObject contact = json.optJSONObject(Contacts.CONTENT_ITEM_TYPE);
+ JSONObject nameObj = contact.optJSONObject(StructuredName.CONTENT_ITEM_TYPE);
+ mName = new Name(nameObj);
+
+ if (contact != null) {
+ // numbers
+ if (contact.has(Phone.CONTENT_ITEM_TYPE)) {
+ String phoneData = contact.getString(Phone.CONTENT_ITEM_TYPE);
+ Object phoneObject = new JSONTokener(phoneData).nextValue();
+ JSONArray phoneNumbers;
+ if (phoneObject instanceof JSONObject) {
+ phoneNumbers = new JSONArray();
+ phoneNumbers.put(phoneObject);
+ } else {
+ phoneNumbers = contact.getJSONArray(Phone.CONTENT_ITEM_TYPE);
+ }
+ for (int i = 0; i < phoneNumbers.length(); ++i) {
+ JSONObject phoneObj = phoneNumbers.getJSONObject(i);
+ mPhoneNumbers.add(new PhoneNumber(phoneObj));
+ }
+ }
+
+ // address
+ if (contact.has(StructuredPostal.CONTENT_ITEM_TYPE)) {
+ JSONArray addresses = contact.getJSONArray(StructuredPostal.CONTENT_ITEM_TYPE);
+ for (int i = 0; i < addresses.length(); ++i) {
+ JSONObject addrObj = addresses.getJSONObject(i);
+ mAddresses.add(new Address(addrObj));
+ }
+ }
+
+ // websites
+ if (contact.has(Website.CONTENT_ITEM_TYPE)) {
+ JSONArray websites = contact.getJSONArray(Website.CONTENT_ITEM_TYPE);
+ for (int i = 0; i < websites.length(); ++i) {
+ JSONObject websiteObj = websites.getJSONObject(i);
+ final WebsiteUrl websiteUrl = new WebsiteUrl(websiteObj);
+ if (!TextUtils.isEmpty(websiteUrl.url)) {
+ mWebsites.add(new WebsiteUrl(websiteObj));
+ }
+ }
+ }
+ }
+
+ }
+ catch(JSONException e) {
+ Log.e(TAG, "Error parsing encoded fragment of uri " + encodedContactUri, e);
+ throw e;
+ }
+ }
+
+ public void addAddress(Address address) {
+ if (DEBUG) Log.d(TAG, "Adding address");
+ if (address != null) {
+ mAddresses.add(address);
+ }
+ }
+
+ public Address[] getAddresses() {
+ return mAddresses.toArray(new Address[mAddresses.size()]);
+ }
+
+ public void addPhoneNumber(PhoneNumber phoneNumber) {
+ if (DEBUG) Log.d(TAG, "Adding phone number");
+ if (phoneNumber != null) {
+ mPhoneNumbers.add(phoneNumber);
+ }
+ }
+
+ public PhoneNumber[] getPhoneNumbers() {
+ return mPhoneNumbers.toArray(
+ new PhoneNumber[mPhoneNumbers.size()]);
+ }
+
+ public void addWebsite(WebsiteUrl website) {
+ if (DEBUG) Log.d(TAG, "Adding website");
+ if (website != null) {
+ mWebsites.add(website);
+ }
+ }
+
+ public WebsiteUrl[] getWebsites() {
+ return mWebsites.toArray(new WebsiteUrl[mWebsites.size()]);
+ }
+
+ public void setName(Name name) {
+ if (DEBUG) Log.d(TAG, "Setting name");
+ if (name != null) {
+ mName = name;
+ }
+ }
+
+ public Name getName() {
+ return mName;
+ }
+
+ public void setPhotoUri(String photoUri) {
+ if (photoUri != null) {
+ setPhotoUri(Uri.parse(photoUri));
+ }
+ }
+
+ public void setPhotoUri(Uri photoUri) {
+ if (DEBUG) Log.d(TAG, "Setting photo URI");
+ mPhotoUri = photoUri;
+ }
+
+ public Uri getPhotoUri() {
+ return mPhotoUri;
+ }
+
+ public long getDirectoryId() {
+ return mDirectoryId;
+ }
+
+ public void setIsBusiness(boolean isBusiness) {
+ if (DEBUG) Log.d(TAG, "Setting isBusiness to " + isBusiness);
+ mIsBusiness = isBusiness;
+ }
+
+ public boolean isBusiness() {
+ return mIsBusiness;
+ }
+
+ public ContactInfo build() {
+ if (mName == null) {
+ throw new IllegalStateException("Name has not been set");
+ }
+
+ if (mDirectoryType != FORWARD_LOOKUP
+ && mDirectoryType != PEOPLE_LOOKUP
+ && mDirectoryType != REVERSE_LOOKUP) {
+ throw new IllegalStateException("Invalid directory type");
+ }
+
+ // Use the incoming call's phone number if no other phone number
+ // is specified. The reverse lookup source could present the phone
+ // number differently (eg. without the area code).
+ if (mPhoneNumbers.size() == 0) {
+ PhoneNumber pn = new PhoneNumber();
+ // Use the formatted number where possible
+ pn.number = mFormattedNumber != null
+ ? mFormattedNumber : mNormalizedNumber;
+ pn.type = Phone.TYPE_MAIN;
+ addPhoneNumber(pn);
+ }
+
+ try {
+ JSONObject contact = new JSONObject();
+
+ // Insert the name
+ contact.put(StructuredName.CONTENT_ITEM_TYPE,
+ mName.getJsonObject());
+
+ // Insert phone numbers
+ JSONArray phoneNumbers = new JSONArray();
+ for (int i = 0; i < mPhoneNumbers.size(); i++) {
+ phoneNumbers.put(mPhoneNumbers.get(i).getJsonObject());
+ }
+ contact.put(Phone.CONTENT_ITEM_TYPE, phoneNumbers);
+
+ // Insert addresses if there are any
+ if (mAddresses.size() > 0) {
+ JSONArray addresses = new JSONArray();
+ for (int i = 0; i < mAddresses.size(); i++) {
+ addresses.put(mAddresses.get(i).getJsonObject());
+ }
+ contact.put(StructuredPostal.CONTENT_ITEM_TYPE, addresses);
+ }
+
+ // Insert websites if there are any
+ if (mWebsites.size() > 0) {
+ JSONArray websites = new JSONArray();
+ for (int i = 0; i < mWebsites.size(); i++) {
+ websites.put(mWebsites.get(i).getJsonObject());
+ }
+ contact.put(Website.CONTENT_ITEM_TYPE, websites);
+ }
+
+ ContactInfo info = new ContactInfo();
+ info.name = mName.displayName;
+ info.normalizedNumber = mNormalizedNumber;
+ info.number = mPhoneNumbers.get(0).number;
+ info.type = mPhoneNumbers.get(0).type;
+ info.label = mPhoneNumbers.get(0).label;
+ info.photoUri = mPhotoUri != null ? mPhotoUri : null;
+
+ String json = new JSONObject()
+ .put(Contacts.DISPLAY_NAME, mName.displayName)
+ .put(Contacts.DISPLAY_NAME_SOURCE, mDisplayNameSource)
+ .put(Directory.EXPORT_SUPPORT,
+ Directory.EXPORT_SUPPORT_ANY_ACCOUNT)
+ .put(Contacts.CONTENT_ITEM_TYPE, contact)
+ .toString();
+
+ if (json != null) {
+ long directoryId = -1;
+ switch (mDirectoryType) {
+ case FORWARD_LOOKUP:
+ directoryId = DirectoryId.NEARBY;
+ break;
+ case PEOPLE_LOOKUP:
+ directoryId = DirectoryId.PEOPLE;
+ break;
+ case REVERSE_LOOKUP:
+ // use null directory to be backwards compatible with old code
+ directoryId = DirectoryId.NULL;
+ break;
+ }
+
+ info.lookupUri = Contacts.CONTENT_LOOKUP_URI
+ .buildUpon()
+ .appendPath(Constants.LOOKUP_URI_ENCODED)
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId))
+ .encodedFragment(json)
+ .build();
+ }
+
+ return info;
+ } catch (JSONException e) {
+ Log.e(TAG, "Failed to build contact", e);
+ return null;
+ }
+ }
+
+ // android.provider.ContactsContract.CommonDataKinds.StructuredPostal
+ public static class Address {
+ public String formattedAddress;
+ public int type;
+ public String label;
+ public String street;
+ public String poBox;
+ public String neighborhood;
+ public String city;
+ public String region;
+ public String postCode;
+ public String country;
+
+ public static Address createFormattedHome(String address) {
+ Address a = new Address();
+ a.formattedAddress = address;
+ a.type = StructuredPostal.TYPE_HOME;
+ return a;
+ }
+
+ public JSONObject getJsonObject() throws JSONException {
+ JSONObject json = new JSONObject();
+ json.putOpt(StructuredPostal.FORMATTED_ADDRESS,
+ formattedAddress);
+ json.put(StructuredPostal.TYPE, type);
+ json.putOpt(StructuredPostal.LABEL, label);
+ json.putOpt(StructuredPostal.STREET, street);
+ json.putOpt(StructuredPostal.POBOX, poBox);
+ json.putOpt(StructuredPostal.NEIGHBORHOOD, neighborhood);
+ json.putOpt(StructuredPostal.CITY, city);
+ json.putOpt(StructuredPostal.REGION, region);
+ json.putOpt(StructuredPostal.POSTCODE, postCode);
+ json.putOpt(StructuredPostal.COUNTRY, country);
+ return json;
+ }
+
+ public Address() {}
+
+ public Address(JSONObject json) throws JSONException {
+ if (json.has(StructuredPostal.FORMATTED_ADDRESS)) {
+ formattedAddress = json.getString(StructuredPostal.FORMATTED_ADDRESS);
+ }
+ }
+
+ public String toString() {
+ return "formattedAddress: " + formattedAddress + "; " +
+ "type: " + type + "; " +
+ "label: " + label + "; " +
+ "street: " + street + "; " +
+ "poBox: " + poBox + "; " +
+ "neighborhood: " + neighborhood + "; " +
+ "city: " + city + "; " +
+ "region: " + region + "; " +
+ "postCode: " + postCode + "; " +
+ "country: " + country;
+ }
+ }
+
+ // android.provider.ContactsContract.CommonDataKinds.StructuredName
+ public static class Name {
+ public String displayName;
+ public String givenName;
+ public String familyName;
+ public String prefix;
+ public String middleName;
+ public String suffix;
+ public String phoneticGivenName;
+ public String phoneticMiddleName;
+ public String phoneticFamilyName;
+
+ public static Name createDisplayName(String displayName) {
+ Name name = new Name();
+ name.displayName = displayName;
+ return name;
+ }
+
+ public JSONObject getJsonObject() throws JSONException {
+ JSONObject json = new JSONObject();
+ json.putOpt(StructuredName.DISPLAY_NAME, displayName);
+ json.putOpt(StructuredName.GIVEN_NAME, givenName);
+ json.putOpt(StructuredName.FAMILY_NAME, familyName);
+ json.putOpt(StructuredName.PREFIX, prefix);
+ json.putOpt(StructuredName.MIDDLE_NAME, middleName);
+ json.putOpt(StructuredName.SUFFIX, suffix);
+ json.putOpt(StructuredName.PHONETIC_GIVEN_NAME,
+ phoneticGivenName);
+ json.putOpt(StructuredName.PHONETIC_MIDDLE_NAME,
+ phoneticMiddleName);
+ json.putOpt(StructuredName.PHONETIC_FAMILY_NAME,
+ phoneticFamilyName);
+ return json;
+ }
+
+ public Name(JSONObject json) throws JSONException {
+ if (json != null) {
+ displayName = json.optString(StructuredName.DISPLAY_NAME, null);
+ }
+ }
+
+ public Name() {}
+
+ public String toString() {
+ return "displayName: " + displayName + "; " +
+ "givenName: " + givenName + "; " +
+ "familyName: " + familyName + "; " +
+ "prefix: " + prefix + "; " +
+ "middleName: " + middleName + "; " +
+ "suffix: " + suffix + "; " +
+ "phoneticGivenName: " + phoneticGivenName + "; " +
+ "phoneticMiddleName: " + phoneticMiddleName + "; " +
+ "phoneticFamilyName: " + phoneticFamilyName;
+ }
+ }
+
+ // android.provider.ContactsContract.CommonDataKinds.Phone
+ public static class PhoneNumber {
+ public String number;
+ public int type;
+ public String label;
+
+ public static PhoneNumber createMainNumber(String number) {
+ PhoneNumber n = new PhoneNumber();
+ n.number = number;
+ n.type = Phone.TYPE_MAIN;
+ return n;
+ }
+
+ public JSONObject getJsonObject() throws JSONException {
+ JSONObject json = new JSONObject();
+ json.put(Phone.NUMBER, number);
+ json.put(Phone.TYPE, type);
+ json.putOpt(Phone.LABEL, label);
+ return json;
+ }
+
+ public PhoneNumber(JSONObject json) throws JSONException {
+ number = json.getString(Phone.NUMBER);
+ type = json.getInt(Phone.TYPE);
+ if (json.has(Phone.LABEL)) {
+ label = json.getString(Phone.LABEL);
+ }
+ }
+
+ public PhoneNumber() {}
+
+ public String toString() {
+ return "number: " + number + "; " +
+ "type: " + type + "; " +
+ "label: " + label;
+ }
+ }
+
+ // android.provider.ContactsContract.CommonDataKinds.Website
+ public static class WebsiteUrl {
+ public String url;
+ public int type;
+ public String label;
+
+ public static WebsiteUrl createProfile(String url) {
+ WebsiteUrl u = new WebsiteUrl();
+ u.url = url;
+ u.type = Website.TYPE_PROFILE;
+ return u;
+ }
+
+ public JSONObject getJsonObject() throws JSONException {
+ JSONObject json = new JSONObject();
+ json.put(Website.URL, url);
+ json.put(Website.TYPE, type);
+ json.putOpt(Website.LABEL, label);
+ return json;
+ }
+
+ public WebsiteUrl() {}
+
+ public WebsiteUrl(JSONObject json) throws JSONException {
+ if (json.has(Website.URL)) {
+ url = json.getString(Website.URL);
+ }
+ if (json.has(Website.TYPE)) {
+ type = json.getInt(Website.TYPE);
+ }
+ if (json.has(Website.LABEL)) {
+ label = json.getString(Website.LABEL);
+ }
+ }
+
+ public String toString() {
+ return "url: " + url + "; " +
+ "type: " + type + "; " +
+ "label: " + label;
+ }
+ }
+}