Update ZXingTest to work on 3.x+, mostly by removing the camera capture bit for now. It can come back after android/ is updated and can be cloned again. Updated android-integration with better API and ability to specify package. Now ZXingTest uses our integration code. It's updated for Android 2.x and reports camera params in a slightly better form. Also fixed a few Android 2.x issues and related intent integration stuff left over from other recent changes.

git-svn-id: https://zxing.googlecode.com/svn/trunk@2020 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2011-11-10 11:16:24 +00:00
parent 22e0f8daa2
commit f328cb618e
20 changed files with 320 additions and 1139 deletions

View file

@ -35,11 +35,15 @@
deprecation="true"
includeantruntime="false">
<classpath>
<pathelement location="${android-home}/platforms/android-10/android.jar"/>
<pathelement location="${android-home}/platforms/android-7/android.jar"/>
</classpath>
</javac>
<jar jarfile="android-integration.jar" basedir="build"/>
</target>
<target name="export" depends="build">
<copy file="android-integration.jar" todir="../androidtest/libs"/>
</target>
<target name="clean">
<delete dir="build"/>

View file

@ -48,7 +48,7 @@
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<scope>provided</scope>
<version>1.6_r2</version>
<version>2.1.2</version>
</dependency>
</dependencies>
<build>

View file

