Overhaul contact encoding in Android; encode phone type too

git-svn-id: https://zxing.googlecode.com/svn/trunk@3012 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2014-01-07 22:00:38 +00:00
parent 83277b92eb
commit dfd6fe71c2
8 changed files with 382 additions and 150 deletions

View file

@ -18,6 +18,7 @@ package com.google.zxing.client.android.encode;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
/** /**
* Implementations encode according to some scheme for encoding contact information, like VCard or * Implementations encode according to some scheme for encoding contact information, like VCard or
@ -31,12 +32,13 @@ abstract class ContactEncoder {
* @return first, the best effort encoding of all data in the appropriate format; second, a * @return first, the best effort encoding of all data in the appropriate format; second, a
* display-appropriate version of the contact information * display-appropriate version of the contact information
*/ */
abstract String[] encode(Iterable<String> names, abstract String[] encode(List<String> names,
String organization, String organization,
Iterable<String> addresses, List<String> addresses,
Iterable<String> phones, List<String> phones,
Iterable<String> emails, List<String> phoneTypes,
Iterable<String> urls, List<String> emails,
List<String> urls,
String note); String note);
/** /**
@ -50,37 +52,38 @@ abstract class ContactEncoder {
return result.isEmpty() ? null : result; return result.isEmpty() ? null : result;
} }
static void doAppend(StringBuilder newContents, static void append(StringBuilder newContents,
StringBuilder newDisplayContents, StringBuilder newDisplayContents,
String prefix, String prefix,
String value, String value,
Formatter fieldFormatter, Formatter fieldFormatter,
char terminator) { char terminator) {
String trimmed = trim(value); String trimmed = trim(value);
if (trimmed != null) { if (trimmed != null) {
newContents.append(prefix).append(':').append(fieldFormatter.format(trimmed)).append(terminator); newContents.append(prefix).append(fieldFormatter.format(trimmed, 0)).append(terminator);
newDisplayContents.append(trimmed).append('\n'); newDisplayContents.append(trimmed).append('\n');
} }
} }
static void doAppendUpToUnique(StringBuilder newContents, static void appendUpToUnique(StringBuilder newContents,
StringBuilder newDisplayContents, StringBuilder newDisplayContents,
String prefix, String prefix,
Iterable<String> values, List<String> values,
int max, int max,
Formatter formatter, Formatter displayFormatter,
Formatter fieldFormatter, Formatter fieldFormatter,
char terminator) { char terminator) {
if (values == null) { if (values == null) {
return; return;
} }
int count = 0; int count = 0;
Collection<String> uniques = new HashSet<>(2); Collection<String> uniques = new HashSet<>(2);
for (String value : values) { for (int i = 0; i < values.size(); i++) {
String value = values.get(i);
String trimmed = trim(value); String trimmed = trim(value);
if (trimmed != null && !trimmed.isEmpty() && !uniques.contains(trimmed)) { if (trimmed != null && !trimmed.isEmpty() && !uniques.contains(trimmed)) {
newContents.append(prefix).append(':').append(fieldFormatter.format(trimmed)).append(terminator); newContents.append(prefix).append(fieldFormatter.format(trimmed, i)).append(terminator);
String display = formatter == null ? trimmed : formatter.format(trimmed); CharSequence display = displayFormatter == null ? trimmed : displayFormatter.format(trimmed, i);
newDisplayContents.append(display).append('\n'); newDisplayContents.append(display).append('\n');
if (++count == max) { if (++count == max) {
break; break;

View file

@ -22,7 +22,12 @@ package com.google.zxing.client.android.encode;
* @author Sean Owen * @author Sean Owen
*/ */
interface Formatter { interface Formatter {
String format(String source); /**
* @param value value to format
* @param index index of value in a list of values to be formatted
* @return formatted value
*/
CharSequence format(CharSequence value, int index);
} }

View file

