mirror of
https://github.com/zxing/zxing.git
synced 2024-11-09 20:44:03 -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.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* display-appropriate version of the contact information
|
||||
*/
|
||||
abstract String[] encode(Iterable<String> names,
|
||||
abstract String[] encode(List<String> names,
|
||||
String organization,
|
||||
Iterable<String> addresses,
|
||||
Iterable<String> phones,
|
||||
Iterable<String> emails,
|
||||
Iterable<String> urls,
|
||||
List<String> addresses,
|
||||
List<String> phones,
|
||||
List<String> phoneTypes,
|
||||
List<String> emails,
|
||||
List<String> urls,
|
||||
String note);
|
||||
|
||||
/**
|
||||
|
@ -50,37 +52,38 @@ abstract class ContactEncoder {
|
|||
return result.isEmpty() ? null : result;
|
||||
}
|
||||
|
||||
static void doAppend(StringBuilder newContents,
|
||||
StringBuilder newDisplayContents,
|
||||
String prefix,
|
||||
String value,
|
||||
Formatter fieldFormatter,
|
||||
char terminator) {
|
||||
static void append(StringBuilder newContents,
|
||||
StringBuilder newDisplayContents,
|
||||
String prefix,
|
||||
String value,
|
||||
Formatter fieldFormatter,
|
||||
char terminator) {
|
||||
String trimmed = trim(value);
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
static void doAppendUpToUnique(StringBuilder newContents,
|
||||
StringBuilder newDisplayContents,
|
||||
String prefix,
|
||||
Iterable<String> values,
|
||||
int max,
|
||||
Formatter formatter,
|
||||
Formatter fieldFormatter,
|
||||
char terminator) {
|
||||
static void appendUpToUnique(StringBuilder newContents,
|
||||
StringBuilder newDisplayContents,
|
||||
String prefix,
|
||||
List<String> values,
|
||||
int max,
|
||||
Formatter displayFormatter,
|
||||
Formatter fieldFormatter,
|
||||
char terminator) {
|
||||
if (values == null) {
|
||||
return;
|
||||
}
|
||||
int count = 0;
|
||||
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);
|
||||
if (trimmed != null && !trimmed.isEmpty() && !uniques.contains(trimmed)) {
|
||||
newContents.append(prefix).append(':').append(fieldFormatter.format(trimmed)).append(terminator);
|
||||
String display = formatter == null ? trimmed : formatter.format(trimmed);
|
||||
newContents.append(prefix).append(fieldFormatter.format(trimmed, i)).append(terminator);
|
||||
CharSequence display = displayFormatter == null ? trimmed : displayFormatter.format(trimmed, i);
|
||||
newDisplayContents.append(display).append('\n');
|
||||
if (++count == max) {
|
||||
break;
|
||||
|
|
|
@ -22,7 +22,12 @@ package com.google.zxing.client.android.encode;
|
|||
* @author Sean Owen
|
||||
*/
|
||||
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 java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
|
@ -27,72 +28,70 @@ import java.util.regex.Pattern;
|
|||
*/
|
||||
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 Pattern NOT_DIGITS = Pattern.compile("[^0-9]+");
|
||||
|
||||
@Override
|
||||
public String[] encode(Iterable<String> names,
|
||||
public String[] encode(List<String> names,
|
||||
String organization,
|
||||
Iterable<String> addresses,
|
||||
Iterable<String> phones,
|
||||
Iterable<String> emails,
|
||||
Iterable<String> urls,
|
||||
List<String> addresses,
|
||||
List<String> phones,
|
||||
List<String> phoneTypes,
|
||||
List<String> emails,
|
||||
List<String> urls,
|
||||
String note) {
|
||||
StringBuilder newContents = new StringBuilder(100);
|
||||
newContents.append("MECARD:");
|
||||
|
||||
StringBuilder newDisplayContents = new StringBuilder(100);
|
||||
appendUpToUnique(newContents, newDisplayContents, "N", names, 1, new Formatter() {
|
||||
@Override
|
||||
public String format(String source) {
|
||||
return source == null ? null : COMMA.matcher(source).replaceAll("");
|
||||
}
|
||||
});
|
||||
append(newContents, newDisplayContents, "ORG", organization);
|
||||
appendUpToUnique(newContents, newDisplayContents, "ADR", addresses, 1, null);
|
||||
appendUpToUnique(newContents, newDisplayContents, "TEL", phones, Integer.MAX_VALUE, new Formatter() {
|
||||
@Override
|
||||
public String format(String source) {
|
||||
CharSequence s = PhoneNumberUtils.formatNumber(source);
|
||||
return s == null ? null : NOT_DIGITS.matcher(s).replaceAll("");
|
||||
}
|
||||
});
|
||||
appendUpToUnique(newContents, newDisplayContents, "EMAIL", emails, Integer.MAX_VALUE, null);
|
||||
appendUpToUnique(newContents, newDisplayContents, "URL", urls, Integer.MAX_VALUE, null);
|
||||
append(newContents, newDisplayContents, "NOTE", note);
|
||||
|
||||
Formatter fieldFormatter = new MECARDFieldFormatter();
|
||||
|
||||
appendUpToUnique(newContents, newDisplayContents, "N", names, 1, new
|
||||
MECARDNameDisplayFormatter(), fieldFormatter, TERMINATOR);
|
||||
|
||||
append(newContents, newDisplayContents, "ORG", organization, fieldFormatter, TERMINATOR);
|
||||
|
||||
appendUpToUnique(newContents, newDisplayContents, "ADR", addresses, 1, null, fieldFormatter, TERMINATOR);
|
||||
|
||||
appendUpToUnique(newContents, newDisplayContents, "TEL", phones, Integer.MAX_VALUE,
|
||||
new MECARDTelDisplayFormatter(), fieldFormatter, 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(';');
|
||||
|
||||
return new String[] { newContents.toString(), newDisplayContents.toString() };
|
||||
}
|
||||
|
||||
private static void append(StringBuilder newContents,
|
||||
StringBuilder newDisplayContents,
|
||||
String prefix,
|
||||
String value) {
|
||||
doAppend(newContents, newDisplayContents, prefix, value, MECARD_FIELD_FORMATTER, TERMINATOR);
|
||||
private static class MECARDFieldFormatter implements Formatter {
|
||||
private static final Pattern RESERVED_MECARD_CHARS = Pattern.compile("([\\\\:;])");
|
||||
private static final Pattern NEWLINE = Pattern.compile("\\n");
|
||||
@Override
|
||||
public CharSequence format(CharSequence value, int index) {
|
||||
return ':' + NEWLINE.matcher(RESERVED_MECARD_CHARS.matcher(value).replaceAll("\\\\$1")).replaceAll("");
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendUpToUnique(StringBuilder newContents,
|
||||
StringBuilder newDisplayContents,
|
||||
String prefix,
|
||||
Iterable<String> values,
|
||||
int max,
|
||||
Formatter formatter) {
|
||||
doAppendUpToUnique(newContents,
|
||||
newDisplayContents,
|
||||
prefix,
|
||||
values,
|
||||
max,
|
||||
formatter,
|
||||
MECARD_FIELD_FORMATTER,
|
||||
TERMINATOR);
|
||||
|
||||
private static class MECARDTelDisplayFormatter implements Formatter {
|
||||
private static final Pattern NOT_DIGITS = Pattern.compile("[^0-9]+");
|
||||
@Override
|
||||
public CharSequence format(CharSequence value, int index) {
|
||||
return NOT_DIGITS.matcher(PhoneNumberUtils.formatNumber(value.toString())).replaceAll("");
|
||||
}
|
||||
}
|
||||
|
||||
private static class MECARDNameDisplayFormatter implements Formatter {
|
||||
private static final Pattern COMMA = Pattern.compile(",");
|
||||
@Override
|
||||
public CharSequence format(CharSequence value, int index) {
|
||||
return COMMA.matcher(value).replaceAll("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,9 +43,9 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -259,26 +259,22 @@ final class QRCodeEncoder {
|
|||
String name = bundle.getString(ContactsContract.Intents.Insert.NAME);
|
||||
String organization = bundle.getString(ContactsContract.Intents.Insert.COMPANY);
|
||||
String address = bundle.getString(ContactsContract.Intents.Insert.POSTAL);
|
||||
Collection<String> phones = new ArrayList<>(Contents.PHONE_KEYS.length);
|
||||
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
|
||||
phones.add(bundle.getString(Contents.PHONE_KEYS[x]));
|
||||
}
|
||||
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]));
|
||||
}
|
||||
List<String> phones = getAllBundleValues(bundle, Contents.PHONE_KEYS);
|
||||
List<String> phoneTypes = getAllBundleValues(bundle, Contents.PHONE_TYPE_KEYS);
|
||||
List<String> emails = getAllBundleValues(bundle, Contents.EMAIL_KEYS);
|
||||
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);
|
||||
|
||||
ContactEncoder mecardEncoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder();
|
||||
String[] encoded = mecardEncoder.encode(Collections.singleton(name),
|
||||
organization,
|
||||
Collections.singleton(address),
|
||||
phones,
|
||||
emails,
|
||||
urls,
|
||||
note);
|
||||
ContactEncoder encoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder();
|
||||
String[] encoded = encoder.encode(Collections.singletonList(name),
|
||||
organization,
|
||||
Collections.singletonList(address),
|
||||
phones,
|
||||
phoneTypes,
|
||||
emails,
|
||||
urls,
|
||||
note);
|
||||
// Make sure we've encoded at least one field.
|
||||
if (!encoded[1].isEmpty()) {
|
||||
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) {
|
||||
ContactEncoder encoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder();
|
||||
String[] encoded = encoder.encode(toIterable(contact.getNames()),
|
||||
String[] encoded = encoder.encode(toList(contact.getNames()),
|
||||
contact.getOrg(),
|
||||
toIterable(contact.getAddresses()),
|
||||
toIterable(contact.getPhoneNumbers()),
|
||||
toIterable(contact.getEmails()),
|
||||
toIterable(contact.getURLs()),
|
||||
toList(contact.getAddresses()),
|
||||
toList(contact.getPhoneNumbers()),
|
||||
null,
|
||||
toList(contact.getEmails()),
|
||||
toList(contact.getURLs()),
|
||||
null);
|
||||
// Make sure we've encoded at least one field.
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,15 @@
|
|||
|
||||
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.
|
||||
|
@ -27,65 +33,123 @@ import java.util.regex.Pattern;
|
|||
*/
|
||||
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';
|
||||
|
||||
@Override
|
||||
public String[] encode(Iterable<String> names,
|
||||
public String[] encode(List<String> names,
|
||||
String organization,
|
||||
Iterable<String> addresses,
|
||||
Iterable<String> phones,
|
||||
Iterable<String> emails,
|
||||
Iterable<String> urls,
|
||||
List<String> addresses,
|
||||
List<String> phones,
|
||||
List<String> phoneTypes,
|
||||
List<String> emails,
|
||||
List<String> urls,
|
||||
String note) {
|
||||
StringBuilder newContents = new StringBuilder(100);
|
||||
newContents.append("BEGIN:VCARD").append(TERMINATOR);
|
||||
newContents.append("VERSION:3.0").append(TERMINATOR);
|
||||
|
||||
StringBuilder newDisplayContents = new StringBuilder(100);
|
||||
appendUpToUnique(newContents, newDisplayContents, "N", names, 1, null);
|
||||
append(newContents, newDisplayContents, "ORG", organization);
|
||||
appendUpToUnique(newContents, newDisplayContents, "ADR", addresses, 1, null);
|
||||
appendUpToUnique(newContents, newDisplayContents, "TEL", phones, Integer.MAX_VALUE, new Formatter() {
|
||||
@Override
|
||||
public String format(String source) {
|
||||
return PhoneNumberUtils.formatNumber(source);
|
||||
}
|
||||
});
|
||||
appendUpToUnique(newContents, newDisplayContents, "EMAIL", emails, Integer.MAX_VALUE, null);
|
||||
appendUpToUnique(newContents, newDisplayContents, "URL", urls, Integer.MAX_VALUE, null);
|
||||
append(newContents, newDisplayContents, "NOTE", note);
|
||||
|
||||
Formatter fieldFormatter = new VCardFieldFormatter();
|
||||
|
||||
appendUpToUnique(newContents, newDisplayContents, "N", names, 1, null, fieldFormatter, TERMINATOR);
|
||||
|
||||
append(newContents, newDisplayContents, "ORG", organization, fieldFormatter, TERMINATOR);
|
||||
|
||||
appendUpToUnique(newContents, newDisplayContents, "ADR", addresses, 1, null, fieldFormatter, TERMINATOR);
|
||||
|
||||
List<Map<String,Set<String>>> phoneMetadata = buildPhoneMetadata(phones, phoneTypes);
|
||||
appendUpToUnique(newContents, newDisplayContents, "TEL", phones, Integer.MAX_VALUE,
|
||||
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);
|
||||
|
||||
return new String[] { newContents.toString(), newDisplayContents.toString() };
|
||||
}
|
||||
|
||||
private static void append(StringBuilder newContents,
|
||||
StringBuilder newDisplayContents,
|
||||
String prefix,
|
||||
String value) {
|
||||
doAppend(newContents, newDisplayContents, prefix, value, VCARD_FIELD_FORMATTER, TERMINATOR);
|
||||
|
||||
static List<Map<String,Set<String>>> buildPhoneMetadata(Collection<String> phones, List<String> phoneTypes) {
|
||||
if (phoneTypes == null || phoneTypes.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
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,
|
||||
StringBuilder newDisplayContents,
|
||||
String prefix,
|
||||
Iterable<String> values,
|
||||
int max,
|
||||
Formatter formatter) {
|
||||
doAppendUpToUnique(newContents,
|
||||
newDisplayContents,
|
||||
prefix,
|
||||
values,
|
||||
max,
|
||||
formatter,
|
||||
VCARD_FIELD_FORMATTER,
|
||||
TERMINATOR);
|
||||
|
||||
private static Integer maybeIntValue(String value) {
|
||||
try {
|
||||
return Integer.valueOf(value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String vCardPurposeLabelForAndroidType(int androidType) {
|
||||
switch (androidType) {
|
||||
case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME:
|
||||
case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK:
|
||||
case ContactsContract.CommonDataKinds.Phone.TYPE_OTHER_FAX:
|
||||
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 {
|
||||
int foundPhone = 0;
|
||||
int phonesNumberColumn = phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
|
||||
int phoneTypeColumn = phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
|
||||
while (phonesCursor.moveToNext() && foundPhone < Contents.PHONE_KEYS.length) {
|
||||
String number = phonesCursor.getString(phonesNumberColumn);
|
||||
if (number != null && !number.isEmpty()) {
|
||||
bundle.putString(Contents.PHONE_KEYS[foundPhone], massageContactData(number));
|
||||
}
|
||||
int type = phonesCursor.getInt(phoneTypeColumn);
|
||||
bundle.putInt(Contents.PHONE_TYPE_KEYS[foundPhone], type);
|
||||
foundPhone++;
|
||||
}
|
||||
} finally {
|
||||
|
|
Loading…
Reference in a new issue