@ -16,14 +16,18 @@
package com.google.zxing.integration.android;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.util.Log;
@ -34,11 +38,11 @@ import android.util.Log;
*
* <h2>Initiating a barcode scan</h2>
*
* <p>Integration is essentially as easy as calling {@link #initiateScan(Activity)} and waiting
* <p>To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait
* for the result in your app.</p>
*
* <p>It does require that the Barcode Scanner application is installed. The
* {@link #initiateScan(Activity)} method will prompt the user to download the application, if needed.</p>
* <p>It does require that the Barcode Scanner (or work-alike) application is installed. The
* {@link #initiateScan()} method will prompt the user to download the application, if needed.</p>
*
* <p>There are a few steps to using this integration. First, your {@link Activity} must implement
* the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
@ -54,23 +58,31 @@ import android.util.Log;
* }
* }</pre>
*
* <p>This is where you will handle a scan result.
* Second, just call this in response to a user action somewhere to begin the scan process:</p>
* <p>This is where you will handle a scan result.</p>
*
* <pre>{@code IntentIntegrator.initiateScan(yourActivity);}</pre>
* <p>Second, just call this in response to a user action somewhere to begin the scan process:</p>
*
* <p>You can use {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} or
* {@link #initiateScan(Activity, int, int, int, int)} to customize the download prompt with
* different text labels.</p>
* <pre>{@code
* IntentIntegrator integrator = new IntentIntegrator(yourActivity);
* integrator.initiateScan();
* }</pre>
*
* <p>Note that {@link #initiateScan(Activity)} returns an {@link AlertDialog} which is non-null if the
* <p>Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the
* user was prompted to download the application. This lets the calling app potentially manage the dialog.
* In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()}
* method.</p>
*
* <p>You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use
* {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and
* yes/no button labels can be changed.</p>
*
* <p>By default, this will only allow applications that are known to respond to this intent correctly
* do so. The apps that are allowed to response can be set with {@link #setTargetApplications(Collection)}.
* For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.</p>
*
* <h2>Sharing text via barcode</h2>
*
* <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(Activity, CharSequence)}.</p>
* <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.</p>
*
* <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
*
@ -91,130 +103,162 @@ public final class IntentIntegrator {
public static final String DEFAULT_YES = "Yes";
public static final String DEFAULT_NO = "No";
private static final String PACKAGE = "com.google.zxing.client.android";
private static final String BS_PACKAGE = "com.google.zxing.client.android";
// supported barcode formats
public static final String PRODUCT_CODE_TYPES = "UPC_A,UPC_E,EAN_8,EAN_13";
public static final String ONE_D_CODE_TYPES = PRODUCT_CODE_TYPES + ",CODE_39,CODE_93,CODE_128";
public static final String QR_CODE_TYPES = "QR_CODE";
public static final String ALL_CODE_TYPES = null;
public static final Collection<String> PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14");
public static final Collection<String> ONE_D_CODE_TYPES =
list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128",
"ITF", "RSS_14", "RSS_EXPANDED");
public static final Collection<String> QR_CODE_TYPES = Collections.singleton("QR_CODE");
public static final Collection<String> DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX");
public static final Method PACKAGE_SETTER;
static {
Method temp;
try {
temp = Intent.class.getMethod("setPackage", String.class);
} catch (NoSuchMethodException nsme) {
temp = null;
}
PACKAGE_SETTER = temp;
public static final Collection<String> ALL_CODE_TYPES = null;
public static final Collection<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singleton(BS_PACKAGE);
public static final Collection<String> TARGET_ALL_KNOWN = list(
BS_PACKAGE, // Barcode Scanner
"com.srowen.bs.android", // Barcode Scanner+
"com.srowen.bs.android.simple" // Barcode Scanner+ Simple
// TODO add more -- what else supports this intent?
);
private final Activity activity;
private String title;
private String message;
private String buttonYes;
private String buttonNo;
private Collection<String> targetApplications;
public IntentIntegrator(Activity activity) {
this.activity = activity;
title = DEFAULT_TITLE;
message = DEFAULT_MESSAGE;
buttonYes = DEFAULT_YES;
buttonNo = DEFAULT_NO;
targetApplications = TARGET_ALL_KNOWN;
}
private IntentIntegrator() {
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setTitleByID(int titleID) {
title = activity.getString(titleID);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void setMessageByID(int messageID) {
message = activity.getString(messageID);
}
public String getButtonYes() {
return buttonYes;
}
public void setButtonYes(String buttonYes) {
this.buttonYes = buttonYes;
}
public void setButtonYesByID(int buttonYesID) {
buttonYes = activity.getString(buttonYesID);
}
public String getButtonNo() {
return buttonNo;
}
public void setButtonNo(String buttonNo) {
this.buttonNo = buttonNo;
}
public void setButtonNoByID(int buttonNoID) {
buttonNo = activity.getString(buttonNoID);
}
public Collection<String> getTargetApplications() {
return targetApplications;
}
public void setTargetApplications(Collection<String> targetApplications) {
this.targetApplications = targetApplications;
}
public void setSingleTargetApplication(String targetApplication) {
this.targetApplications = Collections.singleton(targetApplication);
}
/**
* See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} --
* same, but uses default English labels.
* Initiates a scan for all known barcode types.
*/
public static AlertDialog initiateScan(Activity activity) {
return initiateScan(activity, DEFAULT_TITLE, DEFAULT_MESSAGE, DEFAULT_YES, DEFAULT_NO);
public AlertDialog initiateScan() {
return initiateScan(ALL_CODE_TYPES);
}
/**
* See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} --
* same, but takes string IDs which refer
* to the {@link Activity}'s resource bundle entries.
* Initiates a scan only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*/
public static AlertDialog initiateScan(Activity activity,
int stringTitle,
int stringMessage,
int stringButtonYes,
int stringButtonNo) {
return initiateScan(activity,
activity.getString(stringTitle),
activity.getString(stringMessage),
activity.getString(stringButtonYes),
activity.getString(stringButtonNo));
}
/**
* See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} --
* same, but scans for all supported barcode types.
* @param stringTitle title of dialog prompting user to download Barcode Scanner
* @param stringMessage text of dialog prompting user to download Barcode Scanner
* @param stringButtonYes text of button user clicks when agreeing to download
* Barcode Scanner (e.g. "Yes")
* @param stringButtonNo text of button user clicks when declining to download
* Barcode Scanner (e.g. "No")
* @return an {@link AlertDialog} if the user was prompted to download the app,
* null otherwise
*/
public static AlertDialog initiateScan(Activity activity,
CharSequence stringTitle,
CharSequence stringMessage,
CharSequence stringButtonYes,
CharSequence stringButtonNo) {
return initiateScan(activity,
stringTitle,
stringMessage,
stringButtonYes,
stringButtonNo,
ALL_CODE_TYPES);
}
/**
* Invokes scanning.
*
* @param stringTitle title of dialog prompting user to download Barcode Scanner
* @param stringMessage text of dialog prompting user to download Barcode Scanner
* @param stringButtonYes text of button user clicks when agreeing to download
* Barcode Scanner (e.g. "Yes")
* @param stringButtonNo text of button user clicks when declining to download
* Barcode Scanner (e.g. "No")
* @param stringDesiredBarcodeFormats a comma separated list of codes you would
* like to scan for.
* @return an {@link AlertDialog} if the user was prompted to download the app,
* null otherwise
* @throws InterruptedException if timeout expires before a scan completes
*/
public static AlertDialog initiateScan(Activity activity,
CharSequence stringTitle,
CharSequence stringMessage,
CharSequence stringButtonYes,
CharSequence stringButtonNo,
CharSequence stringDesiredBarcodeFormats) {
Intent intentScan = new Intent(PACKAGE + ".SCAN");
setPackage(intentScan);
public AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
// check which types of codes to scan for
if (stringDesiredBarcodeFormats != null) {
if (desiredBarcodeFormats != null) {
// set the desired barcode types
intentScan.putExtra("SCAN_FORMATS", stringDesiredBarcodeFormats);
StringBuilder joinedByComma = new StringBuilder();
for (String format : desiredBarcodeFormats) {
if (joinedByComma.length() > 0) {
joinedByComma.append(',');
}
joinedByComma.append(format);
}
intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString());
}
try {
activity.startActivityForResult(intentScan, REQUEST_CODE);
return null;
} catch (ActivityNotFoundException e) {
return showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo);
String targetAppPackage = findTargetAppPackage(intentScan);
if (targetAppPackage == null) {
return showDownloadDialog();
}
intentScan.setPackage(targetAppPackage);
activity.startActivityForResult(intentScan, REQUEST_CODE);
return null;
}
private String findTargetAppPackage(Intent intent) {
PackageManager pm = activity.getPackageManager();
List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (availableApps != null) {
for (ResolveInfo availableApp : availableApps) {
String packageName = availableApp.activityInfo.packageName;
if (targetApplications.contains(packageName)) {
return packageName;
}
}
}
return null;
}
private static AlertDialog showDownloadDialog(final Activity activity,
CharSequence stringTitle,
CharSequence stringMessage,
CharSequence stringButtonYes,
CharSequence stringButtonNo) {
private AlertDialog showDownloadDialog() {
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
downloadDialog.setTitle(stringTitle);
downloadDialog.setMessage(stringMessage);
downloadDialog.setPositiveButton(stringButtonYes, new DialogInterface.OnClickListener() {
downloadDialog.setTitle(title);
downloadDialog.setMessage(message);
downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Uri uri = Uri.parse("market://search?q=pname:" + PACKAGE);
Uri uri = Uri.parse("market://details?id=" + BS_PACKAGE);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
try {
activity.startActivity(intent);
@ -224,7 +268,7 @@ public final class IntentIntegrator {
}
}
});
downloadDialog.setNegativeButton(stringButtonNo, new DialogInterface.OnClickListener() {
downloadDialog.setNegativeButton(buttonNo, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {}
});
@ -246,79 +290,36 @@ public final class IntentIntegrator {
String contents = intent.getStringExtra("SCAN_RESULT");
String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
return new IntentResult(contents, formatName);
} else {
return new IntentResult(null, null);
}
return new IntentResult(null, null);
}
return null;
}
/**
* See {@link #shareText(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} --
* same, but uses default English labels.
*/
public static void shareText(Activity activity, CharSequence text) {
shareText(activity, text, DEFAULT_TITLE, DEFAULT_MESSAGE, DEFAULT_YES, DEFAULT_NO);
}
/**
* See {@link #shareText(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} --
* same, but takes string IDs which refer to the {@link Activity}'s resource bundle entries.
*/
public static void shareText(Activity activity,
CharSequence text,
int stringTitle,
int stringMessage,
int stringButtonYes,
int stringButtonNo) {
shareText(activity,
text,
activity.getString(stringTitle),
activity.getString(stringMessage),
activity.getString(stringButtonYes),
activity.getString(stringButtonNo));
}
/**
* Shares the given text by encoding it as a barcode, such that another user can
* scan the text off the screen of the device.
*
* @param text the text string to encode as a barcode
* @param stringTitle title of dialog prompting user to download Barcode Scanner
* @param stringMessage text of dialog prompting user to download Barcode Scanner
* @param stringButtonYes text of button user clicks when agreeing to download
* Barcode Scanner (e.g. "Yes")
* @param stringButtonNo text of button user clicks when declining to download
* Barcode Scanner (e.g. "No")
*/
public static void shareText(Activity activity,
CharSequence text,
CharSequence stringTitle,
CharSequence stringMessage,
CharSequence stringButtonYes,
CharSequence stringButtonNo) {
public void shareText(CharSequence text) {
Intent intent = new Intent();
intent.setAction(PACKAGE + ".ENCODE");
setPackage(intent);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setAction(BS_PACKAGE + ".ENCODE");
intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
intent.putExtra("ENCODE_DATA", text);
try {
String targetAppPackage = findTargetAppPackage(intent);
if (targetAppPackage == null) {
showDownloadDialog();
} else {
intent.setPackage(targetAppPackage);
activity.startActivity(intent);
} catch (ActivityNotFoundException e) {
showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo);
}
}
private static void setPackage(Intent intent) {
if (PACKAGE_SETTER != null) {
try {
PACKAGE_SETTER.invoke(intent, PACKAGE);
} catch (InvocationTargetException ite) {
Log.w(TAG, ite.getTargetException());
} catch (IllegalAccessException iae) {
Log.w(TAG, iae);
}
}
private static Collection<String> list(String... values) {
return Collections.unmodifiableCollection(Arrays.asList(values));
}
}

View file

@ -1,16 +0,0 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked in Version Control Systems, as it is
# integral to the build system of your project.
# The name of your application package as defined in the manifest.
# Used by the 'uninstall' rule.
application-package=com.google.zxing.client.android
# The name of the source folder.
#source-folder=src
# The name of the output folder.
#out-folder=bin
external-libs-folder=external-libs

View file

@ -1,11 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-10

View file

@ -99,11 +99,13 @@ final class QRCodeEncoder {
private boolean encodeContentsFromZXingIntent(Intent intent) {
// Default to QR_CODE if no format given.
String formatString = intent.getStringExtra(Intents.Encode.FORMAT);
try {
format = BarcodeFormat.valueOf(formatString);
} catch (IllegalArgumentException iae) {
// Ignore it then
format = null;
format = null;
if (formatString != null) {
try {
format = BarcodeFormat.valueOf(formatString);
} catch (IllegalArgumentException iae) {
// Ignore it then
}
}
if (format == null || format == BarcodeFormat.QR_CODE) {
String type = intent.getStringExtra(Intents.Encode.TYPE);

View file

@ -16,12 +16,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.zxing.client.androidtest"
android:versionName="1.13"
android:versionCode="5">
<!-- We require Cupcake (Android 1.5) or later, but are really targeting Donut. -->
<uses-sdk android:minSdkVersion="3"
android:targetSdkVersion="4"/>
<!-- Donut-specific flags which allow us to run on any dpi screens. -->
android:versionName="1.2"
android:versionCode="6"
android:installLocation="auto">
<uses-sdk android:minSdkVersion="7"
android:targetSdkVersion="7"/>
<supports-screens android:xlargeScreens="true"
android:largeScreens="true"
android:normalScreens="true"
@ -39,9 +38,6 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="CameraTestActivity"
android:screenOrientation="landscape">
</activity>
<activity android:name="BenchmarkActivity"
android:label="@string/benchmark_name"
android:screenOrientation="portrait"/>

View file

@ -1,15 +0,0 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked in Version Control Systems, as it is
# integral to the build system of your project.
# The name of your application package as defined in the manifest.
# Used by the 'uninstall' rule.
application-package=com.google.zxing.client.androidtest
# The name of the source folder.
#source-folder=src
# The name of the output folder.
#out-folder=bin

View file

@ -1,11 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-10

View file

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<SurfaceView android:id="@+id/preview_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/transparent">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="@color/transparent"/>
<TextView android:id="@+id/status_text_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:layout_weight="0"
android:text="@string/parameters_message"
android:textColor="@color/status_text"
android:background="@color/status_view"
android:padding="4px"/>
</LinearLayout>
</FrameLayout>

View file

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<SurfaceView android:id="@+id/preview_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"/>
<com.google.zxing.client.androidtest.ViewfinderView
android:id="@+id/viewfinder_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/transparent"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/transparent">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="@color/transparent"/>
<TextView android:id="@+id/status_text_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:layout_weight="0"
android:text="@string/status_message"
android:textColor="@color/status_text"
android:background="@color/status_view"
android:padding="4px"/>
</LinearLayout>
</FrameLayout>

View file

@ -20,83 +20,79 @@
android:gravity="center_horizontal"
android:padding="10px">
<TableRow>
<Button android:id="@+id/take_test_photos"
android:layout_width="wrap_content"
<Button android:id="@+id/run_benchmark"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/take_test_photos"/>
android:text="@string/benchmark_run"/>
<Button android:id="@+id/get_camera_parameters"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/get_camera_parameters"/>
</TableRow>
<TableRow>
<Button android:id="@+id/scan_product"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/scan_product"/>
<Button android:id="@+id/scan_qr_code"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/scan_qr_code"/>
</TableRow>
<TableRow>
<Button android:id="@+id/scan_anything"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/scan_anything"/>
<Button android:id="@+id/search_book_contents"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/search_book_contents"/>
</TableRow>
<TableRow>
<Button android:id="@+id/encode_url"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/encode_url"/>
<Button android:id="@+id/encode_email"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/encode_email"/>
</TableRow>
<TableRow>
<Button android:id="@+id/encode_phone"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/encode_phone"/>
<Button android:id="@+id/encode_sms"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/encode_sms"/>
</TableRow>
<TableRow>
<Button android:id="@+id/encode_contact"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/encode_contact"/>
<Button android:id="@+id/encode_location"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/encode_location"/>
</TableRow>
<TableRow>
<Button android:id="@+id/encode_hidden_data"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/encode_hidden_data"/>
<Button android:id="@+id/encode_bad_data"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/encode_bad_data"/>
</TableRow>
<TableRow>
<Button android:id="@+id/share_via_barcode"
android:layout_width="wrap_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/share_via_barcode"/>
<Button android:id="@+id/run_benchmark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/benchmark_run"/>
</TableRow>
</TableLayout>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
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.
-->
<resources>
<declare-styleable name="ViewfinderView">
</declare-styleable>
</resources>

View file

@ -1,289 +0,0 @@
/*
* 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
*
* 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.androidtest;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.WindowManager;
import java.io.IOException;
import java.util.regex.Pattern;
/**
* This object wraps the Camera service object and expects to be the only one talking to it. The
* implementation encapsulates the steps needed to take preview-sized images, which are used for
* both preview and decoding.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
final class CameraManager {
private static final String TAG = CameraManager.class.getSimpleName();
private static final int MIN_FRAME_WIDTH = 240;
private static final int MIN_FRAME_HEIGHT = 240;
private static final int MAX_FRAME_WIDTH = 480;
private static final int MAX_FRAME_HEIGHT = 360;
private static CameraManager cameraManager;
private static final Pattern SEMICOLON = Pattern.compile(";");
private Camera camera;
private final Context context;
private Point screenResolution;
private Point cameraResolution;
private Rect framingRect;
private Handler previewHandler;
private int previewMessage;
private Handler autoFocusHandler;
private int autoFocusMessage;
private boolean initialized;
private boolean previewing;
/**
* Preview frames are delivered here, which we pass on to the registered handler. Make sure to
* clear the handler so it will only receive one message.
*/
private final Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (previewHandler != null) {
Message message = previewHandler.obtainMessage(previewMessage, cameraResolution.x,
cameraResolution.y, data);
message.sendToTarget();
previewHandler = null;
}
}
};
/**
* Autofocus callbacks arrive here, and are dispatched to the Handler which requested them.
*/
private final Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (autoFocusHandler != null) {
Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
// Barcode Scanner needs to insert a delay here because it does continuous focus,
// but this test app does not, so send the message immediately.
message.sendToTarget();
autoFocusHandler = null;
}
}
};
/**
* Initializes this static object with the Context of the calling Activity.
*
* @param context The Activity which wants to use the camera.
*/
public static void init(Context context) {
if (cameraManager == null) {
cameraManager = new CameraManager(context);
}
}
/**
* Gets the CameraManager singleton instance.
*
* @return A reference to the CameraManager singleton.
*/
public static CameraManager get() {
return cameraManager;
}
private CameraManager(Context context) {
this.context = context;
camera = null;
initialized = false;
previewing = false;
}
/**
* Opens the camera driver and initializes the hardware parameters.
*
* @param holder The surface object which the camera will draw preview frames into.
* @throws IOException Indicates the camera driver failed to open.
*/
public String openDriver(SurfaceHolder holder, boolean getParameters) throws IOException {
String result = null;
if (camera == null) {
camera = Camera.open();
camera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
getScreenResolution();
}
if (getParameters) {
result = collectCameraParameters();
}
setCameraParameters();
}
return result;
}
/**
* Closes the camera driver if still in use.
*/
public void closeDriver() {
if (camera != null) {
camera.release();
camera = null;
}
}
/**
* Asks the camera hardware to begin drawing preview frames to the screen.
*/
public void startPreview() {
if (camera != null && !previewing) {
camera.startPreview();
previewing = true;
}
}
/**
* Tells the camera to stop drawing preview frames.
*/
public void stopPreview() {
if (camera != null && previewing) {
camera.stopPreview();
previewHandler = null;
autoFocusHandler = null;
previewing = false;
}
}
/**
* A single preview frame will be returned to the handler supplied. The data will arrive as byte[]
* in the message.obj field, with width and height encoded as message.arg1 and message.arg2,
* respectively.
*
* @param handler The handler to send the message to.
* @param message The what field of the message to be sent.
*/
public void requestPreviewFrame(Handler handler, int message) {
if (camera != null && previewing) {
previewHandler = handler;
previewMessage = message;
camera.setOneShotPreviewCallback(previewCallback);
}
}
/**
* Asks the camera hardware to perform an autofocus.
*
* @param handler The Handler to notify when the autofocus completes.
* @param message The message to deliver.
*/
public void requestAutoFocus(Handler handler, int message) {
if (camera != null && previewing) {
autoFocusHandler = handler;
autoFocusMessage = message;
camera.autoFocus(autoFocusCallback);
}
}
/**
* Calculates the framing rect which the UI should draw to show the user where to place the
* barcode. This target helps with alignment as well as forces the user to hold the device
* far enough away to ensure the image will be in focus.
*
* @return The rectangle to draw on screen in window coordinates.
*/
public Rect getFramingRect() {
if (framingRect == null) {
if (camera == null) {
return null;
}
int width = cameraResolution.x * 3 / 4;
if (width < MIN_FRAME_WIDTH) {
width = MIN_FRAME_WIDTH;
} else if (width > MAX_FRAME_WIDTH) {
width = MAX_FRAME_WIDTH;
}
int height = cameraResolution.y * 3 / 4;
if (height < MIN_FRAME_HEIGHT) {
height = MIN_FRAME_HEIGHT;
} else if (height > MAX_FRAME_HEIGHT) {
height = MAX_FRAME_HEIGHT;
}
int leftOffset = (cameraResolution.x - width) / 2;
int topOffset = (cameraResolution.y - height) / 2;
framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
Log.v(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}
/**
* Sets the camera up to take preview images which are used for both preview and decoding.
* We detect the preview format here so that buildLuminanceSource() can build an appropriate
* LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,
* and the planar Y can be used for barcode scanning without a copy in some cases.
*/
private void setCameraParameters() {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
Log.v(TAG, "Default preview size: " + size.width + ", " + size.height);
int previewFormat = parameters.getPreviewFormat();
String previewFormatString = parameters.get("preview-format");
Log.v(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
// Ensure that the camera resolution is a multiple of 8, as the screen may not be.
// IMPORTANT: Do not copy this old code. A much better and more robust solution can be found
// in Barcode Scanner under zxing/android.
cameraResolution = new Point();
cameraResolution.x = (screenResolution.x >> 3) << 3;
cameraResolution.y = (screenResolution.y >> 3) << 3;
Log.v(TAG, "Setting preview size: " + cameraResolution.x + ", " + cameraResolution.y);
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
camera.setParameters(parameters);
}
private String collectCameraParameters() {
Camera.Parameters parameters = camera.getParameters();
String[] params = SEMICOLON.split(parameters.flatten());
StringBuilder result = new StringBuilder(100);
result.append("Default camera parameters:");
for (String param : params) {
result.append("\n ");
result.append(param);
}
result.append('\n');
return result.toString();
}
private Point getScreenResolution() {
if (screenResolution == null) {
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
screenResolution = new Point(display.getWidth(), display.getHeight());
}
return screenResolution;
}
}

View file

@ -1,215 +0,0 @@
/*
* 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
*
* 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.androidtest;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public final class CameraTestActivity extends Activity implements SurfaceHolder.Callback {
private static final String TAG = CameraTestActivity.class.getSimpleName();
public static final String GET_CAMERA_PARAMETERS = "GET_CAMERA_PARAMETERS";
private static final String[] EMAIL_ADDRESS = {"zxing-external@google.com"};
private SaveThread saveThread;
private boolean getCameraParameters;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getCameraParameters = getIntent().getBooleanExtra(GET_CAMERA_PARAMETERS, false);
if (getCameraParameters) {
setContentView(R.layout.camera_parameters);
} else {
setContentView(R.layout.camera_test);
}
CameraManager.init(getApplication());
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
protected void onResume() {
super.onResume();
if (saveThread == null && !getCameraParameters) {
saveThread = new SaveThread(this);
saveThread.start();
}
}
@Override
protected void onPause() {
super.onPause();
CameraManager.get().stopPreview();
if (saveThread != null) {
Message quit = Message.obtain(saveThread.handler, R.id.quit);
quit.sendToTarget();
try {
saveThread.join();
} catch (InterruptedException e) {
// continue
}
saveThread = null;
}
CameraManager.get().closeDriver();
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case R.id.auto_focus:
// Do not continuously auto focus
break;
case R.id.save_succeeded:
Toast.makeText(CameraTestActivity.this, R.string.save_succeeded, 500).show();
break;
case R.id.save_failed:
Toast.makeText(CameraTestActivity.this, R.string.save_failed, 2000).show();
break;
}
}
};
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (!getCameraParameters) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
if (event.getRepeatCount() == 0) {
CameraManager.get().requestAutoFocus(handler, R.id.auto_focus);
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_CAMERA || keyCode == KeyEvent.KEYCODE_SEARCH) {
if (event.getRepeatCount() == 0) {
CameraManager.get().requestPreviewFrame(saveThread.handler, R.id.save);
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
String parameters = CameraManager.get().openDriver(holder, getCameraParameters);
CameraManager.get().startPreview();
if (getCameraParameters) {
collectStatsAndSendEmail(parameters);
}
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
private void collectStatsAndSendEmail(String parameters) {
StringBuilder result = new StringBuilder(1000);
result.append("Device info:");
result.append("\n Board: ");
result.append(Build.BOARD);
result.append("\n Brand: ");
result.append(Build.BRAND);
result.append("\n Device: ");
result.append(Build.DEVICE);
result.append("\n Display: ");
result.append(Build.DISPLAY);
result.append("\n Fingerprint: ");
result.append(Build.FINGERPRINT);
result.append("\n Host: ");
result.append(Build.HOST);
result.append("\n ID: ");
result.append(Build.ID);
result.append("\n Model: ");
result.append(Build.MODEL);
result.append("\n Product: ");
result.append(Build.PRODUCT);
result.append("\n Tags: ");
result.append(Build.TAGS);
result.append("\n Type: ");
result.append(Build.TYPE);
result.append("\n User: ");
result.append(Build.USER);
result.append("\n Version Incremental: ");
result.append(Build.VERSION.INCREMENTAL);
result.append("\n Version Release: ");
result.append(Build.VERSION.RELEASE);
result.append("\n Version SDK: ");
result.append(Build.VERSION.SDK);
result.append("\n\n");
result.append(parameters);
FileOutputStream stream = null;
try {
stream = new FileOutputStream(new File("/sdcard/CameraParameters.txt"));
stream.write(result.toString().getBytes());
} catch (IOException e) {
Log.e(TAG, "Cannot write parameters file ", e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Log.w(TAG, e);
}
}
}
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, EMAIL_ADDRESS);
intent.putExtra(Intent.EXTRA_SUBJECT, "Camera parameters report");
intent.putExtra(Intent.EXTRA_TEXT, result.toString());
intent.setType("text/plain");
startActivity(intent);
finish();
}
}

View file

@ -1,133 +0,0 @@
/*
* 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
*
* 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.androidtest;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
final class SaveThread extends Thread {
private static final String TAG = SaveThread.class.getSimpleName();
Handler handler;
private final CameraTestActivity mActivity;
SaveThread(CameraTestActivity activity) {
mActivity = activity;
}
@Override
public void run() {
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case R.id.save:
save((byte[]) message.obj, message.arg1, message.arg2);
break;
case R.id.quit:
Looper.myLooper().quit();
break;
}
}
};
Looper.loop();
}
// Save the center rectangle of the Y channel as a greyscale PNG to the SD card.
private void save(byte[] data, int width, int height) {
Rect framingRect = CameraManager.get().getFramingRect();
int framingWidth = framingRect.width();
int framingHeight = framingRect.height();
if (framingWidth > width || framingHeight > height) {
throw new IllegalArgumentException();
}
int leftOffset = framingRect.left;
int topOffset = framingRect.top;
int[] colors = new int[framingWidth * framingHeight];
for (int y = 0; y < framingHeight; y++) {
int rowOffset = (y + topOffset) * width + leftOffset;
for (int x = 0; x < framingWidth; x++) {
int pixel = (int) data[rowOffset + x];
pixel = 0xff000000 + (pixel << 16) + (pixel << 8) + pixel;
colors[y * framingWidth + x] = pixel;
}
}
Bitmap bitmap = Bitmap.createBitmap(colors, framingWidth, framingHeight,
Bitmap.Config.ARGB_8888);
OutputStream outStream = getNewPhotoOutputStream();
if (outStream != null) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
try {
outStream.close();
Message message = Message.obtain(mActivity.handler, R.id.save_succeeded);
message.sendToTarget();
return;
} catch (IOException e) {
Log.e(TAG, "Exception closing stream: " + e.toString());
}
}
Message message = Message.obtain(mActivity.handler, R.id.save_failed);
message.sendToTarget();
}
private static OutputStream getNewPhotoOutputStream() {
File sdcard = new File("/sdcard");
if (sdcard.exists()) {
File barcodes = new File(sdcard, "barcodes");
if (barcodes.exists()) {
if (!barcodes.isDirectory()) {
Log.e(TAG, "/sdcard/barcodes exists but is not a directory");
return null;
}
} else {
if (!barcodes.mkdir()) {
Log.e(TAG, "Could not create /sdcard/barcodes directory");
return null;
}
}
Date now = new Date();
String fileName = now.getTime() + ".png";
try {
return new FileOutputStream(new File(barcodes, fileName));
} catch (FileNotFoundException e) {
Log.e(TAG, "Could not create FileOutputStream");
}
} else {
Log.e(TAG, "/sdcard does not exist");
}
return null;
}
}

View file

@ -1,76 +0,0 @@
/*
* 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
*
* 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.androidtest;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
public final class ViewfinderView extends View {
private final Paint paint;
private final Rect box;
private final int maskColor;
private final int frameColor;
// This constructor is used when the class is built from an XML resource.
public ViewfinderView(Context context, AttributeSet attrs) {
super(context, attrs);
// Initialize these once for performance rather than calling them every time in onDraw().
paint = new Paint();
box = new Rect();
Resources resources = getResources();
maskColor = resources.getColor(R.color.viewfinder_mask);
frameColor = resources.getColor(R.color.viewfinder_frame);
}
@Override
public void onDraw(Canvas canvas) {
Rect frame = CameraManager.get().getFramingRect();
int width = canvas.getWidth();
int height = canvas.getHeight();
// Draw the exterior (i.e. outside the framing rect) darkened, in red to distinguish it from
// the regular barcodes app
paint.setColor(maskColor);
box.set(0, 0, width, frame.top);
canvas.drawRect(box, paint);
box.set(0, frame.top, frame.left, frame.bottom + 1);
canvas.drawRect(box, paint);
box.set(frame.right + 1, frame.top, width, frame.bottom + 1);
canvas.drawRect(box, paint);
box.set(0, frame.bottom + 1, width, height);
canvas.drawRect(box, paint);
// Draw a two pixel solid white border inside the framing rect
paint.setColor(frameColor);
box.set(frame.left, frame.top, frame.right + 1, frame.top + 2);
canvas.drawRect(box, paint);
box.set(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1);
canvas.drawRect(box, paint);
box.set(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1);
canvas.drawRect(box, paint);
box.set(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1);
canvas.drawRect(box, paint);
}
}

View file

@ -21,24 +21,36 @@ import android.app.AlertDialog;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.provider.Contacts;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Arrays;
public final class ZXingTestActivity extends Activity {
private static final String TAG = ZXingTestActivity.class.getSimpleName();
private static final int ABOUT_ID = Menu.FIRST;
private static final String PACKAGE_NAME = "com.google.zxing.client.androidtest";
private static final String PACKAGE_NAME = ZXingTestActivity.class.getPackage().getName();
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.test);
findViewById(R.id.take_test_photos).setOnClickListener(takeTestPhotos);
findViewById(R.id.get_camera_parameters).setOnClickListener(getCameraParameters);
findViewById(R.id.scan_product).setOnClickListener(scanProduct);
findViewById(R.id.scan_qr_code).setOnClickListener(scanQRCode);
@ -86,23 +98,30 @@ public final class ZXingTestActivity extends Activity {
}
return super.onOptionsItemSelected(item);
}
private final Button.OnClickListener takeTestPhotos = new Button.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName(ZXingTestActivity.this, CameraTestActivity.class.getName());
intent.putExtra(CameraTestActivity.GET_CAMERA_PARAMETERS, false);
startActivity(intent);
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (result != null) {
String contents = result.getContents();
if (contents != null) {
showDialog(R.string.result_succeeded, "Format: " + result.getFormatName() + "\nContents: " + contents);
} else {
showDialog(R.string.result_failed, getString(R.string.result_failed_why));
}
}
};
}
private final Button.OnClickListener getCameraParameters = new Button.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName(ZXingTestActivity.this, CameraTestActivity.class.getName());
intent.putExtra(CameraTestActivity.GET_CAMERA_PARAMETERS, true);
String stats = collectStats();
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, "zxing-external@google.com");
intent.putExtra(Intent.EXTRA_SUBJECT, "Camera parameters report");
intent.putExtra(Intent.EXTRA_TEXT, stats);
intent.setType("text/plain");
startActivity(intent);
}
};
@ -123,24 +142,23 @@ public final class ZXingTestActivity extends Activity {
intent.putExtra("SCAN_MODE", "PRODUCT_MODE");
intent.putExtra("SCAN_WIDTH", 800);
intent.putExtra("SCAN_HEIGHT", 200);
startActivityForResult(intent, 0);
startActivityForResult(intent, IntentIntegrator.REQUEST_CODE);
}
};
private final Button.OnClickListener scanQRCode = new Button.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
IntentIntegrator integrator = new IntentIntegrator(ZXingTestActivity.this);
integrator.initiateScan(IntentIntegrator.QR_CODE_TYPES);
}
};
private final Button.OnClickListener scanAnything = new Button.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
startActivityForResult(intent, 0);
IntentIntegrator integrator = new IntentIntegrator(ZXingTestActivity.this);
integrator.initiateScan();
}
};
@ -154,19 +172,6 @@ public final class ZXingTestActivity extends Activity {
}
};
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
showDialog(R.string.result_succeeded, "Format: " + format + "\nContents: " + contents);
} else if (resultCode == RESULT_CANCELED) {
showDialog(R.string.result_failed, getString(R.string.result_failed_why));
}
}
}
private final Button.OnClickListener encodeURL = new Button.OnClickListener() {
@Override
public void onClick(View v) {
@ -199,10 +204,10 @@ public final class ZXingTestActivity extends Activity {
@Override
public void onClick(View v) {
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");
bundle.putString(ContactsContract.Intents.Insert.NAME, "Jenny");
bundle.putString(ContactsContract.Intents.Insert.PHONE, "8675309");
bundle.putString(ContactsContract.Intents.Insert.EMAIL, "jenny@the80s.com");
bundle.putString(ContactsContract.Intents.Insert.POSTAL, "123 Fake St. San Francisco, CA 94102");
encodeBarcode("CONTACT_TYPE", bundle);
}
};
@ -264,4 +269,75 @@ public final class ZXingTestActivity extends Activity {
startActivity(intent);
}
private static String getFlattenedParams() {
Camera camera = Camera.open();
if (camera == null) {
return null;
}
try {
Camera.Parameters parameters = camera.getParameters();
if (parameters == null) {
return null;
}
return parameters.flatten();
} finally {
camera.release();
}
}
private static String collectStats() {
StringBuilder result = new StringBuilder(1000);
result.append("BOARD=").append(Build.BOARD).append('\n');
result.append("BRAND=").append(Build.BRAND).append('\n');
result.append("CPU_ABI=").append(Build.CPU_ABI).append('\n');
result.append("DEVICE=").append(Build.DEVICE).append('\n');
result.append("DISPLAY=").append(Build.DISPLAY).append('\n');
result.append("FINGERPRINT=").append(Build.FINGERPRINT).append('\n');
result.append("HOST=").append(Build.HOST).append('\n');
result.append("ID=").append(Build.ID).append('\n');
result.append("MANUFACTURER=").append(Build.MANUFACTURER).append('\n');
result.append("MODEL=").append(Build.MODEL).append('\n');
result.append("PRODUCT=").append(Build.PRODUCT).append('\n');
result.append("TAGS=").append(Build.TAGS).append('\n');
result.append("TIME=").append(Build.TIME).append('\n');
result.append("TYPE=").append(Build.TYPE).append('\n');
result.append("USER=").append(Build.USER).append('\n');
result.append("VERSION.CODENAME=").append(Build.VERSION.CODENAME).append('\n');
result.append("VERSION.INCREMENTAL=").append(Build.VERSION.INCREMENTAL).append('\n');
result.append("VERSION.RELEASE=").append(Build.VERSION.RELEASE).append('\n');
result.append("VERSION.SDK_INT=").append(Build.VERSION.SDK_INT).append('\n');
String flattened = getFlattenedParams();
String[] params = flattened.split(";");
Arrays.sort(params);
for (String param : params) {
result.append(param).append('\n');
}
String resultString = result.toString();
writeStats(resultString);
return resultString;
}
private static void writeStats(String resultString) {
Writer out = null;
try {
out = new OutputStreamWriter(new FileOutputStream(new File("/sdcard/CameraParameters.txt")),
Charset.forName("UTF-8"));
out.write(resultString);
} catch (IOException e) {
Log.e(TAG, "Cannot write parameters file ", e);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
Log.w(TAG, e);
}
}
}
}
}

View file

@ -130,9 +130,7 @@
<target name="clean">
<delete dir="build"/>
<delete dir="build-test"/>
<delete dir="optimized"/>
<delete file="core.jar"/>
<delete file="ZXingReader.*"/>
<delete file="proguard-dump.txt"/>
</target>

View file

@ -20,7 +20,7 @@
<artifactId>core</artifactId>
<packaging>jar</packaging>
<name>ZXing Core</name>
<version>1.6-SNAPSHOT</version>
<version>2.0-SNAPSHOT</version>
<description>Core barcode encoding/decoding library</description>
<url>http://code.google.com/p/zxing</url>
<inceptionYear>2007</inceptionYear>