mirror of
https://github.com/zxing/zxing.git
synced 2024-11-10 04:54:04 -08:00
Issue 918 Add MECARD/vCard switch after factoring out and tidying some of the contact encoding logic
git-svn-id: https://zxing.googlecode.com/svn/trunk@2097 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
41a450d25e
commit
c77baf34a8
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">إرسال السجل</string>
|
||||
<string name="history_title">سجل</string>
|
||||
<string name="menu_about">حول</string>
|
||||
<string name="menu_encode_mecard">استخدام MECARD</string>
|
||||
<string name="menu_encode_vcard">استخدام vCard</string>
|
||||
<string name="menu_help">تعليمات</string>
|
||||
<string name="menu_history">سجل</string>
|
||||
<string name="menu_settings">إعدادات</string>
|
||||
|
@ -128,7 +130,7 @@
|
|||
<string name="sbc_name">البحث في Google Book</string>
|
||||
<string name="share_name">مشاركة عبر الرمز الشريطي</string>
|
||||
<string name="title_about">إصدار ماسح الرمز الشريطي</string>
|
||||
<string name="wifi_changing_network">طلب الاتصال بالشبكة\u2026</string>
|
||||
<string name="wifi_changing_network">طلب الاتصال بالشبكة\u2026</string>
|
||||
<string name="wifi_ssid_label">اسم الشبكة</string>
|
||||
<string name="wifi_type_label">نوع</string>
|
||||
<string name="zxing_url">http://code.google.com/p/zxing</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Изпрати историята</string>
|
||||
<string name="history_title">История</string>
|
||||
<string name="menu_about">Относно</string>
|
||||
<string name="menu_encode_mecard">Използвайте MECARD</string>
|
||||
<string name="menu_encode_vcard">Използвайте vCard</string>
|
||||
<string name="menu_help">Помощ</string>
|
||||
<string name="menu_history">История</string>
|
||||
<string name="menu_settings">Настройки</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Envia l\'historial</string>
|
||||
<string name="history_title">Historial</string>
|
||||
<string name="menu_about">Quant a</string>
|
||||
<string name="menu_encode_mecard">Utilitza MECARD</string>
|
||||
<string name="menu_encode_vcard">Utilitza vCard</string>
|
||||
<string name="menu_help">Ajuda</string>
|
||||
<string name="menu_history">Historial</string>
|
||||
<string name="menu_settings">Configuració</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Poslat historii</string>
|
||||
<string name="history_title">Historie</string>
|
||||
<string name="menu_about">O</string>
|
||||
<string name="menu_encode_mecard">Použití MECARD</string>
|
||||
<string name="menu_encode_vcard">Použití vCard</string>
|
||||
<string name="menu_help">Pomoc!</string>
|
||||
<string name="menu_history">Historie</string>
|
||||
<string name="menu_settings">Nastavení</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Send historik</string>
|
||||
<string name="history_title">Historik</string>
|
||||
<string name="menu_about">Om</string>
|
||||
<string name="menu_encode_mecard">Brug MECARD</string>
|
||||
<string name="menu_encode_vcard">Brug vCard</string>
|
||||
<string name="menu_help">Hjælp</string>
|
||||
<string name="menu_history">Historik</string>
|
||||
<string name="menu_settings">Indstillinger</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Historie senden</string>
|
||||
<string name="history_title">Historie</string>
|
||||
<string name="menu_about">Info</string>
|
||||
<string name="menu_encode_mecard">Verwenden Sie MECARD</string>
|
||||
<string name="menu_encode_vcard">Verwenden Sie vCard</string>
|
||||
<string name="menu_help">Hilfe</string>
|
||||
<string name="menu_history">Historie</string>
|
||||
<string name="menu_settings">Einstellungen</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Αποστολή ιστορικού</string>
|
||||
<string name="history_title">Ιστορικό</string>
|
||||
<string name="menu_about">Σχετικά</string>
|
||||
<string name="menu_encode_mecard">Χρησιμοποιήστε MECARD</string>
|
||||
<string name="menu_encode_vcard">Χρησιμοποιήστε vCard</string>
|
||||
<string name="menu_help">Βοήθεια</string>
|
||||
<string name="menu_history">Ιστορικό</string>
|
||||
<string name="menu_settings">Ρυθμίσεις</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Enviar historial</string>
|
||||
<string name="history_title">Historial</string>
|
||||
<string name="menu_about">Acerca de</string>
|
||||
<string name="menu_encode_mecard">Usar MECARD</string>
|
||||
<string name="menu_encode_vcard">Usar vCard</string>
|
||||
<string name="menu_help">Ayuda</string>
|
||||
<string name="menu_history">Historial</string>
|
||||
<string name="menu_settings">Configuración</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Lähetä historia</string>
|
||||
<string name="history_title">Historia</string>
|
||||
<string name="menu_about">Tietoja</string>
|
||||
<string name="menu_encode_mecard">Käytä MECARD</string>
|
||||
<string name="menu_encode_vcard">Käytä vCard</string>
|
||||
<string name="menu_help">Apua</string>
|
||||
<string name="menu_history">Historia</string>
|
||||
<string name="menu_settings">Asetukset</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Envoyer historique</string>
|
||||
<string name="history_title">Historique</string>
|
||||
<string name="menu_about">A propos</string>
|
||||
<string name="menu_encode_mecard">Utilisez MECARD</string>
|
||||
<string name="menu_encode_vcard">Utilisez vCard</string>
|
||||
<string name="menu_help">Aide</string>
|
||||
<string name="menu_history">Historique</string>
|
||||
<string name="menu_settings">Paramètres</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">שלח היסטוריה</string>
|
||||
<string name="history_title">היסטוריה</string>
|
||||
<string name="menu_about">אודות</string>
|
||||
<string name="menu_encode_mecard">השתמש MECARD</string>
|
||||
<string name="menu_encode_vcard">השתמש vCard</string>
|
||||
<string name="menu_help">עזרה</string>
|
||||
<string name="menu_history">היסטוריה</string>
|
||||
<string name="menu_settings">הגדרות</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">इतिहास भेजें</string>
|
||||
<string name="history_title">इतिहास</string>
|
||||
<string name="menu_about">के बारे में</string>
|
||||
<string name="menu_encode_mecard">MECARD का प्रयोग करें</string>
|
||||
<string name="menu_encode_vcard">vCard का प्रयोग करें</string>
|
||||
<string name="menu_help">मदद</string>
|
||||
<string name="menu_history">इतिहास</string>
|
||||
<string name="menu_settings">सेटिंग्स</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Előzmények küldése</string>
|
||||
<string name="history_title">Előzmények</string>
|
||||
<string name="menu_about">Rólunk</string>
|
||||
<string name="menu_encode_mecard">Használja MECARD</string>
|
||||
<string name="menu_encode_vcard">Használja vCard</string>
|
||||
<string name="menu_help">Súgó</string>
|
||||
<string name="menu_history">Előzmények</string>
|
||||
<string name="menu_settings">Beállítások</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Kirim riwayat</string>
|
||||
<string name="history_title">Riwayat</string>
|
||||
<string name="menu_about">Tentang</string>
|
||||
<string name="menu_encode_mecard">Gunakan MECARD</string>
|
||||
<string name="menu_encode_vcard">Gunakan vCard</string>
|
||||
<string name="menu_help">Bantuan</string>
|
||||
<string name="menu_history">Riwayat</string>
|
||||
<string name="menu_settings">Pengaturan</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Invia cronologia</string>
|
||||
<string name="history_title">Cronologia</string>
|
||||
<string name="menu_about">Info</string>
|
||||
<string name="menu_encode_mecard">Usa MECARD</string>
|
||||
<string name="menu_encode_vcard">Usa vCard</string>
|
||||
<string name="menu_help">Aiuto</string>
|
||||
<string name="menu_history">Cronologia</string>
|
||||
<string name="menu_settings">Impostazioni</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">שלח היסטוריה</string>
|
||||
<string name="history_title">היסטוריה</string>
|
||||
<string name="menu_about">אודות</string>
|
||||
<string name="menu_encode_mecard">השתמש MECARD</string>
|
||||
<string name="menu_encode_vcard">השתמש vCard</string>
|
||||
<string name="menu_help">עזרה</string>
|
||||
<string name="menu_history">היסטוריה</string>
|
||||
<string name="menu_settings">הגדרות</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">履歴を送信</string>
|
||||
<string name="history_title">履歴</string>
|
||||
<string name="menu_about">詳細</string>
|
||||
<string name="menu_encode_mecard">MECARDを使用してください</string>
|
||||
<string name="menu_encode_vcard">vCardを使用してください</string>
|
||||
<string name="menu_help">ヘルプ</string>
|
||||
<string name="menu_history">履歴</string>
|
||||
<string name="menu_settings">設定</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">기록 보내기</string>
|
||||
<string name="history_title">기록</string>
|
||||
<string name="menu_about">정보</string>
|
||||
<string name="menu_encode_mecard">MECARD를 사용하여</string>
|
||||
<string name="menu_encode_vcard">vCard를 사용하여</string>
|
||||
<string name="menu_help">도움말</string>
|
||||
<string name="menu_history">기록</string>
|
||||
<string name="menu_settings">설정</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Verzend geschiedenis</string>
|
||||
<string name="history_title">Geschiedenis</string>
|
||||
<string name="menu_about">Over</string>
|
||||
<string name="menu_encode_mecard">Gebruik MECARD</string>
|
||||
<string name="menu_encode_vcard">Gebruik vCard</string>
|
||||
<string name="menu_help">Help</string>
|
||||
<string name="menu_history">Geschiedenis</string>
|
||||
<string name="menu_settings">Instellingen</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Wyślij historię</string>
|
||||
<string name="history_title">Historia</string>
|
||||
<string name="menu_about">O aplikacji</string>
|
||||
<string name="menu_encode_mecard">Użyj MECARD</string>
|
||||
<string name="menu_encode_vcard">Użyj vCard</string>
|
||||
<string name="menu_help">Pomoc</string>
|
||||
<string name="menu_history">Historia</string>
|
||||
<string name="menu_settings">Ustawienia</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Enviar histórico</string>
|
||||
<string name="history_title">Histórico</string>
|
||||
<string name="menu_about">Sobre</string>
|
||||
<string name="menu_encode_mecard">Usar MECARD</string>
|
||||
<string name="menu_encode_vcard">Usar vCard</string>
|
||||
<string name="menu_help">Ajuda</string>
|
||||
<string name="menu_history">Histórico</string>
|
||||
<string name="menu_settings">Definições</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Отправить историю</string>
|
||||
<string name="history_title">История</string>
|
||||
<string name="menu_about">О программе</string>
|
||||
<string name="menu_encode_mecard">Используйте MECARD</string>
|
||||
<string name="menu_encode_vcard">Используйте vCard</string>
|
||||
<string name="menu_help">Помощь</string>
|
||||
<string name="menu_history">История</string>
|
||||
<string name="menu_settings">Настройки</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Poslať históriu</string>
|
||||
<string name="history_title">História</string>
|
||||
<string name="menu_about">O programe</string>
|
||||
<string name="menu_encode_mecard">Použitie MECARD</string>
|
||||
<string name="menu_encode_vcard">Použitie vCard</string>
|
||||
<string name="menu_help">Nápoveda</string>
|
||||
<string name="menu_history">História</string>
|
||||
<string name="menu_settings">Nastavenia</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Pošlji zgodovino</string>
|
||||
<string name="history_title">Zgodovina</string>
|
||||
<string name="menu_about">O programu</string>
|
||||
<string name="menu_encode_mecard">Uporaba MECARD</string>
|
||||
<string name="menu_encode_vcard">Uporaba vCard</string>
|
||||
<string name="menu_help">Pomoč</string>
|
||||
<string name="menu_history">Zgodovina</string>
|
||||
<string name="menu_settings">Nastavitve</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Skicka historik</string>
|
||||
<string name="history_title">Historik</string>
|
||||
<string name="menu_about">Om</string>
|
||||
<string name="menu_encode_mecard">Använd MECARD</string>
|
||||
<string name="menu_encode_vcard">Använd vCard</string>
|
||||
<string name="menu_help">Hjälp</string>
|
||||
<string name="menu_history">Historik</string>
|
||||
<string name="menu_settings">Inställningar</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Geçmişi gönder</string>
|
||||
<string name="history_title">Geçmiş</string>
|
||||
<string name="menu_about">Hakkında</string>
|
||||
<string name="menu_encode_mecard">MECARD kullanın</string>
|
||||
<string name="menu_encode_vcard">VCard kullanın</string>
|
||||
<string name="menu_help">Yardım</string>
|
||||
<string name="menu_history">Geçmiş</string>
|
||||
<string name="menu_settings">Ayarlar</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">发送历史</string>
|
||||
<string name="history_title">历史</string>
|
||||
<string name="menu_about">关于</string>
|
||||
<string name="menu_encode_mecard">使用MECARD</string>
|
||||
<string name="menu_encode_vcard">使用vCard</string>
|
||||
<string name="menu_help">帮助</string>
|
||||
<string name="menu_history">历史</string>
|
||||
<string name="menu_settings">设置</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">發送紀錄</string>
|
||||
<string name="history_title">紀錄</string>
|
||||
<string name="menu_about">關於</string>
|
||||
<string name="menu_encode_mecard">使用MECARD</string>
|
||||
<string name="menu_encode_vcard">使用vCard</string>
|
||||
<string name="menu_help">說明</string>
|
||||
<string name="menu_history">紀錄</string>
|
||||
<string name="menu_settings">設定</string>
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<string name="history_send">Send history</string>
|
||||
<string name="history_title">History</string>
|
||||
<string name="menu_about">About</string>
|
||||
<string name="menu_encode_mecard">Use MECARD</string>
|
||||
<string name="menu_encode_vcard">Use vCard</string>
|
||||
<string name="menu_help">Help</string>
|
||||
<string name="menu_history">History</string>
|
||||
<string name="menu_settings">Settings</string>
|
||||
|
|
|
@ -314,15 +314,15 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
|
|||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, SHARE_ID, 0, R.string.menu_share)
|
||||
menu.add(Menu.NONE, SHARE_ID, Menu.NONE, R.string.menu_share)
|
||||
.setIcon(android.R.drawable.ic_menu_share);
|
||||
menu.add(0, HISTORY_ID, 0, R.string.menu_history)
|
||||
menu.add(Menu.NONE, HISTORY_ID, Menu.NONE, R.string.menu_history)
|
||||
.setIcon(android.R.drawable.ic_menu_recent_history);
|
||||
menu.add(0, SETTINGS_ID, 0, R.string.menu_settings)
|
||||
menu.add(Menu.NONE, SETTINGS_ID, Menu.NONE, R.string.menu_settings)
|
||||
.setIcon(android.R.drawable.ic_menu_preferences);
|
||||
menu.add(0, HELP_ID, 0, R.string.menu_help)
|
||||
menu.add(Menu.NONE, HELP_ID, Menu.NONE, R.string.menu_help)
|
||||
.setIcon(android.R.drawable.ic_menu_help);
|
||||
menu.add(0, ABOUT_ID, 0, R.string.menu_about)
|
||||
menu.add(Menu.NONE, ABOUT_ID, Menu.NONE, R.string.menu_about)
|
||||
.setIcon(android.R.drawable.ic_menu_info_details);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Implementations encode according to some scheme for encoding contact information, like VCard or
|
||||
* MECARD.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
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,
|
||||
String organization,
|
||||
Iterable<String> addresses,
|
||||
Iterable<String> phones,
|
||||
Iterable<String> emails,
|
||||
String url,
|
||||
String note);
|
||||
|
||||
/**
|
||||
* @return null if s is null or empty, or result of s.trim() otherwise
|
||||
*/
|
||||
static String trim(String s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
String result = s.trim();
|
||||
return result.length() == 0 ? null : result;
|
||||
}
|
||||
|
||||
static void doAppend(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);
|
||||
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) {
|
||||
if (values == null) {
|
||||
return;
|
||||
}
|
||||
int count = 0;
|
||||
Collection<String> uniques = new HashSet<String>(2);
|
||||
for (String value : values) {
|
||||
String trimmed = trim(value);
|
||||
if (trimmed != null) {
|
||||
if (!uniques.contains(trimmed)) {
|
||||
newContents.append(prefix).append(':').append(fieldFormatter.format(trimmed)).append(terminator);
|
||||
String display = formatter == null ? trimmed : formatter.format(trimmed);
|
||||
newDisplayContents.append(display).append('\n');
|
||||
if (++count == max) {
|
||||
break;
|
||||
}
|
||||
uniques.add(trimmed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -40,6 +40,7 @@ import java.io.File;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* This class encodes data from an Intent into a QR code, and then displays it full screen so that
|
||||
|
@ -51,7 +52,11 @@ public final class EncodeActivity extends Activity {
|
|||
|
||||
private static final String TAG = EncodeActivity.class.getSimpleName();
|
||||
|
||||
private static final int SHARE_MENU = Menu.FIRST;
|
||||
private static final int ENCODE_FORMAT_MENU = Menu.FIRST + 1;
|
||||
private static final int MAX_BARCODE_FILENAME_LENGTH = 24;
|
||||
private static final Pattern NOT_ALPHANUMERIC = Pattern.compile("[^A-Za-z0-9]");
|
||||
private static final String USE_VCARD_KEY = "USE_VCARD";
|
||||
|
||||
private QRCodeEncoder qrCodeEncoder;
|
||||
|
||||
|
@ -73,22 +78,41 @@ public final class EncodeActivity extends Activity {
|
|||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, Menu.FIRST, 0, R.string.menu_share).setIcon(android.R.drawable.ic_menu_share);
|
||||
menu.add(Menu.NONE, SHARE_MENU, Menu.NONE, R.string.menu_share).setIcon(android.R.drawable.ic_menu_share);
|
||||
int encodeNameResource = qrCodeEncoder.isUseVCard() ? R.string.menu_encode_mecard : R.string.menu_encode_vcard;
|
||||
menu.add(Menu.NONE, ENCODE_FORMAT_MENU, Menu.NONE, encodeNameResource)
|
||||
.setIcon(android.R.drawable.ic_menu_sort_alphabetically);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case SHARE_MENU:
|
||||
share();
|
||||
return true;
|
||||
case ENCODE_FORMAT_MENU:
|
||||
Intent intent = getIntent();
|
||||
intent.putExtra(USE_VCARD_KEY, !qrCodeEncoder.isUseVCard());
|
||||
startActivity(getIntent());
|
||||
finish();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void share() {
|
||||
QRCodeEncoder encoder = qrCodeEncoder;
|
||||
if (encoder == null) { // Odd
|
||||
Log.w(TAG, "No existing barcode to send?");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
String contents = encoder.getContents();
|
||||
if (contents == null) {
|
||||
Log.w(TAG, "No existing barcode to send?");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
Bitmap bitmap;
|
||||
|
@ -96,7 +120,7 @@ public final class EncodeActivity extends Activity {
|
|||
bitmap = encoder.encodeAsBitmap();
|
||||
} catch (WriterException we) {
|
||||
Log.w(TAG, we);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
File bsRoot = new File(Environment.getExternalStorageDirectory(), "BarcodeScanner");
|
||||
|
@ -104,7 +128,7 @@ public final class EncodeActivity extends Activity {
|
|||
if (!barcodesRoot.exists() && !barcodesRoot.mkdirs()) {
|
||||
Log.w(TAG, "Couldn't make dir " + barcodesRoot);
|
||||
showErrorMessage(R.string.msg_unmount_usb);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
File barcodeFile = new File(barcodesRoot, makeBarcodeFileName(contents) + ".png");
|
||||
barcodeFile.delete();
|
||||
|
@ -115,7 +139,7 @@ public final class EncodeActivity extends Activity {
|
|||
} catch (FileNotFoundException fnfe) {
|
||||
Log.w(TAG, "Couldn't access file " + barcodeFile + " due to " + fnfe);
|
||||
showErrorMessage(R.string.msg_unmount_usb);
|
||||
return true;
|
||||
return;
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
try {
|
||||
|
@ -128,24 +152,17 @@ public final class EncodeActivity extends Activity {
|
|||
|
||||
Intent intent = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name) + " - " + encoder.getTitle());
|
||||
intent.putExtra(Intent.EXTRA_TEXT, encoder.getContents());
|
||||
intent.putExtra(Intent.EXTRA_TEXT, contents);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + barcodeFile.getAbsolutePath()));
|
||||
intent.setType("image/png");
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||
startActivity(Intent.createChooser(intent, null));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static CharSequence makeBarcodeFileName(CharSequence contents) {
|
||||
int fileNameLength = Math.min(MAX_BARCODE_FILENAME_LENGTH, contents.length());
|
||||
StringBuilder fileName = new StringBuilder(fileNameLength);
|
||||
for (int i = 0; i < fileNameLength; i++) {
|
||||
char c = contents.charAt(i);
|
||||
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) {
|
||||
fileName.append(c);
|
||||
} else {
|
||||
fileName.append('_');
|
||||
}
|
||||
String fileName = NOT_ALPHANUMERIC.matcher(contents).replaceAll("_");
|
||||
if (fileName.length() > MAX_BARCODE_FILENAME_LENGTH) {
|
||||
fileName = fileName.substring(0, MAX_BARCODE_FILENAME_LENGTH);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
@ -166,7 +183,8 @@ public final class EncodeActivity extends Activity {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
qrCodeEncoder = new QRCodeEncoder(this, intent, smallerDimension);
|
||||
boolean useVCard = intent.getBooleanExtra(USE_VCARD_KEY, false);
|
||||
qrCodeEncoder = new QRCodeEncoder(this, intent, smallerDimension, useVCard);
|
||||
Bitmap bitmap = qrCodeEncoder.encodeAsBitmap();
|
||||
ImageView view = (ImageView) findViewById(R.id.image_view);
|
||||
view.setImageBitmap(bitmap);
|
||||
|
@ -180,11 +198,7 @@ public final class EncodeActivity extends Activity {
|
|||
setTitle(getString(R.string.app_name));
|
||||
}
|
||||
} catch (WriterException e) {
|
||||
Log.e(TAG, "Could not encode barcode", e);
|
||||
showErrorMessage(R.string.msg_encode_contents_failed);
|
||||
qrCodeEncoder = null;
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(TAG, "Could not encode barcode", e);
|
||||
Log.w(TAG, "Could not encode barcode", e);
|
||||
showErrorMessage(R.string.msg_encode_contents_failed);
|
||||
qrCodeEncoder = null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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;
|
||||
|
||||
/**
|
||||
* Encapsulates some simple formatting logic, to aid refactoring in {@link ContactEncoder}.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
interface Formatter {
|
||||
|
||||
String format(String source);
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Encodes contact information according to the MECARD format.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
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 = ';';
|
||||
|
||||
@Override
|
||||
public String[] encode(Iterable<String> names,
|
||||
String organization,
|
||||
Iterable<String> addresses,
|
||||
Iterable<String> phones,
|
||||
Iterable<String> emails,
|
||||
String url,
|
||||
String note) {
|
||||
StringBuilder newContents = new StringBuilder(100);
|
||||
StringBuilder newDisplayContents = new StringBuilder(100);
|
||||
newContents.append("MECARD:");
|
||||
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) {
|
||||
return PhoneNumberUtils.formatNumber(source);
|
||||
}
|
||||
});
|
||||
appendUpToUnique(newContents, newDisplayContents, "EMAIL", emails, Integer.MAX_VALUE, null);
|
||||
append(newContents, newDisplayContents, "URL", url);
|
||||
append(newContents, newDisplayContents, "NOTE", note);
|
||||
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 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -40,10 +40,11 @@ import android.util.Log;
|
|||
|
||||
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.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -65,35 +66,36 @@ final class QRCodeEncoder {
|
|||
private String title;
|
||||
private BarcodeFormat format;
|
||||
private final int dimension;
|
||||
private final boolean useVCard;
|
||||
|
||||
QRCodeEncoder(Activity activity, Intent intent, int dimension) {
|
||||
QRCodeEncoder(Activity activity, Intent intent, int dimension, boolean useVCard) throws WriterException {
|
||||
this.activity = activity;
|
||||
this.dimension = dimension;
|
||||
this.useVCard = useVCard;
|
||||
String action = intent.getAction();
|
||||
if (action.equals(Intents.Encode.ACTION)) {
|
||||
if (!encodeContentsFromZXingIntent(intent)) {
|
||||
throw new IllegalArgumentException("No valid data to encode.");
|
||||
}
|
||||
encodeContentsFromZXingIntent(intent);
|
||||
} else if (action.equals(Intent.ACTION_SEND)) {
|
||||
if (!encodeContentsFromShareIntent(intent)) {
|
||||
throw new IllegalArgumentException("No valid data to encode.");
|
||||
}
|
||||
encodeContentsFromShareIntent(intent);
|
||||
}
|
||||
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
public String getContents() {
|
||||
String getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
public String getDisplayContents() {
|
||||
String getDisplayContents() {
|
||||
return displayContents;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
boolean isUseVCard() {
|
||||
return useVCard;
|
||||
}
|
||||
|
||||
// It would be nice if the string encoding lived in the core ZXing library,
|
||||
// but we use platform specific code like PhoneNumberUtils, so it can't.
|
||||
private boolean encodeContentsFromZXingIntent(Intent intent) {
|
||||
|
@ -126,26 +128,23 @@ final class QRCodeEncoder {
|
|||
}
|
||||
|
||||
// Handles send intents from multitude of Android applications
|
||||
private boolean encodeContentsFromShareIntent(Intent intent) {
|
||||
private void encodeContentsFromShareIntent(Intent intent) throws WriterException {
|
||||
// Check if this is a plain text encoding, or contact
|
||||
if (intent.hasExtra(Intent.EXTRA_TEXT)) {
|
||||
return encodeContentsFromShareIntentPlainText(intent);
|
||||
encodeContentsFromShareIntentPlainText(intent);
|
||||
} else {
|
||||
// Attempt default sharing.
|
||||
encodeContentsFromShareIntentDefault(intent);
|
||||
}
|
||||
// Attempt default sharing.
|
||||
return encodeContentsFromShareIntentDefault(intent);
|
||||
}
|
||||
|
||||
private boolean encodeContentsFromShareIntentPlainText(Intent intent) {
|
||||
private void encodeContentsFromShareIntentPlainText(Intent intent) throws WriterException {
|
||||
// Notice: Google Maps shares both URL and details in one text, bummer!
|
||||
String theContents = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
String theContents = ContactEncoder.trim(intent.getStringExtra(Intent.EXTRA_TEXT));
|
||||
// We only support non-empty and non-blank texts.
|
||||
// Trim text to avoid URL breaking.
|
||||
if (theContents == null) {
|
||||
return false;
|
||||
}
|
||||
theContents = theContents.trim();
|
||||
if (theContents.length() == 0) {
|
||||
return false;
|
||||
if (theContents == null || theContents.length() == 0) {
|
||||
throw new WriterException("Empty EXTRA_TEXT");
|
||||
}
|
||||
contents = theContents;
|
||||
// We only do QR code.
|
||||
|
@ -158,49 +157,47 @@ final class QRCodeEncoder {
|
|||
displayContents = contents;
|
||||
}
|
||||
title = activity.getString(R.string.contents_text);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handles send intents from the Contacts app, retrieving a contact as a VCARD.
|
||||
// Note: Does not work on HTC devices due to broken custom Contacts application.
|
||||
private boolean encodeContentsFromShareIntentDefault(Intent intent) {
|
||||
private void encodeContentsFromShareIntentDefault(Intent intent) throws WriterException {
|
||||
format = BarcodeFormat.QR_CODE;
|
||||
Bundle bundle = intent.getExtras();
|
||||
if (bundle == null) {
|
||||
throw new WriterException("No extras");
|
||||
}
|
||||
Uri uri = (Uri) bundle.getParcelable(Intent.EXTRA_STREAM);
|
||||
if (uri == null) {
|
||||
throw new WriterException("No EXTRA_STREAM");
|
||||
}
|
||||
byte[] vcard;
|
||||
String vcardString;
|
||||
try {
|
||||
Uri uri = (Uri)intent.getExtras().getParcelable(Intent.EXTRA_STREAM);
|
||||
InputStream stream = activity.getContentResolver().openInputStream(uri);
|
||||
int length = stream.available();
|
||||
if (length <= 0) {
|
||||
Log.w(TAG, "Content stream is empty");
|
||||
return false;
|
||||
throw new WriterException("Content stream is empty");
|
||||
}
|
||||
byte[] vcard = new byte[length];
|
||||
vcard = new byte[length];
|
||||
int bytesRead = stream.read(vcard, 0, length);
|
||||
if (bytesRead < length) {
|
||||
Log.w(TAG, "Unable to fully read available bytes from content stream");
|
||||
return false;
|
||||
throw new WriterException("Unable to fully read available bytes from content stream");
|
||||
}
|
||||
String vcardString = new String(vcard, 0, bytesRead, "UTF-8");
|
||||
Log.d(TAG, "Encoding share intent content:");
|
||||
Log.d(TAG, vcardString);
|
||||
Result result = new Result(vcardString, vcard, null, BarcodeFormat.QR_CODE);
|
||||
ParsedResult parsedResult = ResultParser.parseResult(result);
|
||||
if (!(parsedResult instanceof AddressBookParsedResult)) {
|
||||
Log.d(TAG, "Result was not an address");
|
||||
return false;
|
||||
}
|
||||
if (!encodeQRCodeContents((AddressBookParsedResult) parsedResult)) {
|
||||
Log.d(TAG, "Unable to encode contents");
|
||||
return false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
return false;
|
||||
} catch (NullPointerException e) {
|
||||
Log.w(TAG, e);
|
||||
// In case the uri was not found in the Intent.
|
||||
return false;
|
||||
vcardString = new String(vcard, 0, bytesRead, "UTF-8");
|
||||
} catch (IOException ioe) {
|
||||
throw new WriterException(ioe);
|
||||
}
|
||||
Log.d(TAG, "Encoding share intent content:");
|
||||
Log.d(TAG, vcardString);
|
||||
Result result = new Result(vcardString, vcard, null, BarcodeFormat.QR_CODE);
|
||||
ParsedResult parsedResult = ResultParser.parseResult(result);
|
||||
if (!(parsedResult instanceof AddressBookParsedResult)) {
|
||||
throw new WriterException("Result was not an address");
|
||||
}
|
||||
encodeQRCodeContents((AddressBookParsedResult) parsedResult);
|
||||
if (contents == null || contents.length() == 0) {
|
||||
throw new WriterException("No content to encode");
|
||||
}
|
||||
return contents != null && contents.length() > 0;
|
||||
}
|
||||
|
||||
private void encodeQRCodeContents(Intent intent, String type) {
|
||||
|
@ -212,21 +209,21 @@ final class QRCodeEncoder {
|
|||
title = activity.getString(R.string.contents_text);
|
||||
}
|
||||
} else if (type.equals(Contents.Type.EMAIL)) {
|
||||
String data = trim(intent.getStringExtra(Intents.Encode.DATA));
|
||||
String data = ContactEncoder.trim(intent.getStringExtra(Intents.Encode.DATA));
|
||||
if (data != null) {
|
||||
contents = "mailto:" + data;
|
||||
displayContents = data;
|
||||
title = activity.getString(R.string.contents_email);
|
||||
}
|
||||
} else if (type.equals(Contents.Type.PHONE)) {
|
||||
String data = trim(intent.getStringExtra(Intents.Encode.DATA));
|
||||
String data = ContactEncoder.trim(intent.getStringExtra(Intents.Encode.DATA));
|
||||
if (data != null) {
|
||||
contents = "tel:" + data;
|
||||
displayContents = PhoneNumberUtils.formatNumber(data);
|
||||
title = activity.getString(R.string.contents_phone);
|
||||
}
|
||||
} else if (type.equals(Contents.Type.SMS)) {
|
||||
String data = trim(intent.getStringExtra(Intents.Encode.DATA));
|
||||
String data = ContactEncoder.trim(intent.getStringExtra(Intents.Encode.DATA));
|
||||
if (data != null) {
|
||||
contents = "sms:" + data;
|
||||
displayContents = PhoneNumberUtils.formatNumber(data);
|
||||
|
@ -237,69 +234,33 @@ final class QRCodeEncoder {
|
|||
Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
|
||||
if (bundle != null) {
|
||||
|
||||
StringBuilder newContents = new StringBuilder(100);
|
||||
StringBuilder newDisplayContents = new StringBuilder(100);
|
||||
|
||||
newContents.append("MECARD:");
|
||||
|
||||
String name = trim(bundle.getString(ContactsContract.Intents.Insert.NAME));
|
||||
if (name != null) {
|
||||
newContents.append("N:").append(escapeMECARD(name)).append(';');
|
||||
newDisplayContents.append(name);
|
||||
}
|
||||
|
||||
String address = trim(bundle.getString(ContactsContract.Intents.Insert.POSTAL));
|
||||
if (address != null) {
|
||||
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
|
||||
newDisplayContents.append('\n').append(address);
|
||||
}
|
||||
|
||||
Collection<String> uniquePhones = new HashSet<String>(Contents.PHONE_KEYS.length);
|
||||
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<String>(Contents.PHONE_KEYS.length);
|
||||
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
|
||||
String phone = trim(bundle.getString(Contents.PHONE_KEYS[x]));
|
||||
if (phone != null) {
|
||||
uniquePhones.add(phone);
|
||||
}
|
||||
phones.add(bundle.getString(Contents.PHONE_KEYS[x]));
|
||||
}
|
||||
for (String phone : uniquePhones) {
|
||||
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
|
||||
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
|
||||
}
|
||||
|
||||
Collection<String> uniqueEmails = new HashSet<String>(Contents.EMAIL_KEYS.length);
|
||||
Collection<String> emails = new ArrayList<String>(Contents.EMAIL_KEYS.length);
|
||||
for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
|
||||
String email = trim(bundle.getString(Contents.EMAIL_KEYS[x]));
|
||||
if (email != null) {
|
||||
uniqueEmails.add(email);
|
||||
}
|
||||
}
|
||||
for (String email : uniqueEmails) {
|
||||
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
|
||||
newDisplayContents.append('\n').append(email);
|
||||
}
|
||||
|
||||
String url = trim(bundle.getString(Contents.URL_KEY));
|
||||
if (url != null) {
|
||||
// escapeMECARD(url) -> wrong escape e.g. http\://zxing.google.com
|
||||
newContents.append("URL:").append(url).append(';');
|
||||
newDisplayContents.append('\n').append(url);
|
||||
}
|
||||
|
||||
String note = trim(bundle.getString(Contents.NOTE_KEY));
|
||||
if (note != null) {
|
||||
newContents.append("NOTE:").append(escapeMECARD(note)).append(';');
|
||||
newDisplayContents.append('\n').append(note);
|
||||
emails.add(bundle.getString(Contents.EMAIL_KEYS[x]));
|
||||
}
|
||||
String url = bundle.getString(Contents.URL_KEY);
|
||||
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,
|
||||
url,
|
||||
note);
|
||||
// Make sure we've encoded at least one field.
|
||||
if (newDisplayContents.length() > 0) {
|
||||
newContents.append(';');
|
||||
contents = newContents.toString();
|
||||
displayContents = newDisplayContents.toString();
|
||||
if (encoded[1].length() > 0) {
|
||||
contents = encoded[0];
|
||||
displayContents = encoded[1];
|
||||
title = activity.getString(R.string.contents_contact);
|
||||
} else {
|
||||
contents = null;
|
||||
displayContents = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -319,68 +280,23 @@ final class QRCodeEncoder {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean encodeQRCodeContents(AddressBookParsedResult contact) {
|
||||
|
||||
StringBuilder newContents = new StringBuilder(100);
|
||||
StringBuilder newDisplayContents = new StringBuilder(100);
|
||||
|
||||
newContents.append("MECARD:");
|
||||
|
||||
String[] names = contact.getNames();
|
||||
if (names != null && names.length > 0) {
|
||||
String name = trim(names[0]);
|
||||
if (name != null) {
|
||||
newContents.append("N:").append(escapeMECARD(name)).append(';');
|
||||
newDisplayContents.append(name);
|
||||
}
|
||||
}
|
||||
|
||||
for (String address : trimAndDeduplicate(contact.getAddresses())) {
|
||||
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
|
||||
newDisplayContents.append('\n').append(address);
|
||||
}
|
||||
|
||||
for (String phone : trimAndDeduplicate(contact.getPhoneNumbers())) {
|
||||
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
|
||||
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
|
||||
}
|
||||
|
||||
for (String email : trimAndDeduplicate(contact.getEmails())) {
|
||||
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
|
||||
newDisplayContents.append('\n').append(email);
|
||||
}
|
||||
|
||||
String url = trim(contact.getURL());
|
||||
if (url != null) {
|
||||
newContents.append("URL:").append(escapeMECARD(url)).append(';');
|
||||
newDisplayContents.append('\n').append(url);
|
||||
}
|
||||
|
||||
private void encodeQRCodeContents(AddressBookParsedResult contact) {
|
||||
ContactEncoder encoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder();
|
||||
String[] encoded = encoder.encode(Arrays.asList(contact.getNames()),
|
||||
contact.getOrg(),
|
||||
Arrays.asList(contact.getAddresses()),
|
||||
Arrays.asList(contact.getPhoneNumbers()),
|
||||
Arrays.asList(contact.getEmails()),
|
||||
contact.getURL(),
|
||||
null);
|
||||
// Make sure we've encoded at least one field.
|
||||
if (newDisplayContents.length() > 0) {
|
||||
newContents.append(';');
|
||||
contents = newContents.toString();
|
||||
displayContents = newDisplayContents.toString();
|
||||
if (encoded[1].length() > 0) {
|
||||
contents = encoded[0];
|
||||
displayContents = encoded[1];
|
||||
title = activity.getString(R.string.contents_contact);
|
||||
return true;
|
||||
} else {
|
||||
contents = null;
|
||||
displayContents = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Iterable<String> trimAndDeduplicate(String[] values) {
|
||||
if (values == null || values.length == 0) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Collection<String> uniqueValues = new HashSet<String>(values.length);
|
||||
for (String value : values) {
|
||||
uniqueValues.add(trim(value));
|
||||
}
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
Bitmap encodeAsBitmap() throws WriterException {
|
||||
Map<EncodeHintType,Object> hints = null;
|
||||
String encoding = guessAppropriateEncoding(contents);
|
||||
|
@ -393,7 +309,6 @@ final class QRCodeEncoder {
|
|||
int width = result.getWidth();
|
||||
int height = result.getHeight();
|
||||
int[] pixels = new int[width * height];
|
||||
// All are 0, or black, by default
|
||||
for (int y = 0; y < height; y++) {
|
||||
int offset = y * width;
|
||||
for (int x = 0; x < width; x++) {
|
||||
|
@ -416,28 +331,4 @@ final class QRCodeEncoder {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static String trim(String s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
String result = s.trim();
|
||||
return result.length() == 0 ? null : result;
|
||||
}
|
||||
|
||||
private static String escapeMECARD(String input) {
|
||||
if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) {
|
||||
return input;
|
||||
}
|
||||
int length = input.length();
|
||||
StringBuilder result = new StringBuilder(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = input.charAt(i);
|
||||
if (c == ':' || c == ';') {
|
||||
result.append('\\');
|
||||
}
|
||||
result.append(c);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Encodes contact information according to the vCard format.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
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,
|
||||
String organization,
|
||||
Iterable<String> addresses,
|
||||
Iterable<String> phones,
|
||||
Iterable<String> emails,
|
||||
String url,
|
||||
String note) {
|
||||
StringBuilder newContents = new StringBuilder(100);
|
||||
StringBuilder newDisplayContents = new StringBuilder(100);
|
||||
newContents.append("BEGIN:VCARD").append(TERMINATOR);
|
||||
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);
|
||||
append(newContents, newDisplayContents, "URL", url);
|
||||
append(newContents, newDisplayContents, "NOTE", note);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -30,5 +30,9 @@ public final class WriterException extends Exception {
|
|||
public WriterException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public WriterException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -100,10 +100,13 @@ public final class VCardResultParser extends ResultParser {
|
|||
|
||||
while (i < max) {
|
||||
|
||||
// At start or after newling, match prefix, followed by optional metadata
|
||||
// At start or after newline, match prefix, followed by optional metadata
|
||||
// (led by ;) ultimately ending in colon
|
||||
Matcher matcher = Pattern.compile("(?:^|\n)" + prefix + "(?:;([^:]*))?:",
|
||||
Pattern.CASE_INSENSITIVE).matcher(rawText);
|
||||
if (i > 0) {
|
||||
i--; // Find from i-1 not i since looking at the preceding character
|
||||
}
|
||||
if (!matcher.find(i)) {
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue