Checked in the ZXing Test app for Android under androidtest. This application exercis...
authordswitkin <dswitkin@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Tue, 21 Oct 2008 21:55:15 +0000 (21:55 +0000)
committerdswitkin <dswitkin@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Tue, 21 Oct 2008 21:55:15 +0000 (21:55 +0000)
git-svn-id: http://zxing.googlecode.com/svn/trunk@629 59b500cc-1b3d-0410-9834-0bbf25fbcc57

14 files changed:
androidtest/AndroidManifest.xml [new file with mode: 0755]
androidtest/build.xml [new file with mode: 0644]
androidtest/res/drawable/icon.png [new file with mode: 0644]
androidtest/res/layout/camera_test.xml [new file with mode: 0755]
androidtest/res/layout/test.xml [new file with mode: 0755]
androidtest/res/values/attrs.xml [new file with mode: 0755]
androidtest/res/values/colors.xml [new file with mode: 0755]
androidtest/res/values/ids.xml [new file with mode: 0755]
androidtest/res/values/strings.xml [new file with mode: 0755]
androidtest/src/com/google/zxing/client/androidtest/CameraManager.java [new file with mode: 0755]
androidtest/src/com/google/zxing/client/androidtest/CameraTestActivity.java [new file with mode: 0755]
androidtest/src/com/google/zxing/client/androidtest/SaveThread.java [new file with mode: 0755]
androidtest/src/com/google/zxing/client/androidtest/ViewfinderView.java [new file with mode: 0755]
androidtest/src/com/google/zxing/client/androidtest/ZXingTestActivity.java [new file with mode: 0755]

diff --git a/androidtest/AndroidManifest.xml b/androidtest/AndroidManifest.xml
new file mode 100755 (executable)
index 0000000..35846c2
--- /dev/null
@@ -0,0 +1,33 @@
+<?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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.google.zxing.client.androidtest">
+  <application android:label="@string/app_name"
+               android:icon="@drawable/icon">
+    <activity android:name="ZXingTestActivity"
+              android:label="@string/app_name">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN"/>
+        <category android:name="android.intent.category.LAUNCHER"/>
+      </intent-filter>
+    </activity>
+    <activity android:name="CameraTestActivity"
+              android:screenOrientation="landscape">
+    </activity>
+  </application>
+  <uses-permission android:name="android.permission.CAMERA"/>
+</manifest>
diff --git a/androidtest/build.xml b/androidtest/build.xml
new file mode 100644 (file)
index 0000000..6c3f626
--- /dev/null
@@ -0,0 +1,289 @@
+<?xml version="1.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.
+-->
+<project name="ZXingTest" default="debug">
+  <!-- SDK Locations -->
+  <property file="../build.properties"/>
+  <property name="sdk-folder" value="${android-home}"/>
+  <property name="android-tools" value="${sdk-folder}/tools"/>
+
+  <!-- Application Package Name -->
+  <property name="application-package" value="com.google.zxing.client.androidtest" />
+
+  <!-- The intermediates directory -->
+  <!-- Eclipse uses "bin" for its own output, so we do the same. -->
+  <property name="outdir" value="bin" />
+
+  <!-- ************************************************************************************* -->
+  <!-- No user servicable parts below. -->
+
+  <property name="android-framework" value="${android-tools}/lib/framework.aidl" />
+
+  <!-- Input directories -->
+  <property name="resource-dir" value="res" />
+  <property name="asset-dir" value="assets" />
+  <property name="srcdir" value="src" />
+  <condition property="srcdir-ospath"
+             value="${basedir}\${srcdir}"
+             else="${basedir}/${srcdir}" >
+    <os family="windows"/>
+  </condition>
+
+  <property name="external-libs" value="../core" />
+  <condition property="external-libs-ospath"
+             value="${basedir}\${external-libs}"
+             else="${basedir}/${external-libs}" >
+    <os family="windows"/>
+  </condition>
+
+  <!-- Output directories -->
+  <property name="outdir-classes" value="${outdir}/classes" />
+  <condition property="outdir-classes-ospath"
+             value="${basedir}\${outdir-classes}"
+             else="${basedir}/${outdir-classes}" >
+    <os family="windows"/>
+  </condition>
+
+  <!-- Create R.java in the source directory -->
+  <property name="outdir-r" value="src" />
+
+  <!-- Intermediate files -->
+  <property name="dex-file" value="classes.dex" />
+  <property name="intermediate-dex" value="${outdir}/${dex-file}" />
+  <condition property="intermediate-dex-ospath"
+             value="${basedir}\${intermediate-dex}"
+             else="${basedir}/${intermediate-dex}" >
+    <os family="windows"/>
+  </condition>
+
+  <!-- The final package file to generate -->
+  <property name="resources-package" value="${outdir}/${ant.project.name}.ap_" />
+  <condition property="resources-package-ospath"
+             value="${basedir}\${resources-package}"
+             else="${basedir}/${resources-package}" >
+    <os family="windows"/>
+  </condition>
+
+  <property name="out-debug-package" value="${outdir}/${ant.project.name}-debug.apk" />
+  <condition property="out-debug-package-ospath"
+             value="${basedir}\${out-debug-package}"
+             else="${basedir}/${out-debug-package}" >
+    <os family="windows"/>
+  </condition>
+
+  <property name="out-unsigned-package" value="${outdir}/${ant.project.name}-unsigned.apk" />
+  <condition property="out-unsigned-package-ospath"
+             value="${basedir}\${out-unsigned-package}"
+             else="${basedir}/${out-unsigned-package}" >
+    <os family="windows"/>
+  </condition>
+
+  <!-- Tools -->
+  <condition property="aapt" value="${android-tools}/aapt.exe" else="${android-tools}/aapt" >
+    <os family="windows"/>
+  </condition>
+  <condition property="aidl" value="${android-tools}/aidl.exe" else="${android-tools}/aidl" >
+    <os family="windows"/>
+  </condition>
+  <condition property="adb" value="${android-tools}/adb.exe" else="${android-tools}/adb" >
+    <os family="windows"/>
+  </condition>
+  <condition property="dx" value="${android-tools}/dx.bat" else="${android-tools}/dx" >
+    <os family="windows"/>
+  </condition>
+  <condition property="apk-builder" value="${android-tools}/apkbuilder.bat" else="${android-tools}/apkbuilder" >
+    <os family="windows"/>
+  </condition>
+
+  <property name="android-jar" value="${sdk-folder}/android.jar" />
+
+  <!-- Rules -->
+
+  <!-- Create the output directories if they don't exist yet. -->
+  <target name="dirs">
+    <echo>Creating output directories if needed...</echo>
+    <mkdir dir="${outdir}" />
+    <mkdir dir="${outdir-classes}" />
+  </target>
+
+  <!-- Generate the R.java file for this project's resources. -->
+  <target name="resource-src" depends="dirs">
+    <echo>Generating R.java / Manifest.java from the resources...</echo>
+    <exec executable="${aapt}" failonerror="true">
+      <arg value="package" />
+      <arg value="-m" />
+      <arg value="-J" />
+      <arg value="${outdir-r}" />
+      <arg value="-M" />
+      <arg value="AndroidManifest.xml" />
+      <arg value="-S" />
+      <arg value="${resource-dir}" />
+      <arg value="-I" />
+      <arg value="${android-jar}" />
+    </exec>
+  </target>
+
+  <!-- Generate java classes from .aidl files. -->
+  <target name="aidl" depends="dirs">
+    <echo>Compiling aidl files into Java classes...</echo>
+    <apply executable="${aidl}" failonerror="true">
+      <arg value="-p${android-framework}" />
+      <arg value="-I${srcdir}" />
+      <fileset dir="${srcdir}">
+        <include name="**/*.aidl"/>
+      </fileset>
+    </apply>
+  </target>
+
+  <!-- Compile this project's .java files into .class files. -->
+  <target name="compile" depends="dirs, resource-src, aidl">
+    <javac encoding="ascii" target="1.5" debug="true" extdirs=""
+           srcdir="."
+           destdir="${outdir-classes}"
+           bootclasspath="${android-jar}">
+      <classpath>
+        <fileset dir="${external-libs}" includes="*.jar"/>
+      </classpath>
+    </javac>
+  </target>
+
+  <!-- Convert this project's .class files into .dex files. -->
+  <target name="dex" depends="compile">
+    <echo>Converting compiled files and external libraries into ${outdir}/${dex-file}...</echo>
+    <apply executable="${dx}" failonerror="true" parallel="true">
+      <arg value="--dex" />
+      <arg value="--output=${intermediate-dex-ospath}" />
+      <arg path="${outdir-classes-ospath}" />
+      <fileset dir="${external-libs}" includes="*.jar"/>
+    </apply>
+  </target>
+
+  <!-- Put the project's resources into the output package file. -->
+  <target name="package-res-and-assets">
+    <echo>Packaging resources and assets...</echo>
+    <exec executable="${aapt}" failonerror="true">
+      <arg value="package" />
+      <arg value="-f" />
+      <arg value="-M" />
+      <arg value="AndroidManifest.xml" />
+      <arg value="-S" />
+      <arg value="${resource-dir}" />
+      <arg value="-A" />
+      <arg value="${asset-dir}" />
+      <arg value="-I" />
+      <arg value="${android-jar}" />
+      <arg value="-F" />
+      <arg value="${resources-package}" />
+    </exec>
+  </target>
+
+  <!-- Same as package-res-and-assets, but without "-A ${asset-dir}" -->
+  <target name="package-res-no-assets">
+    <echo>Packaging resources...</echo>
+    <exec executable="${aapt}" failonerror="true">
+      <arg value="package" />
+      <arg value="-f" />
+      <arg value="-M" />
+      <arg value="AndroidManifest.xml" />
+      <arg value="-S" />
+      <arg value="${resource-dir}" />
+      <!-- No assets directory -->
+      <arg value="-I" />
+      <arg value="${android-jar}" />
+      <arg value="-F" />
+      <arg value="${resources-package}" />
+    </exec>
+  </target>
+
+  <!-- Invoke the proper target depending on whether or not
+an assets directory is present. -->
+  <!-- TODO: find a nicer way to include the "-A ${asset-dir}" argument
+only when the assets dir exists. -->
+  <target name="package-res">
+    <available file="${asset-dir}" type="dir"
+               property="res-target" value="and-assets" />
+    <property name="res-target" value="no-assets" />
+    <antcall target="package-res-${res-target}" />
+  </target>
+
+  <!-- Package the application and sign it with a debug key.
+      This is the default target when building. It is used for debug. -->
+  <target name="debug" depends="dex, package-res">
+    <echo>Packaging ${out-debug-package}, and signing it with a debug key...</echo>
+    <exec executable="${apk-builder}" failonerror="true">
+      <arg value="${out-debug-package-ospath}" />
+      <arg value="-z" />
+      <arg value="${resources-package-ospath}" />
+      <arg value="-f" />
+      <arg value="${intermediate-dex-ospath}" />
+      <arg value="-rf" />
+      <arg value="${srcdir-ospath}" />
+      <arg value="-rj" />
+      <arg value="${external-libs-ospath}" />
+    </exec>
+  </target>
+
+  <!-- Package the application without signing it.
+        This allows for the application to be signed later with an official publishing key. -->
+  <target name="release" depends="dex, package-res">
+    <echo>Packaging ${out-unsigned-package} for release...</echo>
+    <exec executable="${apk-builder}" failonerror="true">
+      <arg value="${out-unsigned-package-ospath}" />
+      <arg value="-u" />
+      <arg value="-z" />
+      <arg value="${resources-package-ospath}" />
+      <arg value="-f" />
+      <arg value="${intermediate-dex-ospath}" />
+      <arg value="-rf" />
+      <arg value="${srcdir-ospath}" />
+      <arg value="-rj" />
+      <arg value="${external-libs-ospath}" />
+    </exec>
+    <echo>It will need to be signed with jarsigner before being published.</echo>
+  </target>
+
+  <!-- Install the package on the default emulator -->
+  <target name="install" depends="debug">
+    <echo>Installing ${out-debug-package} onto default emulator...</echo>
+    <exec executable="${adb}" failonerror="true">
+      <arg value="install" />
+      <arg value="${out-debug-package}" />
+    </exec>
+  </target>
+
+  <target name="reinstall" depends="debug">
+    <echo>Installing ${out-debug-package} onto default emulator...</echo>
+    <exec executable="${adb}" failonerror="true">
+      <arg value="install" />
+      <arg value="-r" />
+      <arg value="${out-debug-package}" />
+    </exec>
+  </target>
+
+  <!-- Uinstall the package from the default emulator -->
+  <target name="uninstall">
+    <echo>Uninstalling ${application-package} from the default emulator...</echo>
+    <exec executable="${adb}" failonerror="true">
+      <arg value="uninstall" />
+      <arg value="${application-package}" />
+    </exec>
+  </target>
+
+  <target name="clean">
+    <delete dir="${outdir}"/>
+  </target>
+
+</project>
diff --git a/androidtest/res/drawable/icon.png b/androidtest/res/drawable/icon.png
new file mode 100644 (file)
index 0000000..45c603d
Binary files /dev/null and b/androidtest/res/drawable/icon.png differ
diff --git a/androidtest/res/layout/camera_test.xml b/androidtest/res/layout/camera_test.xml
new file mode 100755 (executable)
index 0000000..30a30a8
--- /dev/null
@@ -0,0 +1,63 @@
+<?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"/>
+
+    <FrameLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:background="@color/status_view"
+        android:baselineAligned="false"
+        android:padding="4px">
+
+      <TextView android:id="@+id/status_text_view"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="left|center_vertical"
+                android:text="@string/status_message"
+                android:textColor="@color/status_text"/>
+
+    </FrameLayout>
+
+  </LinearLayout>
+
+</FrameLayout>
diff --git a/androidtest/res/layout/test.xml b/androidtest/res/layout/test.xml
new file mode 100755 (executable)
index 0000000..e0c752a
--- /dev/null
@@ -0,0 +1,78 @@
+<?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.
+ -->
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="fill_parent"
+             android:layout_height="fill_parent"
+             android:gravity="center_horizontal"
+             android:padding="10px">
+  <TableRow>
+    <Button android:id="@+id/scan_product"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/scan_product"/>
+    <Button android:id="@+id/scan_qr_code"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/scan_qr_code"/>
+  </TableRow>
+  <TableRow>
+    <Button android:id="@+id/test_camera"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/test_camera"/>
+    <Button android:id="@+id/search_book_contents"
+            android:layout_width="wrap_content"
+            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_height="wrap_content"
+            android:text="@string/encode_url"/>
+    <Button android:id="@+id/encode_email"
+            android:layout_width="wrap_content"
+            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_height="wrap_content"
+            android:text="@string/encode_phone"/>
+    <Button android:id="@+id/encode_sms"
+            android:layout_width="wrap_content"
+            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_height="wrap_content"
+            android:text="@string/encode_contact"/>
+    <Button android:id="@+id/encode_location"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/encode_location"/>
+  </TableRow>
+  <TableRow>
+    <Button android:id="@+id/encode_bad_data"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/encode_bad_data"/>
+  </TableRow>
+</TableLayout>
diff --git a/androidtest/res/values/attrs.xml b/androidtest/res/values/attrs.xml
new file mode 100755 (executable)
index 0000000..5ce5c86
--- /dev/null
@@ -0,0 +1,20 @@
+<?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>
diff --git a/androidtest/res/values/colors.xml b/androidtest/res/values/colors.xml
new file mode 100755 (executable)
index 0000000..7b9b504
--- /dev/null
@@ -0,0 +1,23 @@
+<?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>
+  <color name="status_view">#50000000</color>
+  <color name="status_text">#ffffffff</color>
+  <color name="transparent">#00000000</color>
+  <color name="viewfinder_frame">#ffffffff</color>
+  <color name="viewfinder_mask">#ccff0000</color>
+</resources>
diff --git a/androidtest/res/values/ids.xml b/androidtest/res/values/ids.xml
new file mode 100755 (executable)
index 0000000..72bf92f
--- /dev/null
@@ -0,0 +1,24 @@
+<?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>
+  <!-- Messages IDs -->
+  <item type="id" name="auto_focus"/>
+  <item type="id" name="quit"/>
+  <item type="id" name="save"/>
+  <item type="id" name="save_succeeded"/>
+  <item type="id" name="save_failed"/>
+</resources>
diff --git a/androidtest/res/values/strings.xml b/androidtest/res/values/strings.xml
new file mode 100755 (executable)
index 0000000..e786edd
--- /dev/null
@@ -0,0 +1,36 @@
+<?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>
+  <string name="app_name">ZXing Test</string>
+  <string name="scan_product">Scan product</string>
+  <string name="scan_qr_code">Scan QR Code</string>
+  <string name="search_book_contents">Search Book Contents</string>
+  <string name="test_camera">Test camera</string>
+  <string name="encode_url">Encode URL</string>
+  <string name="encode_email">Encode email</string>
+  <string name="encode_phone">Encode phone</string>
+  <string name="encode_sms">Encode SMS</string>
+  <string name="encode_contact">Encode contact</string>
+  <string name="encode_location">Encode location</string>
+  <string name="encode_bad_data">Encode bad data</string>
+  <string name="result_failed">No barcode found</string>
+  <string name="result_failed_why">"The user gave up and pressed Back"</string>
+  <string name="result_succeeded">Found barcode</string>
+  <string name="status_message">Press the shutter button to save images to the SD card for testing purposes. Press DPAD_CENTER to trigger autofocus.</string>
+  <string name="save_succeeded">Save succeeded</string>
+  <string name="save_failed">Save failed - is the SD card installed?</string>
+</resources>
diff --git a/androidtest/src/com/google/zxing/client/androidtest/CameraManager.java b/androidtest/src/com/google/zxing/client/androidtest/CameraManager.java
new file mode 100755 (executable)
index 0000000..049aefc
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * 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.view.Display;
+import android.view.SurfaceHolder;
+import android.view.WindowManager;
+
+/**
+ * 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.
+ */
+final class CameraManager {
+
+  private static final String TAG = "CameraManager";
+
+  private static CameraManager mCameraManager;
+  private Camera mCamera;
+  private final Context mContext;
+  private Point mScreenResolution;
+  private Rect mFramingRect;
+  private Handler mPreviewHandler;
+  private int mPreviewMessage;
+  private Handler mAutoFocusHandler;
+  private int mAutoFocusMessage;
+  private boolean mPreviewing;
+
+  public static void init(Context context) {
+    if (mCameraManager == null) {
+      mCameraManager = new CameraManager(context);
+      mCameraManager.getScreenResolution();
+    }
+  }
+
+  public static CameraManager get() {
+    return mCameraManager;
+  }
+
+  private CameraManager(Context context) {
+    mContext = context;
+    mCamera = null;
+    mPreviewing = false;
+  }
+
+  public void openDriver(SurfaceHolder holder) {
+    if (mCamera == null) {
+      mCamera = Camera.open();
+      mCamera.setPreviewDisplay(holder);
+
+      setCameraParameters();
+    }
+  }
+
+  public void closeDriver() {
+    if (mCamera != null) {
+      mCamera.release();
+      mCamera = null;
+    }
+  }
+
+  public void startPreview() {
+    if (mCamera != null && !mPreviewing) {
+      mCamera.startPreview();
+      mPreviewing = true;
+    }
+  }
+
+  public void stopPreview() {
+    if (mCamera != null && mPreviewing) {
+      mCamera.setPreviewCallback(null);
+      mCamera.stopPreview();
+      mPreviewHandler = null;
+      mAutoFocusHandler = null;
+      mPreviewing = 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 (mCamera != null && mPreviewing) {
+      mPreviewHandler = handler;
+      mPreviewMessage = message;
+      mCamera.setPreviewCallback(previewCallback);
+    }
+  }
+
+  public void requestAutoFocus(Handler handler, int message) {
+    if (mCamera != null && mPreviewing) {
+      mAutoFocusHandler = handler;
+      mAutoFocusMessage = message;
+      mCamera.autoFocus(autoFocusCallback);
+    }
+  }
+
+  /**
+   * Calculates the framing rect which the UI should draw to show the user where to place the
+   * barcode. The actual captured image should be a bit larger than indicated because they might
+   * frame the shot too tightly. 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 (mFramingRect == null) {
+      int size = ((mScreenResolution.x < mScreenResolution.y) ? mScreenResolution.x :
+          mScreenResolution.y) * 3 / 4;
+      int leftOffset = (mScreenResolution.x - size) / 2;
+      int topOffset = (mScreenResolution.y - size) / 2;
+      mFramingRect = new Rect(leftOffset, topOffset, leftOffset + size, topOffset + size);
+    }
+    return mFramingRect;
+  }
+
+  /**
+   * 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() {
+    public void onPreviewFrame(byte[] data, Camera camera) {
+      camera.setPreviewCallback(null);
+      if (mPreviewHandler != null) {
+        Message message = mPreviewHandler.obtainMessage(mPreviewMessage,
+            mScreenResolution.x, mScreenResolution.y, data);
+        message.sendToTarget();
+        mPreviewHandler = null;
+      }
+    }
+  };
+
+  private final Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
+    public void onAutoFocus(boolean success, Camera camera) {
+      if (mAutoFocusHandler != null) {
+        Message message = mAutoFocusHandler.obtainMessage(mAutoFocusMessage, success);
+        // The Barcodes app needs to insert a delay here because it does continuous focus,
+        // but this test app does not, so send the message immediately.
+        message.sendToTarget();
+        mAutoFocusHandler = null;
+      }
+    }
+  };
+
+  /**
+   * Sets the camera up to take preview images which are used for both preview and decoding. We're
+   * counting on the default YUV420 semi-planar data. If that changes in the future, we'll need to
+   * specify it explicitly with setPreviewFormat().
+   */
+  private void setCameraParameters() {
+    Camera.Parameters parameters = mCamera.getParameters();
+    parameters.setPreviewSize(mScreenResolution.x, mScreenResolution.y);
+    mCamera.setParameters(parameters);
+  }
+
+  private Point getScreenResolution() {
+    if (mScreenResolution == null) {
+      WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+      Display display = wm.getDefaultDisplay();
+      mScreenResolution = new Point(display.getWidth(), display.getHeight());
+    }
+    return mScreenResolution;
+  }
+
+}
diff --git a/androidtest/src/com/google/zxing/client/androidtest/CameraTestActivity.java b/androidtest/src/com/google/zxing/client/androidtest/CameraTestActivity.java
new file mode 100755 (executable)
index 0000000..1bb30f7
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Toast;
+
+public final class CameraTestActivity extends Activity implements SurfaceHolder.Callback {
+
+  private SaveThread mSaveThread;
+
+  @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);
+    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 (mSaveThread == null) {
+      mSaveThread = new SaveThread(this, CameraManager.get().getFramingRect());
+      mSaveThread.start();
+    }
+  }
+
+  @Override
+  protected void onPause() {
+    super.onPause();
+
+    CameraManager.get().stopPreview();
+    if (mSaveThread != null) {
+      Message quit = Message.obtain(mSaveThread.mHandler, R.id.quit);
+      quit.sendToTarget();
+      try {
+        mSaveThread.join();
+      } catch (InterruptedException e) {
+      }
+      mSaveThread = null;
+    }
+    CameraManager.get().closeDriver();
+  }
+
+  public Handler mHandler = new Handler() {
+    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 (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+      if (event.getRepeatCount() == 0) {
+        CameraManager.get().requestAutoFocus(mHandler, R.id.auto_focus);
+      }
+      return true;
+    } else if (keyCode == KeyEvent.KEYCODE_CAMERA) {
+      if (event.getRepeatCount() == 0) {
+        CameraManager.get().requestPreviewFrame(mSaveThread.mHandler, R.id.save);
+      }
+      return true;
+    }
+    return super.onKeyDown(keyCode, event);
+  }
+
+  public void surfaceCreated(SurfaceHolder holder) {
+    CameraManager.get().openDriver(holder);
+    CameraManager.get().startPreview();
+  }
+
+  public void surfaceDestroyed(SurfaceHolder holder) {
+
+  }
+
+  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+
+  }
+
+}
diff --git a/androidtest/src/com/google/zxing/client/androidtest/SaveThread.java b/androidtest/src/com/google/zxing/client/androidtest/SaveThread.java
new file mode 100755 (executable)
index 0000000..583db57
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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";
+
+  public Handler mHandler;
+
+  private CameraTestActivity mActivity;
+  private Rect mFramingRect;
+
+  SaveThread(CameraTestActivity activity, Rect framingRect) {
+    mActivity = activity;
+    mFramingRect = framingRect;
+  }
+
+  @Override
+  public void run() {
+    Looper.prepare();
+    mHandler = new Handler() {
+      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 JPEG to the SD card
+  private void save(byte[] data, int width, int height) {
+    int framingWidth = mFramingRect.width();
+    int framingHeight = mFramingRect.height();
+    assert (framingWidth <= width);
+    assert (framingHeight <= height);
+
+    int leftOffset = mFramingRect.left;
+    int topOffset = mFramingRect.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.JPEG, 80, outStream);
+      try {
+        outStream.close();
+        Message message = Message.obtain(mActivity.mHandler, R.id.save_succeeded);
+        message.sendToTarget();
+        return;
+      } catch (IOException e) {
+        Log.e(TAG, "Exception closing stream: " + e.toString());
+      }
+    }
+
+    Message message = Message.obtain(mActivity.mHandler, R.id.save_failed);
+    message.sendToTarget();
+  }
+
+  private 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() + ".jpg";
+      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;
+  }
+
+}
diff --git a/androidtest/src/com/google/zxing/client/androidtest/ViewfinderView.java b/androidtest/src/com/google/zxing/client/androidtest/ViewfinderView.java
new file mode 100755 (executable)
index 0000000..6511572
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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 class ViewfinderView extends View {
+
+  private Paint mPaint;
+  private Rect mBox;
+  private int mMaskColor;
+  private int mFrameColor;
+
+  // 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().
+    mPaint = new Paint();
+    mBox = new Rect();
+    Resources resources = getResources();
+    mMaskColor = resources.getColor(R.color.viewfinder_mask);
+    mFrameColor = 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
+    mPaint.setColor(mMaskColor);
+    mBox.set(0, 0, width, frame.top);
+    canvas.drawRect(mBox, mPaint);
+    mBox.set(0, frame.top, frame.left, frame.bottom + 1);
+    canvas.drawRect(mBox, mPaint);
+    mBox.set(frame.right + 1, frame.top, width, frame.bottom + 1);
+    canvas.drawRect(mBox, mPaint);
+    mBox.set(0, frame.bottom + 1, width, height);
+    canvas.drawRect(mBox, mPaint);
+
+    // Draw a two pixel solid white border inside the framing rect
+    mPaint.setColor(mFrameColor);
+    mBox.set(frame.left, frame.top, frame.right + 1, frame.top + 2);
+    canvas.drawRect(mBox, mPaint);
+    mBox.set(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1);
+    canvas.drawRect(mBox, mPaint);
+    mBox.set(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1);
+    canvas.drawRect(mBox, mPaint);
+    mBox.set(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1);
+    canvas.drawRect(mBox, mPaint);
+  }
+
+}
diff --git a/androidtest/src/com/google/zxing/client/androidtest/ZXingTestActivity.java b/androidtest/src/com/google/zxing/client/androidtest/ZXingTestActivity.java
new file mode 100755 (executable)
index 0000000..9df7be9
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * 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.app.AlertDialog;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Contacts;
+import android.view.View;
+import android.widget.Button;
+
+public class ZXingTestActivity extends Activity {
+
+  @Override
+  public void onCreate(Bundle icicle) {
+    super.onCreate(icicle);
+
+    setContentView(R.layout.test);
+
+    Button scan_product = (Button) findViewById(R.id.scan_product);
+    scan_product.setOnClickListener(mScanProduct);
+
+    Button scan_qr_code = (Button) findViewById(R.id.scan_qr_code);
+    scan_qr_code.setOnClickListener(mScanQRCode);
+
+    Button test_camera = (Button) findViewById(R.id.test_camera);
+    test_camera.setOnClickListener(mTestCamera);
+
+    Button search_book_contents = (Button) findViewById(R.id.search_book_contents);
+    search_book_contents.setOnClickListener(mSearchBookContents);
+
+    Button encode_url = (Button) findViewById(R.id.encode_url);
+    encode_url.setOnClickListener(mEncodeURL);
+
+    Button encode_email = (Button) findViewById(R.id.encode_email);
+    encode_email.setOnClickListener(mEncodeEmail);
+
+    Button encode_phone = (Button) findViewById(R.id.encode_phone);
+    encode_phone.setOnClickListener(mEncodePhone);
+
+    Button encode_sms = (Button) findViewById(R.id.encode_sms);
+    encode_sms.setOnClickListener(mEncodeSMS);
+
+    Button encode_contact = (Button) findViewById(R.id.encode_contact);
+    encode_contact.setOnClickListener(mEncodeContact);
+
+    Button encode_location = (Button) findViewById(R.id.encode_location);
+    encode_location.setOnClickListener(mEncodeLocation);
+
+    Button encode_bad_data = (Button) findViewById(R.id.encode_bad_data);
+    encode_bad_data.setOnClickListener(mEncodeBadData);
+  }
+
+  public Button.OnClickListener mScanProduct = new Button.OnClickListener() {
+    public void onClick(View v) {
+      Intent intent = new Intent("com.google.zxing.client.android.SCAN");
+      intent.putExtra("SCAN_MODE", "PRODUCT_MODE");
+      startActivityForResult(intent, 0);
+    }
+  };
+
+  public Button.OnClickListener mScanQRCode = new Button.OnClickListener() {
+    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);
+    }
+  };
+
+  public Button.OnClickListener mTestCamera = new Button.OnClickListener() {
+    public void onClick(View v) {
+      Intent intent = new Intent(Intent.ACTION_VIEW);
+      intent.setClassName(ZXingTestActivity.this, CameraTestActivity.class.getName());
+      startActivity(intent);
+    }
+  };
+
+  public Button.OnClickListener mSearchBookContents = new Button.OnClickListener() {
+    public void onClick(View v) {
+      Intent intent = new Intent("com.google.zxing.client.android.SEARCH_BOOK_CONTENTS");
+      intent.putExtra("ISBN", "9780441014989");
+      intent.putExtra("QUERY", "future");
+      startActivity(intent);
+    }
+  };
+
+  @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));
+      }
+    }
+  }
+
+  public Button.OnClickListener mEncodeURL = new Button.OnClickListener() {
+    public void onClick(View v) {
+      encodeBarcode("TEXT_TYPE", "http://www.nytimes.com");
+    }
+  };
+
+  public Button.OnClickListener mEncodeEmail = new Button.OnClickListener() {
+    public void onClick(View v) {
+      encodeBarcode("EMAIL_TYPE", "foo@example.com");
+    }
+  };
+
+  public Button.OnClickListener mEncodePhone = new Button.OnClickListener() {
+    public void onClick(View v) {
+      encodeBarcode("PHONE_TYPE", "2125551212");
+    }
+  };
+
+  public Button.OnClickListener mEncodeSMS = new Button.OnClickListener() {
+    public void onClick(View v) {
+      encodeBarcode("SMS_TYPE", "2125551212");
+    }
+  };
+
+  public Button.OnClickListener mEncodeContact = new Button.OnClickListener() {
+    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");
+      encodeBarcode("CONTACT_TYPE", bundle);
+    }
+  };
+
+  public Button.OnClickListener mEncodeLocation = new Button.OnClickListener() {
+    public void onClick(View v) {
+      Bundle bundle = new Bundle();
+      bundle.putFloat("LAT", 40.829208f);
+      bundle.putFloat("LONG", -74.191279f);
+      encodeBarcode("LOCATION_TYPE", bundle);
+    }
+  };
+
+  public Button.OnClickListener mEncodeBadData = new Button.OnClickListener() {
+    public void onClick(View v) {
+      encodeBarcode(null, "bar");
+    }
+  };
+
+  private void showDialog(int title, String message) {
+    AlertDialog.Builder builder = new AlertDialog.Builder(this);
+    builder.setTitle(title);
+    builder.setMessage(message);
+    builder.setPositiveButton("OK", null);
+    builder.show();
+  }
+
+  private void encodeBarcode(String type, String data) {
+    Intent intent = new Intent("com.google.zxing.client.android.ENCODE");
+    intent.putExtra("ENCODE_TYPE", type);
+    intent.putExtra("ENCODE_DATA", data);
+    startActivity(intent);
+  }
+
+  private void encodeBarcode(String type, Bundle data) {
+    Intent intent = new Intent("com.google.zxing.client.android.ENCODE");
+    intent.putExtra("ENCODE_TYPE", type);
+    intent.putExtra("ENCODE_DATA", data);
+    startActivity(intent);
+  }
+
+}