versionName is 2.31, 2.4, or 3.0. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.zxing.client.android"
- android:versionName="3.0 alpha3"
- android:versionCode="34">
- <!-- Allows this app to run on Cupcake devices. -->
- <uses-sdk android:minSdkVersion="3"/>
+ android:versionName="3.0 beta1"
+ android:versionCode="35">
+ <!-- We require Donut (Android 1.6) or later. -->
+ <uses-sdk android:minSdkVersion="4"/>
<!-- Donut-specific flags which allow us to run on large and high dpi screens. -->
<supports-screens
android:largeScreens="true"
<action android:name="com.google.zxing.client.android.SCAN"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
- <intent-filter>
- <!-- For compatibility only - do not use in new code, this will go away! -->
- <action android:name="com.android.barcodes.SCAN"/>
- <category android:name="android.intent.category.DEFAULT"/>
- </intent-filter>
<!-- Allow web apps to launch Barcode Scanner by linking to http://zxing.appspot.com/scan. -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
- <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
- <data android:scheme="http" android:host="zxing.appspot.com" android:path="/scan" />
+ <data android:scheme="http" android:host="zxing.appspot.com" android:path="/scan"/>
</intent-filter>
<!-- We also support a Google Product Search URL. -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
- <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
- <data android:scheme="http" android:host="www.google.com" android:path="/m/products/scan" />
+ <data android:scheme="http" android:host="www.google.com" android:path="/m/products/scan"/>
</intent-filter>
<!-- And the UK version. -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
- <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
- <data android:scheme="http" android:host="www.google.co.uk" android:path="/m/products/scan" />
+ <data android:scheme="http" android:host="www.google.co.uk" android:path="/m/products/scan"/>
</intent-filter>
</activity>
<activity android:name=".PreferencesActivity"
<action android:name="com.google.zxing.client.android.ENCODE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
+ <!-- This allows us to handle the Share button in Contacts. -->
<intent-filter>
- <!-- For compatibility only - do not use in new code, this will go away! -->
- <action android:name="com.android.barcodes.ENCODE"/>
+ <action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
+ <data android:mimeType="text/x-vcard"/>
</intent-filter>
</activity>
<activity android:name=".book.SearchBookContentsActivity"
<action android:name="com.google.zxing.client.android.SEARCH_BOOK_CONTENTS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
- <intent-filter>
- <!-- For compatibility only - do not use in new code, this will go away! -->
- <action android:name="com.android.barcodes.SEARCH_BOOK_CONTENTS"/>
- <category android:name="android.intent.category.DEFAULT"/>
- </intent-filter>
</activity>
<activity android:name=".share.ShareActivity"
android:label="@string/share_name"
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.Result;
import com.google.zxing.WriterException;
-import com.google.zxing.client.android.Intents;
import com.google.zxing.client.android.Contents;
+import com.google.zxing.client.android.Intents;
import com.google.zxing.client.android.R;
+import com.google.zxing.client.result.AddressBookParsedResult;
+import com.google.zxing.client.result.ParsedResult;
+import com.google.zxing.client.result.ResultParser;
import com.google.zxing.common.ByteMatrix;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
/**
* This class does the work of decoding the user's request and extracting all the data
- * to be encoded in a QR Code.
+ * to be encoded in a barcode.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public QRCodeEncoder(Activity activity, Intent intent) {
this.activity = activity;
- if (!encodeContents(intent)) {
+ if (intent == null) {
+ throw new IllegalArgumentException("No valid data to encode.");
+ }
+
+ String action = intent.getAction();
+ if (action.equals(Intents.Encode.ACTION)) {
+ if (!encodeContentsFromZXingIntent(intent)) {
+ throw new IllegalArgumentException("No valid data to encode.");
+ }
+ } else if (action.equals(Intent.ACTION_SEND)) {
+ if (!encodeContentsFromShareIntent(intent)) {
throw new IllegalArgumentException("No valid data to encode.");
+ }
}
}
public String getTitle() {
return title;
}
-
+
public String getFormat() {
return format.toString();
}
// 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 encodeContents(Intent intent) {
- if (intent == null) {
- return false;
- }
-
- // default to QR_CODE if no format given
+ private boolean encodeContentsFromZXingIntent(Intent intent) {
+ // Default to QR_CODE if no format given.
String format = intent.getStringExtra(Intents.Encode.FORMAT);
- if (format == null || format.length() == 0 ||
+ if (format == null || format.length() == 0 ||
format.equals(Contents.Format.QR_CODE)) {
String type = intent.getStringExtra(Intents.Encode.TYPE);
if (type == null || type.length() == 0) {
return contents != null && contents.length() > 0;
}
+ // Handles send intents from the Contacts app, retrieving a contact as a VCARD.
+ private boolean encodeContentsFromShareIntent(Intent intent) {
+ format = BarcodeFormat.QR_CODE;
+ try {
+ Uri uri = (Uri)intent.getExtras().getParcelable(Intent.EXTRA_STREAM);
+ InputStream stream = activity.getContentResolver().openInputStream(uri);
+ int length = stream.available();
+ byte[] vcard = new byte[length];
+ stream.read(vcard, 0, length);
+ String vcardString = new String(vcard, "utf-8");
+ Result result = new Result(vcardString, vcard, null, BarcodeFormat.QR_CODE);
+ ParsedResult parsedResult = ResultParser.parseResult(result);
+ if (!(parsedResult instanceof AddressBookParsedResult)) {
+ return false;
+ }
+ if (!encodeQRCodeContents((AddressBookParsedResult) parsedResult)) {
+ return false;
+ }
+ } catch (FileNotFoundException e) {
+ return false;
+ } catch (IOException e) {
+ return false;
+ }
+ return contents != null && contents.length() > 0;
+ }
+
private void encodeQRCodeContents(Intent intent, String type) {
if (type.equals(Contents.Type.TEXT)) {
String data = intent.getStringExtra(Intents.Encode.DATA);
}
}
+ private boolean encodeQRCodeContents(AddressBookParsedResult contact) {
+ StringBuilder newContents = new StringBuilder();
+ StringBuilder newDisplayContents = new StringBuilder();
+ newContents.append("MECARD:");
+ String[] names = contact.getNames();
+ if (names != null && names.length > 0) {
+ newContents.append("N:").append(names[0]).append(';');
+ newDisplayContents.append(names[0]);
+ }
+ String address = contact.getAddress();
+ if (address != null && address.length() > 0) {
+ newContents.append("ADR:").append(address).append(';');
+ newDisplayContents.append('\n').append(address);
+ }
+ String[] phoneNumbers = contact.getPhoneNumbers();
+ if (phoneNumbers != null) {
+ for (int x = 0; x < phoneNumbers.length; x++) {
+ String phone = phoneNumbers[x];
+ if (phone != null && phone.length() > 0) {
+ newContents.append("TEL:").append(phone).append(';');
+ newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
+ }
+ }
+ }
+ String[] emails = contact.getEmails();
+ if (emails != null) {
+ for (int x = 0; x < emails.length; x++) {
+ String email = emails[x];
+ if (email != null && email.length() > 0) {
+ newContents.append("EMAIL:").append(email).append(';');
+ newDisplayContents.append('\n').append(email);
+ }
+ }
+ }
+ String url = contact.getURL();
+ if (url != null && url.length() > 0) {
+ newContents.append("URL:").append(url).append(';');
+ newDisplayContents.append('\n').append(url);
+ }
+ // Make sure we've encoded at least one field.
+ if (newDisplayContents.length() > 0) {
+ newContents.append(';');
+ contents = newContents.toString();
+ displayContents = newDisplayContents.toString();
+ title = activity.getString(R.string.contents_contact);
+ return true;
+ } else {
+ contents = null;
+ displayContents = null;
+ return false;
+ }
+ }
+
private static final class EncodeThread extends Thread {
private static final String TAG = "EncodeThread";