@ -18,6 +18,7 @@ package com.google.zxing.client.android.encode;
import android.telephony.PhoneNumberUtils; import android.telephony.PhoneNumberUtils;
import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
@ -27,72 +28,70 @@ import java.util.regex.Pattern;
*/ */
final class MECARDContactEncoder extends ContactEncoder { final class MECARDContactEncoder extends ContactEncoder {
private static final Pattern RESERVED_MECARD_CHARS = Pattern.compile("([\\\\:;])");
private static final Pattern NEWLINE = Pattern.compile("\\n");
private static final Pattern COMMA = Pattern.compile(",");
private static final Formatter MECARD_FIELD_FORMATTER = new Formatter() {
@Override
public String format(String source) {
return NEWLINE.matcher(RESERVED_MECARD_CHARS.matcher(source).replaceAll("\\\\$1")).replaceAll("");
}
};
private static final char TERMINATOR = ';'; private static final char TERMINATOR = ';';
private static final Pattern NOT_DIGITS = Pattern.compile("[^0-9]+");
@Override @Override
public String[] encode(Iterable<String> names, public String[] encode(List<String> names,
String organization, String organization,
Iterable<String> addresses, List<String> addresses,
Iterable<String> phones, List<String> phones,
Iterable<String> emails, List<String> phoneTypes,
Iterable<String> urls, List<String> emails,
List<String> urls,
String note) { String note) {
StringBuilder newContents = new StringBuilder(100); StringBuilder newContents = new StringBuilder(100);
newContents.append("MECARD:"); newContents.append("MECARD:");
StringBuilder newDisplayContents = new StringBuilder(100); StringBuilder newDisplayContents = new StringBuilder(100);
appendUpToUnique(newContents, newDisplayContents, "N", names, 1, new Formatter() {
@Override Formatter fieldFormatter = new MECARDFieldFormatter();
public String format(String source) {
return source == null ? null : COMMA.matcher(source).replaceAll(""); appendUpToUnique(newContents, newDisplayContents, "N", names, 1, new
} MECARDNameDisplayFormatter(), fieldFormatter, TERMINATOR);
});
append(newContents, newDisplayContents, "ORG", organization); append(newContents, newDisplayContents, "ORG", organization, fieldFormatter, TERMINATOR);
appendUpToUnique(newContents, newDisplayContents, "ADR", addresses, 1, null);
appendUpToUnique(newContents, newDisplayContents, "TEL", phones, Integer.MAX_VALUE, new Formatter() { appendUpToUnique(newContents, newDisplayContents, "ADR", addresses, 1, null, fieldFormatter, TERMINATOR);
@Override
public String format(String source) { appendUpToUnique(newContents, newDisplayContents, "TEL", phones, Integer.MAX_VALUE,
CharSequence s = PhoneNumberUtils.formatNumber(source); new MECARDTelDisplayFormatter(), fieldFormatter, TERMINATOR);
return s == null ? null : NOT_DIGITS.matcher(s).replaceAll("");
} appendUpToUnique(newContents, newDisplayContents, "EMAIL", emails, Integer.MAX_VALUE, null,
}); fieldFormatter, TERMINATOR);
appendUpToUnique(newContents, newDisplayContents, "EMAIL", emails, Integer.MAX_VALUE, null);
appendUpToUnique(newContents, newDisplayContents, "URL", urls, Integer.MAX_VALUE, null); appendUpToUnique(newContents, newDisplayContents, "URL", urls, Integer.MAX_VALUE, null,
append(newContents, newDisplayContents, "NOTE", note); fieldFormatter, TERMINATOR);
append(newContents, newDisplayContents, "NOTE", note, fieldFormatter, TERMINATOR);
newContents.append(';'); newContents.append(';');
return new String[] { newContents.toString(), newDisplayContents.toString() }; return new String[] { newContents.toString(), newDisplayContents.toString() };
} }
private static void append(StringBuilder newContents, private static class MECARDFieldFormatter implements Formatter {
StringBuilder newDisplayContents, private static final Pattern RESERVED_MECARD_CHARS = Pattern.compile("([\\\\:;])");
String prefix, private static final Pattern NEWLINE = Pattern.compile("\\n");
String value) { @Override
doAppend(newContents, newDisplayContents, prefix, value, MECARD_FIELD_FORMATTER, TERMINATOR); public CharSequence format(CharSequence value, int index) {
return ':' + NEWLINE.matcher(RESERVED_MECARD_CHARS.matcher(value).replaceAll("\\\\$1")).replaceAll("");
}
} }
private static void appendUpToUnique(StringBuilder newContents, private static class MECARDTelDisplayFormatter implements Formatter {
StringBuilder newDisplayContents, private static final Pattern NOT_DIGITS = Pattern.compile("[^0-9]+");
String prefix, @Override
Iterable<String> values, public CharSequence format(CharSequence value, int index) {
int max, return NOT_DIGITS.matcher(PhoneNumberUtils.formatNumber(value.toString())).replaceAll("");
Formatter formatter) { }
doAppendUpToUnique(newContents, }
newDisplayContents,
prefix, private static class MECARDNameDisplayFormatter implements Formatter {
values, private static final Pattern COMMA = Pattern.compile(",");
max, @Override
formatter, public CharSequence format(CharSequence value, int index) {
MECARD_FIELD_FORMATTER, return COMMA.matcher(value).replaceAll("");
TERMINATOR); }
} }
} }

