mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
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:
parent
83277b92eb
commit
dfd6fe71c2
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue