diff --git a/libs/core-3.0.1.jar b/libs/core-3.0.1.jar new file mode 100644 index 000000000..d1b35fcbb Binary files /dev/null and b/libs/core-3.0.1.jar differ diff --git a/libs/core-3.0.1.jar.README b/libs/core-3.0.1.jar.README new file mode 100644 index 000000000..8535081d5 --- /dev/null +++ b/libs/core-3.0.1.jar.README @@ -0,0 +1,17 @@ +zxing +----- + +ZXing ("zebra crossing") is an open-source, multi-format 1D/2D barcode image +processing library implemented in Java, with ports to other languages. + +https://github.com/zxing/zxing + +Building zxing from scratch is a massive pain, so we use the official jar. +The main source repo is SVN, so we couldn't do a git submodule anyway. + +The releases should be signed by this key: +Sean Owen (ZXing) +CE32 85F3 2068 5193 D11F EA01 F6CE 9695 C931 8406 + +http://central.maven.org/maven2/com/google/zxing/core/3.0.1/core-3.0.1.jar +http://central.maven.org/maven2/com/google/zxing/core/3.0.1/core-3.0.1.jar.asc diff --git a/src/com/google/zxing/encode/Contents.java b/src/com/google/zxing/encode/Contents.java new file mode 100755 index 000000000..6271fa9af --- /dev/null +++ b/src/com/google/zxing/encode/Contents.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008 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 + * + * https://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.encode; + +import android.provider.ContactsContract; + +/** + * The set of constants to use when sending Barcode Scanner an Intent which requests a barcode + * to be encoded. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +public final class Contents { + private Contents() { + } + + public static final class Type { + /** + * Plain text. Use Intent.putExtra(DATA, string). This can be used for URLs too, but string + * must include "http://" or "https://". + */ + public static final String TEXT = "TEXT_TYPE"; + + /** + * An email type. Use Intent.putExtra(DATA, string) where string is the email address. + */ + public static final String EMAIL = "EMAIL_TYPE"; + + /** + * Use Intent.putExtra(DATA, string) where string is the phone number to call. + */ + public static final String PHONE = "PHONE_TYPE"; + + /** + * An SMS type. Use Intent.putExtra(DATA, string) where string is the number to SMS. + */ + public static final String SMS = "SMS_TYPE"; + + /** + * A contact. Send a request to encode it as follows: + *

+ * import android.provider.Contacts; + *