View file

@ -43,9 +43,9 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -259,26 +259,22 @@ final class QRCodeEncoder {
String name = bundle.getString(ContactsContract.Intents.Insert.NAME); String name = bundle.getString(ContactsContract.Intents.Insert.NAME);
String organization = bundle.getString(ContactsContract.Intents.Insert.COMPANY); String organization = bundle.getString(ContactsContract.Intents.Insert.COMPANY);
String address = bundle.getString(ContactsContract.Intents.Insert.POSTAL); String address = bundle.getString(ContactsContract.Intents.Insert.POSTAL);
Collection<String> phones = new ArrayList<>(Contents.PHONE_KEYS.length); List<String> phones = getAllBundleValues(bundle, Contents.PHONE_KEYS);
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) { List<String> phoneTypes = getAllBundleValues(bundle, Contents.PHONE_TYPE_KEYS);
phones.add(bundle.getString(Contents.PHONE_KEYS[x])); List<String> emails = getAllBundleValues(bundle, Contents.EMAIL_KEYS);
}
Collection<String> emails = new ArrayList<>(Contents.EMAIL_KEYS.length);
for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
emails.add(bundle.getString(Contents.EMAIL_KEYS[x]));
}
String url = bundle.getString(Contents.URL_KEY); String url = bundle.getString(Contents.URL_KEY);
Iterable<String> urls = url == null ? null : Collections.singletonList(url); List<String> urls = url == null ? null : Collections.singletonList(url);
String note = bundle.getString(Contents.NOTE_KEY); String note = bundle.getString(Contents.NOTE_KEY);
ContactEncoder mecardEncoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder(); ContactEncoder encoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder();
String[] encoded = mecardEncoder.encode(Collections.singleton(name), String[] encoded = encoder.encode(Collections.singletonList(name),
organization, organization,
Collections.singleton(address), Collections.singletonList(address),
phones, phones,
emails, phoneTypes,
urls, emails,
note); urls,
note);
// Make sure we've encoded at least one field. // Make sure we've encoded at least one field.
if (!encoded[1].isEmpty()) { if (!encoded[1].isEmpty()) {
contents = encoded[0]; contents = encoded[0];
@ -307,14 +303,24 @@ final class QRCodeEncoder {
} }
} }
private static List<String> getAllBundleValues(Bundle bundle, String[] keys) {
List<String> values = new ArrayList<>(keys.length);
for (String key : keys) {
Object value = bundle.get(key);
values.add(value == null ? null : value.toString());
}
return values;
}
private void encodeQRCodeContents(AddressBookParsedResult contact) { private void encodeQRCodeContents(AddressBookParsedResult contact) {
ContactEncoder encoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder(); ContactEncoder encoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder();
String[] encoded = encoder.encode(toIterable(contact.getNames()), String[] encoded = encoder.encode(toList(contact.getNames()),
contact.getOrg(), contact.getOrg(),
toIterable(contact.getAddresses()), toList(contact.getAddresses()),
toIterable(contact.getPhoneNumbers()), toList(contact.getPhoneNumbers()),
toIterable(contact.getEmails()), null,
toIterable(contact.getURLs()), toList(contact.getEmails()),
toList(contact.getURLs()),
null); null);
// Make sure we've encoded at least one field. // Make sure we've encoded at least one field.
if (!encoded[1].isEmpty()) { if (!encoded[1].isEmpty()) {
@ -324,7 +330,7 @@ final class QRCodeEncoder {
} }
} }
private static Iterable<String> toIterable(String[] values) { private static List<String> toList(String[] values) {
return values == null ? null : Arrays.asList(values); return values == null ? null : Arrays.asList(values);
} }

View file

@ -16,9 +16,15 @@
package com.google.zxing.client.android.encode; package com.google.zxing.client.android.encode;
import android.telephony.PhoneNumberUtils; import android.provider.ContactsContract;
import java.util.regex.Pattern; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* Encodes contact information according to the vCard format. * Encodes contact information according to the vCard format.
@ -27,65 +33,123 @@ import java.util.regex.Pattern;
*/ */
final class VCardContactEncoder extends ContactEncoder { final class VCardContactEncoder extends ContactEncoder {
private static final Pattern RESERVED_VCARD_CHARS = Pattern.compile("([\\\\,;])");
private static final Pattern NEWLINE = Pattern.compile("\\n");
private static final Formatter VCARD_FIELD_FORMATTER = new Formatter() {
@Override
public String format(String source) {
return NEWLINE.matcher(RESERVED_VCARD_CHARS.matcher(source).replaceAll("\\\\$1")).replaceAll("");
}
};
private static final char TERMINATOR = '\n'; private static final char TERMINATOR = '\n';
@Override @Override
public String[] encode(Iterable<String> names, public String[] encode(List<String> names,
String organization, String organization,
Iterable<String> addresses, List<String> addresses,
Iterable<String> phones, List<String> phones,
Iterable<String> emails, List<String> phoneTypes,
Iterable<String> urls, List<String> emails,
List<String> urls,
String note) { String note) {
StringBuilder newContents = new StringBuilder(100); StringBuilder newContents = new StringBuilder(100);
newContents.append("BEGIN:VCARD").append(TERMINATOR); newContents.append("BEGIN:VCARD").append(TERMINATOR);
newContents.append("VERSION:3.0").append(TERMINATOR); newContents.append("VERSION:3.0").append(TERMINATOR);
StringBuilder newDisplayContents = new StringBuilder(100); StringBuilder newDisplayContents = new StringBuilder(100);
appendUpToUnique(newContents, newDisplayContents, "N", names, 1, null);
append(newContents, newDisplayContents, "ORG", organization); Formatter fieldFormatter = new VCardFieldFormatter();
appendUpToUnique(newContents, newDisplayContents, "ADR", addresses, 1, null);
appendUpToUnique(newContents, newDisplayContents, "TEL", phones, Integer.MAX_VALUE, new Formatter() { appendUpToUnique(newContents, newDisplayContents, "N", names, 1, null, fieldFormatter, TERMINATOR);
@Override
public String format(String source) { append(newContents, newDisplayContents, "ORG", organization, fieldFormatter, TERMINATOR);
return PhoneNumberUtils.formatNumber(source);
} appendUpToUnique(newContents, newDisplayContents, "ADR", addresses, 1, null, fieldFormatter, TERMINATOR);
});
appendUpToUnique(newContents, newDisplayContents, "EMAIL", emails, Integer.MAX_VALUE, null); List<Map<String,Set<String>>> phoneMetadata = buildPhoneMetadata(phones, phoneTypes);
appendUpToUnique(newContents, newDisplayContents, "URL", urls, Integer.MAX_VALUE, null); appendUpToUnique(newContents, newDisplayContents, "TEL", phones, Integer.MAX_VALUE,
append(newContents, newDisplayContents, "NOTE", note); new VCardTelDisplayFormatter(phoneMetadata),
new VCardFieldFormatter(phoneMetadata), TERMINATOR);
appendUpToUnique(newContents, newDisplayContents, "EMAIL", emails, Integer.MAX_VALUE, null,
fieldFormatter, TERMINATOR);
appendUpToUnique(newContents, newDisplayContents, "URL", urls, Integer.MAX_VALUE, null,
fieldFormatter, TERMINATOR);
append(newContents, newDisplayContents, "NOTE", note, fieldFormatter, TERMINATOR);
newContents.append("END:VCARD").append(TERMINATOR); newContents.append("END:VCARD").append(TERMINATOR);
return new String[] { newContents.toString(), newDisplayContents.toString() }; return new String[] { newContents.toString(), newDisplayContents.toString() };
} }
private static void append(StringBuilder newContents, static List<Map<String,Set<String>>> buildPhoneMetadata(Collection<String> phones, List<String> phoneTypes) {
StringBuilder newDisplayContents, if (phoneTypes == null || phoneTypes.isEmpty()) {
String prefix, return null;
String value) { }
doAppend(newContents, newDisplayContents, prefix, value, VCARD_FIELD_FORMATTER, TERMINATOR); List<Map<String,Set<String>>> metadataForIndex = new ArrayList<>();
for (int i = 0; i < phones.size(); i++) {
if (phoneTypes.size() <= i) {
metadataForIndex.add(null);
} else {
Map<String,Set<String>> metadata = new HashMap<>();
metadataForIndex.add(metadata);
Set<String> typeTokens = new HashSet<>();
metadata.put("TYPE", typeTokens);
String typeString = phoneTypes.get(i);
Integer androidType = maybeIntValue(typeString);
if (androidType == null) {
typeTokens.add(typeString);
} else {
String purpose = vCardPurposeLabelForAndroidType(androidType);
String context = vCardContextLabelForAndroidType(androidType);
if (purpose != null) {
typeTokens.add(purpose);
}
if (context != null) {
typeTokens.add(context);
}
}
}
}
return metadataForIndex;
} }
private static void appendUpToUnique(StringBuilder newContents, private static Integer maybeIntValue(String value) {
StringBuilder newDisplayContents, try {
String prefix, return Integer.valueOf(value);
Iterable<String> values, } catch (NumberFormatException nfe) {
int max, return null;
Formatter formatter) { }
doAppendUpToUnique(newContents, }
newDisplayContents,
prefix, private static String vCardPurposeLabelForAndroidType(int androidType) {
values, switch (androidType) {
max, case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME:
formatter, case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK:
VCARD_FIELD_FORMATTER, case ContactsContract.CommonDataKinds.Phone.TYPE_OTHER_FAX:
TERMINATOR); return "fax";
case ContactsContract.CommonDataKinds.Phone.TYPE_PAGER:
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_PAGER:
return "pager";
case ContactsContract.CommonDataKinds.Phone.TYPE_TTY_TDD:
return "textphone";
case ContactsContract.CommonDataKinds.Phone.TYPE_MMS:
return "text";
default:
return null;
}
}
private static String vCardContextLabelForAndroidType(int androidType) {
switch (androidType) {
case ContactsContract.CommonDataKinds.Phone.TYPE_HOME:
case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE:
case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME:
case ContactsContract.CommonDataKinds.Phone.TYPE_PAGER:
return "home";
case ContactsContract.CommonDataKinds.Phone.TYPE_COMPANY_MAIN:
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK:
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE:
case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK:
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_PAGER:
return "work";
default:
return null;
}
} }
} }

View file

@ -0,0 +1,79 @@
/*
* Copyright (C) 2014 ZXing authors
*
* 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.google.zxing.client.android.encode;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
/**
* @author Sean Owen
*/
final class VCardFieldFormatter implements Formatter {
private static final Pattern RESERVED_VCARD_CHARS = Pattern.compile("([\\\\,;])");
private static final Pattern NEWLINE = Pattern.compile("\\n");
private final List<Map<String,Set<String>>> metadataForIndex;
VCardFieldFormatter() {
this(null);
}
VCardFieldFormatter(List<Map<String,Set<String>>> metadataForIndex) {
this.metadataForIndex = metadataForIndex;
}
@Override
public CharSequence format(CharSequence value, int index) {
value = RESERVED_VCARD_CHARS.matcher(value).replaceAll("\\\\$1");
value = NEWLINE.matcher(value).replaceAll("");
Map<String,Set<String>> metadata =
metadataForIndex == null || metadataForIndex.size() <= index ? null : metadataForIndex.get(index);
value = formatMetadata(value, metadata);
return value;
}
private static CharSequence formatMetadata(CharSequence value, Map<String,Set<String>> metadata) {
StringBuilder withMetadata = new StringBuilder();
if (metadata != null) {
for (Map.Entry<String,Set<String>> metadatum : metadata.entrySet()) {
Set<String> values = metadatum.getValue();
if (values == null || values.isEmpty()) {
continue;
}
withMetadata.append(';').append(metadatum.getKey()).append('=');
if (values.size() > 1) {
withMetadata.append('"');
}
Iterator<String> valuesIt = values.iterator();
withMetadata.append(valuesIt.next());
while (valuesIt.hasNext()) {
withMetadata.append(',').append(valuesIt.next());
}
if (values.size() > 1) {
withMetadata.append('"');
}
}
}
withMetadata.append(':').append(value);
return withMetadata;
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright (C) 2014 ZXing authors
*
* 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.google.zxing.client.android.encode;
import android.telephony.PhoneNumberUtils;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Sean Owen
*/
final class VCardTelDisplayFormatter implements Formatter {
private final List<Map<String,Set<String>>> metadataForIndex;
VCardTelDisplayFormatter() {
this(null);
}
VCardTelDisplayFormatter(List<Map<String,Set<String>>> metadataForIndex) {
this.metadataForIndex = metadataForIndex;
}
@Override
public CharSequence format(CharSequence value, int index) {
value = PhoneNumberUtils.formatNumber(value.toString());
Map<String,Set<String>> metadata =
metadataForIndex == null || metadataForIndex.size() <= index ? null : metadataForIndex.get(index);
value = formatMetadata(value, metadata);
return value;
}
private static CharSequence formatMetadata(CharSequence value, Map<String,Set<String>> metadata) {
if (metadata == null || metadata.isEmpty()) {
return value;
}
StringBuilder withMetadata = new StringBuilder();
for (Map.Entry<String,Set<String>> metadatum : metadata.entrySet()) {
Set<String> values = metadatum.getValue();
if (values == null || values.isEmpty()) {
continue;
}
Iterator<String> valuesIt = values.iterator();
withMetadata.append(valuesIt.next());
while (valuesIt.hasNext()) {
withMetadata.append(',').append(valuesIt.next());
}
}
if (withMetadata.length() > 0) {
withMetadata.append(' ');
}
withMetadata.append(value);
return withMetadata;
}
}

View file

@ -220,11 +220,14 @@ public final class ShareActivity extends Activity {
try { try {
int foundPhone = 0; int foundPhone = 0;
int phonesNumberColumn = phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); int phonesNumberColumn = phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
int phoneTypeColumn = phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
while (phonesCursor.moveToNext() && foundPhone < Contents.PHONE_KEYS.length) { while (phonesCursor.moveToNext() && foundPhone < Contents.PHONE_KEYS.length) {
String number = phonesCursor.getString(phonesNumberColumn); String number = phonesCursor.getString(phonesNumberColumn);
if (number != null && !number.isEmpty()) { if (number != null && !number.isEmpty()) {
bundle.putString(Contents.PHONE_KEYS[foundPhone], massageContactData(number)); bundle.putString(Contents.PHONE_KEYS[foundPhone], massageContactData(number));
} }
int type = phonesCursor.getInt(phoneTypeColumn);
bundle.putInt(Contents.PHONE_TYPE_KEYS[foundPhone], type);
foundPhone++; foundPhone++;
} }
} finally { } finally {