+ * Intent intent = new Intent(Intents.Encode.ACTION); + * intent.putExtra(Intents.Encode.TYPE, CONTACT); + * Bundle bundle = new Bundle(); + * bundle.putString(Contacts.Intents.Insert.NAME, "Jenny"); + * bundle.putString(Contacts.Intents.Insert.PHONE, "8675309"); + * bundle.putString(Contacts.Intents.Insert.EMAIL, "jenny@the80s.com"); + * bundle.putString(Contacts.Intents.Insert.POSTAL, "123 Fake St. San Francisco, CA 94102"); + * intent.putExtra(Intents.Encode.DATA, bundle); + */ + public static final String CONTACT = "CONTACT_TYPE"; + + /** + * A geographic location. Use as follows: + * Bundle bundle = new Bundle(); + * bundle.putFloat("LAT", latitude); + * bundle.putFloat("LONG", longitude); + * intent.putExtra(Intents.Encode.DATA, bundle); + */ + public static final String LOCATION = "LOCATION_TYPE"; + + private Type() { + } + } + + public static final String URL_KEY = "URL_KEY"; + + public static final String NOTE_KEY = "NOTE_KEY"; + + /** + * When using Type.CONTACT, these arrays provide the keys for adding or retrieving multiple + * phone numbers and addresses. + */ + public static final String[] PHONE_KEYS = { + ContactsContract.Intents.Insert.PHONE, + ContactsContract.Intents.Insert.SECONDARY_PHONE, + ContactsContract.Intents.Insert.TERTIARY_PHONE + }; + + public static final String[] PHONE_TYPE_KEYS = { + ContactsContract.Intents.Insert.PHONE_TYPE, + ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE, + ContactsContract.Intents.Insert.TERTIARY_PHONE_TYPE + }; + + public static final String[] EMAIL_KEYS = { + ContactsContract.Intents.Insert.EMAIL, + ContactsContract.Intents.Insert.SECONDARY_EMAIL, + ContactsContract.Intents.Insert.TERTIARY_EMAIL + }; + + public static final String[] EMAIL_TYPE_KEYS = { + ContactsContract.Intents.Insert.EMAIL_TYPE, + ContactsContract.Intents.Insert.SECONDARY_EMAIL_TYPE, + ContactsContract.Intents.Insert.TERTIARY_EMAIL_TYPE + }; + +} diff --git a/src/com/google/zxing/encode/QRCodeEncoder.java b/src/com/google/zxing/encode/QRCodeEncoder.java new file mode 100755 index 000000000..9b17eccf9 --- /dev/null +++ b/src/com/google/zxing/encode/QRCodeEncoder.java @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2008 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 + * + * https://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. + */ +// from https://stackoverflow.com/questions/4782543/integration-zxing-library-directly-into-my-android-application +package com.google.zxing.encode; + +import android.graphics.Bitmap; +import android.os.Bundle; +import android.provider.ContactsContract; +import android.telephony.PhoneNumberUtils; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; + +import java.util.Collection; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.Map; + +public final class QRCodeEncoder { + private static final int WHITE = 0xFFFFFFFF; + private static final int BLACK = 0xFF000000; + + private int dimension = Integer.MIN_VALUE; + private String contents = null; + private String displayContents = null; + private String title = null; + private BarcodeFormat format = null; + private boolean encoded = false; + + public QRCodeEncoder(String data, Bundle bundle, String type, String format, int dimension) { + this.dimension = dimension; + encoded = encodeContents(data, bundle, type, format); + } + + public String getContents() { + return contents; + } + + public String getDisplayContents() { + return displayContents; + } + + public String getTitle() { + return title; + } + + private boolean encodeContents(String data, Bundle bundle, String type, String formatString) { + // Default to QR_CODE if no format given. + format = null; + if (formatString != null) { + try { + format = BarcodeFormat.valueOf(formatString); + } catch (IllegalArgumentException iae) { + // Ignore it then + } + } + if (format == null || format == BarcodeFormat.QR_CODE) { + this.format = BarcodeFormat.QR_CODE; + encodeQRCodeContents(data, bundle, type); + } else if (data != null && data.length() > 0) { + contents = data; + displayContents = data; + title = "Text"; + } + return contents != null && contents.length() > 0; + } + + private void encodeQRCodeContents(String data, Bundle bundle, String type) { + if (type.equals(Contents.Type.TEXT)) { + if (data != null && data.length() > 0) { + contents = data; + displayContents = data; + title = "Text"; + } + } else if (type.equals(Contents.Type.EMAIL)) { + data = trim(data); + if (data != null) { + contents = "mailto:" + data; + displayContents = data; + title = "E-Mail"; + } + } else if (type.equals(Contents.Type.PHONE)) { + data = trim(data); + if (data != null) { + contents = "tel:" + data; + displayContents = PhoneNumberUtils.formatNumber(data); + title = "Phone"; + } + } else if (type.equals(Contents.Type.SMS)) { + data = trim(data); + if (data != null) { + contents = "sms:" + data; + displayContents = PhoneNumberUtils.formatNumber(data); + title = "SMS"; + } + } else if (type.equals(Contents.Type.CONTACT)) { + 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 uniquePhones = new HashSet(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); + } + } + for (String phone : uniquePhones) { + newContents.append("TEL:").append(escapeMECARD(phone)).append(';'); + newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone)); + } + + Collection uniqueEmails = new HashSet(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); + } + + // Make sure we've encoded at least one field. + if (newDisplayContents.length() > 0) { + newContents.append(';'); + contents = newContents.toString(); + displayContents = newDisplayContents.toString(); + title = "Contact"; + } else { + contents = null; + displayContents = null; + } + + } + } else if (type.equals(Contents.Type.LOCATION)) { + if (bundle != null) { + // These must use Bundle.getFloat(), not getDouble(), it's part of the API. + float latitude = bundle.getFloat("LAT", Float.MAX_VALUE); + float longitude = bundle.getFloat("LONG", Float.MAX_VALUE); + if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) { + contents = "geo:" + latitude + ',' + longitude; + displayContents = latitude + "," + longitude; + title = "Location"; + } + } + } + } + + public Bitmap encodeAsBitmap() throws WriterException { + if (!encoded) return null; + + Map hints = null; + String encoding = guessAppropriateEncoding(contents); + if (encoding != null) { + hints = new EnumMap(EncodeHintType.class); + hints.put(EncodeHintType.CHARACTER_SET, encoding); + } + MultiFormatWriter writer = new MultiFormatWriter(); + BitMatrix result = writer.encode(contents, format, dimension, dimension, hints); + 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++) { + pixels[offset + x] = result.get(x, y) ? BLACK : WHITE; + } + } + + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, width, 0, 0, width, height); + return bitmap; + } + + private static String guessAppropriateEncoding(CharSequence contents) { + // Very crude at the moment + for (int i = 0; i < contents.length(); i++) { + if (contents.charAt(i) > 0xFF) { return "UTF-8"; } + } + 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(); + } +}