mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
The new 0.9 SDK Android client (for real this time).
git-svn-id: https://zxing.googlecode.com/svn/trunk@569 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
de73980d99
commit
fecaba26de
48
android/AndroidManifest.xml
Executable file
48
android/AndroidManifest.xml
Executable file
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Google Inc.
|
||||
|
||||
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.android.barcodes">
|
||||
<application android:icon="@drawable/ic_launcher_barcodes"
|
||||
android:label="@string/app_name">
|
||||
<activity android:name=".BarcodesCaptureActivity"
|
||||
android:screenOrientation="landscape"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.android.barcodes.SCAN"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="BarcodesPreferenceActivity"
|
||||
android:label="@string/preferences_name">
|
||||
</activity>
|
||||
<activity android:name="BarcodesEncodeActivity"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.barcodes.ENCODE"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
274
android/build.xml
Normal file
274
android/build.xml
Normal file
|
@ -0,0 +1,274 @@
|
|||
<?xml version="1.0" ?>
|
||||
<project name="BarcodeScanner" 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.android.barcodes" />
|
||||
|
||||
<!-- 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>
|
BIN
android/res/drawable/ic_launcher_barcodes.png
Executable file
BIN
android/res/drawable/ic_launcher_barcodes.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
BIN
android/res/drawable/zxing_icon.png
Executable file
BIN
android/res/drawable/zxing_icon.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
71
android/res/layout/capture.xml
Executable file
71
android/res/layout/capture.xml
Executable file
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Google Inc.
|
||||
|
||||
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.android.barcodes.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"/>
|
||||
|
||||
<LinearLayout android:id="@+id/status_view"
|
||||
android:orientation="horizontal"
|
||||
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="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left|center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/msg_default_status"
|
||||
android:textColor="@color/status_text"/>
|
||||
|
||||
<Button android:id="@+id/status_action_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center|fill_horizontal"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
38
android/res/layout/encode.xml
Executable file
38
android/res/layout/encode.xml
Executable file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Google Inc.
|
||||
|
||||
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.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/encode_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@color/encode_view"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView android:id="@+id/image_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:scaleType="center"/>
|
||||
|
||||
<TextView android:id="@+id/contents_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/contents_text"
|
||||
android:textSize="20.0sp"/>
|
||||
</LinearLayout>
|
BIN
android/res/raw/beep.ogg
Executable file
BIN
android/res/raw/beep.ogg
Executable file
Binary file not shown.
20
android/res/values/attrs.xml
Executable file
20
android/res/values/attrs.xml
Executable file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Google Inc.
|
||||
|
||||
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>
|
27
android/res/values/colors.xml
Executable file
27
android/res/values/colors.xml
Executable file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Google Inc.
|
||||
|
||||
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="contents_text">#000000</color>
|
||||
<color name="encode_view">#ffffff</color>
|
||||
<color name="result_points">#c000ff00</color>
|
||||
<color name="status_view">#50000000</color>
|
||||
<color name="status_text">#ffffffff</color>
|
||||
<color name="transparent">#00000000</color>
|
||||
<color name="viewfinder_frame">#ff000000</color>
|
||||
<color name="viewfinder_laser">#ff0000</color>
|
||||
<color name="viewfinder_mask">#60000000</color>
|
||||
</resources>
|
28
android/res/values/ids.xml
Executable file
28
android/res/values/ids.xml
Executable file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Google Inc.
|
||||
|
||||
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="decode"/>
|
||||
<item type="id" name="decode_failed"/>
|
||||
<item type="id" name="decode_succeeded"/>
|
||||
<item type="id" name="encode_failed"/>
|
||||
<item type="id" name="encode_succeeded"/>
|
||||
<item type="id" name="quit"/>
|
||||
<item type="id" name="restart_preview"/>
|
||||
<item type="id" name="return_scan_result"/>
|
||||
</resources>
|
58
android/res/values/strings.xml
Executable file
58
android/res/values/strings.xml
Executable file
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Google Inc.
|
||||
|
||||
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">Barcode Scanner</string>
|
||||
|
||||
<string name="button_add_contact">Add contact</string>
|
||||
<string name="button_cancel">Cancel</string>
|
||||
<string name="button_dial">Dial</string>
|
||||
<string name="button_email">Email</string>
|
||||
<string name="button_lookup_product">Look up product</string>
|
||||
<string name="button_ok">OK</string>
|
||||
<string name="button_open_browser">Open browser</string>
|
||||
<string name="button_show_map">Show map</string>
|
||||
|
||||
<string name="contents_contact">Contact info</string>
|
||||
<string name="contents_email">Email address</string>
|
||||
<string name="contents_location">Geographic coordinates</string>
|
||||
<string name="contents_phone">Phone number</string>
|
||||
<string name="contents_sms">SMS address</string>
|
||||
<string name="contents_text">Plain text</string>
|
||||
|
||||
<string name="menu_about">About</string>
|
||||
<string name="menu_help">Help</string>
|
||||
<string name="menu_settings">Settings</string>
|
||||
|
||||
<string name="msg_about">Based on the ZXing Barcode Library</string>
|
||||
<string name="msg_encode_barcode_failed">Could not retrieve a barcode from the network.</string>
|
||||
<string name="msg_encode_contents_failed">Could not encode a barcode from the data provided.</string>
|
||||
<string name="msg_encode_in_progress">Generating a barcode\u2026</string>
|
||||
<string name="msg_help">Barcode Scanner continuously scans the viewfinder rectangle, so there\'s no need to press the shutter button. If you\'re having trouble, make sure to hold the phone steady. If the camera is unable to focus, try moving further back from the barcode.</string>
|
||||
<string name="msg_default_status">Place a barcode inside the viewfinder rectangle to read it.</string>
|
||||
|
||||
<string name="preferences_decode_1D_title">Decode 1D barcodes</string>
|
||||
<string name="preferences_decode_QR_title">Decode QR Codes</string>
|
||||
<string name="preferences_general_title">General settings</string>
|
||||
<string name="preferences_name">Settings</string>
|
||||
<string name="preferences_play_beep_title">Beep when a barcode is found</string>
|
||||
<string name="preferences_sounds_title">Sounds</string>
|
||||
|
||||
<string name="title_about">About Barcode Scanner</string>
|
||||
<string name="title_help">Help</string>
|
||||
|
||||
<string name="zxing_url">http://code.google.com/p/zxing</string>
|
||||
</resources>
|
34
android/res/xml/preferences.xml
Executable file
34
android/res/xml/preferences.xml
Executable file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Google Inc.
|
||||
|
||||
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.
|
||||
-->
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory android:title="@string/preferences_general_title">
|
||||
<CheckBoxPreference
|
||||
android:key="preferences_decode_1D"
|
||||
android:defaultValue="true"
|
||||
android:title="@string/preferences_decode_1D_title"/>
|
||||
<CheckBoxPreference
|
||||
android:key="preferences_decode_QR"
|
||||
android:defaultValue="true"
|
||||
android:title="@string/preferences_decode_QR_title"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/preferences_sounds_title">
|
||||
<CheckBoxPreference
|
||||
android:key="preferences_play_beep"
|
||||
android:defaultValue="true"
|
||||
android:title="@string/preferences_play_beep_title"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
57
android/src/com/android/barcodes/AndroidIntentParsedResult.java
Executable file
57
android/src/com/android/barcodes/AndroidIntentParsedResult.java
Executable file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.content.Intent;
|
||||
import com.google.zxing.client.result.ParsedResult;
|
||||
import com.google.zxing.client.result.ParsedResultType;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* A {@link com.google.zxing.client.result.ParsedResult} derived from a URI that encodes an Android
|
||||
* {@link Intent}, and which should presumably trigger that intent on Android.
|
||||
*/
|
||||
public final class AndroidIntentParsedResult extends ParsedResult {
|
||||
|
||||
private final Intent mIntent;
|
||||
|
||||
private AndroidIntentParsedResult(Intent intent) {
|
||||
super(ParsedResultType.ANDROID_INTENT);
|
||||
mIntent = intent;
|
||||
}
|
||||
|
||||
public static AndroidIntentParsedResult parse(String rawText) {
|
||||
try {
|
||||
return new AndroidIntentParsedResult(Intent.getIntent(rawText));
|
||||
} catch (URISyntaxException urise) {
|
||||
return null;
|
||||
} catch (IllegalArgumentException iae) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Intent getIntent() {
|
||||
return mIntent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayResult() {
|
||||
return mIntent.toString();
|
||||
}
|
||||
|
||||
}
|
308
android/src/com/android/barcodes/BarcodesCaptureActivity.java
Executable file
308
android/src/com/android/barcodes/BarcodesCaptureActivity.java
Executable file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer.OnCompletionListener;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.client.result.ParsedResult;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The barcode reader activity itself. This is loosely based on the CameraPreview
|
||||
* example included in the Android SDK.
|
||||
*/
|
||||
public final class BarcodesCaptureActivity extends Activity implements SurfaceHolder.Callback {
|
||||
|
||||
private static final int SETTINGS_ID = Menu.FIRST;
|
||||
private static final int HELP_ID = Menu.FIRST + 1;
|
||||
private static final int ABOUT_ID = Menu.FIRST + 2;
|
||||
|
||||
public BarcodesCaptureActivityHandler mHandler;
|
||||
|
||||
private ViewfinderView mViewfinderView;
|
||||
private MediaPlayer mMediaPlayer;
|
||||
private String mLastResult;
|
||||
private boolean mPlayBeep;
|
||||
private boolean mScanIntent;
|
||||
private String mDecodeMode;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
setContentView(R.layout.capture);
|
||||
|
||||
CameraManager.init(getApplication());
|
||||
mViewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
|
||||
mHandler = null;
|
||||
|
||||
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();
|
||||
resetStatusView();
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
mPlayBeep = prefs.getBoolean(BarcodesPreferenceActivity.KEY_PLAY_BEEP, true);
|
||||
initBeepSound();
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (intent != null && intent.getAction().equals(Intents.Scan.ACTION)) {
|
||||
mScanIntent = true;
|
||||
mDecodeMode = intent.getStringExtra(Intents.Scan.MODE);
|
||||
} else {
|
||||
mScanIntent = false;
|
||||
mDecodeMode = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (mHandler != null) {
|
||||
mHandler.quitSynchronously();
|
||||
mHandler = null;
|
||||
}
|
||||
CameraManager.get().closeDriver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (mScanIntent) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
} else if (keyCode == KeyEvent.KEYCODE_FOCUS || keyCode == KeyEvent.KEYCODE_CAMERA) {
|
||||
// Handle these events so they don't launch the Camera app
|
||||
return true;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, SETTINGS_ID, 0, R.string.menu_settings)
|
||||
.setIcon(android.R.drawable.ic_menu_preferences);
|
||||
menu.add(0, HELP_ID, 0, R.string.menu_help)
|
||||
.setIcon(android.R.drawable.ic_menu_help);
|
||||
menu.add(0, ABOUT_ID, 0, R.string.menu_about)
|
||||
.setIcon(android.R.drawable.ic_menu_info_details);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case SETTINGS_ID: {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setClassName(this, BarcodesPreferenceActivity.class.getName());
|
||||
startActivity(intent);
|
||||
break;
|
||||
}
|
||||
case HELP_ID: {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.title_help);
|
||||
builder.setMessage(R.string.msg_help);
|
||||
builder.setPositiveButton(R.string.button_ok, null);
|
||||
builder.show();
|
||||
break;
|
||||
}
|
||||
case ABOUT_ID: {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.title_about);
|
||||
builder.setMessage(getString(R.string.msg_about) + "\n\n" + getString(R.string.zxing_url));
|
||||
builder.setIcon(R.drawable.zxing_icon);
|
||||
builder.setPositiveButton(R.string.button_open_browser, mAboutListener);
|
||||
builder.setNegativeButton(R.string.button_cancel, null);
|
||||
builder.show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private final DialogInterface.OnClickListener mAboutListener = new DialogInterface.OnClickListener() {
|
||||
public void onClick(android.content.DialogInterface dialogInterface, int i) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.zxing_url)));
|
||||
startActivity(intent);
|
||||
}
|
||||
};
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
CameraManager.get().openDriver(holder);
|
||||
if (mHandler == null) {
|
||||
mHandler = new BarcodesCaptureActivityHandler(this, mDecodeMode);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A valid barcode has been found, so give an indication of success and show the results.
|
||||
*
|
||||
* @param rawResult The contents of the barcode.
|
||||
* @param duration How long the decoding took in milliseconds.
|
||||
*/
|
||||
public void handleDecode(Result rawResult, int duration) {
|
||||
if (!rawResult.toString().equals(mLastResult)) {
|
||||
mLastResult = rawResult.toString();
|
||||
playBeepSound();
|
||||
|
||||
ResultPoint[] points = rawResult.getResultPoints();
|
||||
if (points != null && points.length > 0) {
|
||||
mViewfinderView.drawResultPoints(points);
|
||||
}
|
||||
|
||||
TextView textView = (TextView) findViewById(R.id.status_text_view);
|
||||
ParsedResult result = ResultHandler.parseResult(rawResult);
|
||||
String displayResult = result.getDisplayResult();
|
||||
displayResult = displayResult.replace("\r", "");
|
||||
textView.setText(displayResult);
|
||||
|
||||
if (!mScanIntent) {
|
||||
Button actionButton = (Button) findViewById(R.id.status_action_button);
|
||||
int buttonText = ResultHandler.getActionButtonText(result.getType());
|
||||
if (buttonText != 0) {
|
||||
actionButton.setVisibility(View.VISIBLE);
|
||||
actionButton.setText(buttonText);
|
||||
ResultHandler resultHandler = new ResultHandler(this, result);
|
||||
actionButton.setOnClickListener(resultHandler);
|
||||
actionButton.requestFocus();
|
||||
} else {
|
||||
actionButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
View statusView = findViewById(R.id.status_view);
|
||||
statusView.setBackgroundColor(getResources().getColor(R.color.result_points));
|
||||
|
||||
// Show the green finder patterns briefly, then either return the result or go back to
|
||||
// continuous scanning.
|
||||
if (mScanIntent) {
|
||||
Intent intent = new Intent(Intents.Scan.ACTION);
|
||||
intent.putExtra(Intents.Scan.RESULT, rawResult.toString());
|
||||
intent.putExtra(Intents.Scan.RESULT_FORMAT, rawResult.getBarcodeFormat().toString());
|
||||
Message message = Message.obtain(mHandler, R.id.return_scan_result);
|
||||
message.obj = intent;
|
||||
mHandler.sendMessageDelayed(message, 1000);
|
||||
} else {
|
||||
Message message = Message.obtain(mHandler, R.id.restart_preview);
|
||||
mHandler.sendMessageDelayed(message, 2000);
|
||||
}
|
||||
} else if (mHandler != null) {
|
||||
Message message = Message.obtain(mHandler, R.id.restart_preview);
|
||||
message.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the beep MediaPlayer in advance so that the sound can be triggered with the least
|
||||
* latency possible.
|
||||
*/
|
||||
private void initBeepSound() {
|
||||
if (mPlayBeep && mMediaPlayer == null) {
|
||||
mMediaPlayer = new MediaPlayer();
|
||||
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_SYSTEM);
|
||||
mMediaPlayer.setOnCompletionListener(mBeepListener);
|
||||
|
||||
AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.beep);
|
||||
try {
|
||||
mMediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(),
|
||||
file.getLength());
|
||||
file.close();
|
||||
mMediaPlayer.setVolume(0.15f, 0.15f);
|
||||
mMediaPlayer.prepare();
|
||||
} catch (IOException e) {
|
||||
mMediaPlayer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void playBeepSound() {
|
||||
if (mPlayBeep && mMediaPlayer != null) {
|
||||
mMediaPlayer.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When the beep has finished playing, rewind to queue up another one.
|
||||
*/
|
||||
private final OnCompletionListener mBeepListener = new OnCompletionListener() {
|
||||
public void onCompletion(MediaPlayer mediaPlayer) {
|
||||
mediaPlayer.seekTo(0);
|
||||
}
|
||||
};
|
||||
|
||||
private void resetStatusView() {
|
||||
resetStatusViewColor();
|
||||
TextView textView = (TextView) findViewById(R.id.status_text_view);
|
||||
textView.setText(R.string.msg_default_status);
|
||||
Button actionButton = (Button) findViewById(R.id.status_action_button);
|
||||
actionButton.setVisibility(View.GONE);
|
||||
mLastResult = "";
|
||||
}
|
||||
|
||||
public void resetStatusViewColor() {
|
||||
View statusView = findViewById(R.id.status_view);
|
||||
statusView.setBackgroundColor(getResources().getColor(R.color.status_view));
|
||||
}
|
||||
|
||||
public void drawViewfinder() {
|
||||
mViewfinderView.drawViewfinder();
|
||||
}
|
||||
|
||||
}
|
102
android/src/com/android/barcodes/BarcodesCaptureActivityHandler.java
Executable file
102
android/src/com/android/barcodes/BarcodesCaptureActivityHandler.java
Executable file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import com.google.zxing.Result;
|
||||
|
||||
/**
|
||||
* This class handles all the messaging which comprises the state machine for capture.
|
||||
*/
|
||||
public class BarcodesCaptureActivityHandler extends Handler {
|
||||
|
||||
private final BarcodesCaptureActivity mActivity;
|
||||
private final DecodeThread mDecodeThread;
|
||||
private State mState;
|
||||
|
||||
private enum State {
|
||||
PREVIEW,
|
||||
SUCCESS,
|
||||
DONE
|
||||
}
|
||||
|
||||
BarcodesCaptureActivityHandler(BarcodesCaptureActivity activity, String decodeMode) {
|
||||
mActivity = activity;
|
||||
mDecodeThread = new DecodeThread(activity, decodeMode);
|
||||
mDecodeThread.start();
|
||||
mState = State.SUCCESS;
|
||||
|
||||
// Start ourselves capturing previews and decoding.
|
||||
restartPreviewAndDecode();
|
||||
}
|
||||
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case R.id.auto_focus:
|
||||
// When one auto focus pass finishes, start another. This is the closest thing to
|
||||
// continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
|
||||
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
|
||||
break;
|
||||
case R.id.restart_preview:
|
||||
restartPreviewAndDecode();
|
||||
break;
|
||||
case R.id.decode_succeeded:
|
||||
mState = State.SUCCESS;
|
||||
int duration = message.arg1;
|
||||
mActivity.handleDecode((Result) message.obj, duration);
|
||||
break;
|
||||
case R.id.decode_failed:
|
||||
// We're decoding as fast as possible, so when one decode fails, start another.
|
||||
mState = State.PREVIEW;
|
||||
CameraManager.get().requestPreviewFrame(mDecodeThread.mHandler, R.id.decode);
|
||||
break;
|
||||
case R.id.return_scan_result:
|
||||
mActivity.setResult(Activity.RESULT_OK, (Intent) message.obj);
|
||||
mActivity.finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void quitSynchronously() {
|
||||
mState = State.DONE;
|
||||
CameraManager.get().stopPreview();
|
||||
Message quit = Message.obtain(mDecodeThread.mHandler, R.id.quit);
|
||||
quit.sendToTarget();
|
||||
try {
|
||||
mDecodeThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
// Be absolutely sure we don't send any queued up messages
|
||||
removeMessages(R.id.decode_succeeded);
|
||||
removeMessages(R.id.decode_failed);
|
||||
}
|
||||
|
||||
private void restartPreviewAndDecode() {
|
||||
if (mState == State.SUCCESS) {
|
||||
mState = State.PREVIEW;
|
||||
CameraManager.get().startPreview();
|
||||
CameraManager.get().requestPreviewFrame(mDecodeThread.mHandler, R.id.decode);
|
||||
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
|
||||
mActivity.resetStatusViewColor();
|
||||
mActivity.drawViewfinder();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
137
android/src/com/android/barcodes/BarcodesEncodeActivity.java
Executable file
137
android/src/com/android/barcodes/BarcodesEncodeActivity.java
Executable file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* This class encodes data from an Intent into a QR code, and then displays it full screen so that
|
||||
* another person can scan it with their device.
|
||||
*/
|
||||
public class BarcodesEncodeActivity extends Activity {
|
||||
|
||||
private QRCodeEncoder mQRCodeEncoder;
|
||||
private ProgressDialog mProgressDialog;
|
||||
private boolean mFirstLayout;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (intent == null || !intent.getAction().equals(Intents.Encode.ACTION)) {
|
||||
finish();
|
||||
} else {
|
||||
setContentView(R.layout.encode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
LinearLayout layout = (LinearLayout) findViewById(R.id.encode_view);
|
||||
layout.getViewTreeObserver().addOnGlobalLayoutListener(mLayoutListener);
|
||||
mFirstLayout = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This needs to be delayed until after the first layout so that the view dimensions will be
|
||||
* available.
|
||||
*/
|
||||
public OnGlobalLayoutListener mLayoutListener = new OnGlobalLayoutListener() {
|
||||
public void onGlobalLayout() {
|
||||
if (mFirstLayout) {
|
||||
LinearLayout layout = (LinearLayout) findViewById(R.id.encode_view);
|
||||
int width = layout.getWidth();
|
||||
int height = layout.getHeight();
|
||||
int smallerDimension = (width < height) ? width : height;
|
||||
|
||||
Intent intent = getIntent();
|
||||
try {
|
||||
mQRCodeEncoder = new QRCodeEncoder(BarcodesEncodeActivity.this, intent);
|
||||
setTitle(getString(R.string.app_name) + " - " + mQRCodeEncoder.getTitle());
|
||||
mQRCodeEncoder.requestBarcode(mHandler, smallerDimension);
|
||||
mProgressDialog = ProgressDialog.show(BarcodesEncodeActivity.this, null,
|
||||
getString(R.string.msg_encode_in_progress), true, true, mCancelListener);
|
||||
} catch (IllegalArgumentException e) {
|
||||
showErrorMessage(R.string.msg_encode_contents_failed);
|
||||
}
|
||||
mFirstLayout = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case R.id.encode_succeeded:
|
||||
mProgressDialog.dismiss();
|
||||
mProgressDialog = null;
|
||||
Bitmap image = (Bitmap)message.obj;
|
||||
ImageView view = (ImageView) findViewById(R.id.image_view);
|
||||
view.setImageBitmap(image);
|
||||
TextView contents = (TextView) findViewById(R.id.contents_text_view);
|
||||
contents.setText(mQRCodeEncoder.getDisplayContents());
|
||||
mQRCodeEncoder = null;
|
||||
break;
|
||||
case R.id.encode_failed:
|
||||
showErrorMessage(R.string.msg_encode_barcode_failed);
|
||||
mQRCodeEncoder = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void showErrorMessage(int message) {
|
||||
if (mProgressDialog != null) {
|
||||
mProgressDialog.dismiss();
|
||||
mProgressDialog = null;
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(message);
|
||||
builder.setPositiveButton(R.string.button_ok, mClickListener);
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private OnClickListener mClickListener = new OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
|
||||
private OnCancelListener mCancelListener = new OnCancelListener() {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
58
android/src/com/android/barcodes/BarcodesPreferenceActivity.java
Executable file
58
android/src/com/android/barcodes/BarcodesPreferenceActivity.java
Executable file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.CheckBoxPreference;
|
||||
|
||||
public class BarcodesPreferenceActivity extends android.preference.PreferenceActivity
|
||||
implements OnSharedPreferenceChangeListener {
|
||||
|
||||
static final String KEY_DECODE_1D = "preferences_decode_1D";
|
||||
static final String KEY_DECODE_QR = "preferences_decode_QR";
|
||||
static final String KEY_PLAY_BEEP = "preferences_play_beep";
|
||||
|
||||
CheckBoxPreference mDecode1D;
|
||||
CheckBoxPreference mDecodeQR;
|
||||
CheckBoxPreference mPlayBeep;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
PreferenceScreen preferences = getPreferenceScreen();
|
||||
preferences.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||
mDecode1D = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_1D);
|
||||
mDecodeQR = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_QR);
|
||||
mPlayBeep = (CheckBoxPreference) preferences.findPreference(KEY_PLAY_BEEP);
|
||||
}
|
||||
|
||||
// Prevent the user from turning off both decode options
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (key.equals(KEY_DECODE_1D)) {
|
||||
mDecodeQR.setEnabled(mDecode1D.isChecked());
|
||||
mDecodeQR.setChecked(true);
|
||||
} else if (key.equals(KEY_DECODE_QR)) {
|
||||
mDecode1D.setEnabled(mDecodeQR.isChecked());
|
||||
mDecode1D.setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
219
android/src/com/android/barcodes/CameraManager.java
Executable file
219
android/src/com/android/barcodes/CameraManager.java
Executable file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
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.WindowManager;
|
||||
import android.view.SurfaceHolder;
|
||||
import com.google.zxing.ResultPoint;
|
||||
|
||||
/**
|
||||
* 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 mInitialized;
|
||||
private boolean mPreviewing;
|
||||
|
||||
public static void init(Context context) {
|
||||
if (mCameraManager == null) {
|
||||
mCameraManager = new CameraManager(context);
|
||||
}
|
||||
}
|
||||
|
||||
public static CameraManager get() {
|
||||
return mCameraManager;
|
||||
}
|
||||
|
||||
private CameraManager(Context context) {
|
||||
mContext = context;
|
||||
mCamera = null;
|
||||
mInitialized = false;
|
||||
mPreviewing = false;
|
||||
}
|
||||
|
||||
public void openDriver(SurfaceHolder holder) {
|
||||
if (mCamera == null) {
|
||||
mCamera = Camera.open();
|
||||
mCamera.setPreviewDisplay(holder);
|
||||
|
||||
if (!mInitialized) {
|
||||
mInitialized = true;
|
||||
getScreenResolution();
|
||||
}
|
||||
|
||||
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);
|
||||
Log.v(TAG, "Calculated framing rect: " + mFramingRect);
|
||||
}
|
||||
return mFramingRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the result points from still resolution coordinates to screen coordinates.
|
||||
*
|
||||
* @param points The points returned by the Reader subclass through Result.getResultPoints().
|
||||
* @return An array of Points scaled to the size of the framing rect and offset appropriately
|
||||
* so they can be drawn in screen coordinates.
|
||||
*/
|
||||
public Point[] convertResultPoints(ResultPoint[] points) {
|
||||
Rect frame = getFramingRect();
|
||||
int count = points.length;
|
||||
Point[] output = new Point[count];
|
||||
for (int x = 0; x < count; x++) {
|
||||
output[x] = new Point();
|
||||
output[x].x = frame.left + (int) (points[x].getX() + 0.5f);
|
||||
output[x].y = frame.top + (int) (points[x].getY() + 0.5f);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
// Simulate continuous autofocus by sending a focus request every second.
|
||||
mAutoFocusHandler.sendMessageDelayed(message, 1000);
|
||||
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);
|
||||
Log.v(TAG, "Setting params for preview: width " + mScreenResolution.x + " height " +
|
||||
mScreenResolution.y);
|
||||
}
|
||||
|
||||
private Point getScreenResolution() {
|
||||
if (mScreenResolution == null) {
|
||||
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
|
||||
Display display = manager.getDefaultDisplay();
|
||||
mScreenResolution = new Point(display.getWidth(), display.getHeight());
|
||||
}
|
||||
return mScreenResolution;
|
||||
}
|
||||
|
||||
}
|
82
android/src/com/android/barcodes/Contents.java
Executable file
82
android/src/com/android/barcodes/Contents.java
Executable file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
|
||||
public final class Contents {
|
||||
|
||||
/**
|
||||
* All the formats we know about.
|
||||
*/
|
||||
public static final class Format {
|
||||
public static final String UPC_A = "UPC_A";
|
||||
public static final String UPC_E = "UPC_E";
|
||||
public static final String EAN_8 = "EAN_8";
|
||||
public static final String EAN_13 = "EAN_13";
|
||||
public static final String CODE_39 = "CODE_39";
|
||||
public static final String CODE_128 = "CODE_128";
|
||||
public static final String QR_CODE = "QR_CODE";
|
||||
}
|
||||
|
||||
public static final class Type {
|
||||
/**
|
||||
* Plain text. Use Intent.putExtra(DATA, string). This can be used for URLs too, but string
|
||||
* must include "http://" or "https://".
|
||||
*/
|
||||
public static final String TEXT = "TEXT_TYPE";
|
||||
|
||||
/**
|
||||
* An email type. Use Intent.putExtra(DATA, string) where string is the email address.
|
||||
*/
|
||||
public static final String EMAIL = "EMAIL_TYPE";
|
||||
|
||||
/**
|
||||
* Use Intent.putExtra(DATA, string) where string is the phone number to call.
|
||||
*/
|
||||
public static final String PHONE = "PHONE_TYPE";
|
||||
|
||||
/**
|
||||
* An SMS type. Use Intent.putExtra(DATA, string) where string is the number to SMS.
|
||||
*/
|
||||
public static final String SMS = "SMS_TYPE";
|
||||
|
||||
/**
|
||||
* A contact. Send a request to encode it as follows:
|
||||
*
|
||||
* import android.provider.Contacts;
|
||||
*
|
||||
* Intent intent = new Intent(Intents.Encode.ACTION);
|
||||
* intent.putExtra(Intents.Encode.TYPE, CONTACT);
|
||||
* Bundle bundle = new Bundle();
|
||||
* bundle.putString(Contacts.Intents.Insert.NAME, "Jenny");
|
||||
* bundle.putString(Contacts.Intents.Insert.PHONE, "8675309");
|
||||
* bundle.putString(Contacts.Intents.Insert.EMAIL, "jenny@the80s.com");
|
||||
* intent.putExtra(Intents.Encode.DATA, bundle);
|
||||
*/
|
||||
public static final String CONTACT = "CONTACT_TYPE";
|
||||
|
||||
/**
|
||||
* A geographic location. Use as follows:
|
||||
* Bundle bundle = new Bundle();
|
||||
* bundle.putFloat("LAT", latitude);
|
||||
* bundle.putFloat("LONG", longitude);
|
||||
* intent.putExtra(Intents.Encode.DATA, bundle);
|
||||
*/
|
||||
public static final String LOCATION = "LOCATION_TYPE";
|
||||
}
|
||||
|
||||
}
|
162
android/src/com/android/barcodes/DecodeThread.java
Executable file
162
android/src/com/android/barcodes/DecodeThread.java
Executable file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.MonochromeBitmapSource;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.ReaderException;
|
||||
import com.google.zxing.Result;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* This thread does all the heavy lifting of decoding the images.
|
||||
*/
|
||||
final class DecodeThread extends Thread {
|
||||
|
||||
public Handler mHandler;
|
||||
private BarcodesCaptureActivity mActivity;
|
||||
private MultiFormatReader mMultiFormatReader;
|
||||
|
||||
DecodeThread(BarcodesCaptureActivity activity, String mode) {
|
||||
mActivity = activity;
|
||||
mMultiFormatReader = new MultiFormatReader();
|
||||
|
||||
// The prefs can't change while the thread is running, so pick them up once here.
|
||||
if (mode == null || mode.length() == 0) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
boolean decode1D = prefs.getBoolean(BarcodesPreferenceActivity.KEY_DECODE_1D, true);
|
||||
boolean decodeQR = prefs.getBoolean(BarcodesPreferenceActivity.KEY_DECODE_QR, true);
|
||||
if (decode1D && decodeQR) {
|
||||
setDecodeAllMode();
|
||||
} else if (decode1D) {
|
||||
setDecode1DMode();
|
||||
} else if (decodeQR) {
|
||||
setDecodeQRMode();
|
||||
}
|
||||
} else {
|
||||
if (mode.equals(Intents.Scan.PRODUCT_MODE)) {
|
||||
setDecodeProductMode();
|
||||
} else if (mode.equals(Intents.Scan.ONE_D_MODE)) {
|
||||
setDecode1DMode();
|
||||
} else if (mode.equals(Intents.Scan.QR_CODE_MODE)) {
|
||||
setDecodeQRMode();
|
||||
} else {
|
||||
setDecodeAllMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Looper.prepare();
|
||||
mHandler = new Handler() {
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case R.id.decode:
|
||||
decode((byte[]) message.obj, message.arg1, message.arg2);
|
||||
break;
|
||||
case R.id.quit:
|
||||
Looper.myLooper().quit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
Looper.loop();
|
||||
}
|
||||
|
||||
private void setDecodeProductMode() {
|
||||
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(3);
|
||||
Vector<BarcodeFormat> vector = new Vector<BarcodeFormat>();
|
||||
vector.addElement(BarcodeFormat.UPC_A);
|
||||
vector.addElement(BarcodeFormat.UPC_E);
|
||||
vector.addElement(BarcodeFormat.EAN_13);
|
||||
vector.addElement(BarcodeFormat.EAN_8);
|
||||
hints.put(DecodeHintType.POSSIBLE_FORMATS, vector);
|
||||
mMultiFormatReader.setHints(hints);
|
||||
}
|
||||
|
||||
// TODO: This is fragile in case we add new formats. It would be better to have a new enum
|
||||
// value which represented all 1D formats.
|
||||
private void setDecode1DMode() {
|
||||
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(3);
|
||||
Vector<BarcodeFormat> vector = new Vector<BarcodeFormat>();
|
||||
vector.addElement(BarcodeFormat.UPC_A);
|
||||
vector.addElement(BarcodeFormat.UPC_E);
|
||||
vector.addElement(BarcodeFormat.EAN_13);
|
||||
vector.addElement(BarcodeFormat.EAN_8);
|
||||
vector.addElement(BarcodeFormat.CODE_39);
|
||||
vector.addElement(BarcodeFormat.CODE_128);
|
||||
hints.put(DecodeHintType.POSSIBLE_FORMATS, vector);
|
||||
mMultiFormatReader.setHints(hints);
|
||||
}
|
||||
|
||||
private void setDecodeQRMode() {
|
||||
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(3);
|
||||
Vector<BarcodeFormat> vector = new Vector<BarcodeFormat>();
|
||||
vector.addElement(BarcodeFormat.QR_CODE);
|
||||
hints.put(DecodeHintType.POSSIBLE_FORMATS, vector);
|
||||
mMultiFormatReader.setHints(hints);
|
||||
}
|
||||
|
||||
private void setDecodeAllMode() {
|
||||
mMultiFormatReader.setHints(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
|
||||
* reuse the same reader objects from one decode to the next.
|
||||
*
|
||||
* @param data The YUV preview frame.
|
||||
* @param width The width of the preview frame.
|
||||
* @param height The height of the preview frame.
|
||||
*/
|
||||
private void decode(byte[] data, int width, int height) {
|
||||
Date startDate = new Date();
|
||||
boolean success;
|
||||
Result rawResult = null;
|
||||
try {
|
||||
MonochromeBitmapSource source = new YUVMonochromeBitmapSource(data, width, height,
|
||||
CameraManager.get().getFramingRect());
|
||||
rawResult = mMultiFormatReader.decodeWithState(source);
|
||||
success = true;
|
||||
} catch (ReaderException e) {
|
||||
success = false;
|
||||
}
|
||||
Date endDate = new Date();
|
||||
|
||||
if (success) {
|
||||
Message message = Message.obtain(mActivity.mHandler, R.id.decode_succeeded, rawResult);
|
||||
message.arg1 = (int) (endDate.getTime() - startDate.getTime());
|
||||
message.sendToTarget();
|
||||
} else {
|
||||
Message message = Message.obtain(mActivity.mHandler, R.id.decode_failed);
|
||||
message.arg1 = (int) (endDate.getTime() - startDate.getTime());
|
||||
message.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
86
android/src/com/android/barcodes/Intents.java
Executable file
86
android/src/com/android/barcodes/Intents.java
Executable file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
public final class Intents {
|
||||
|
||||
public static final class Scan {
|
||||
/**
|
||||
* Send this intent to open the Barcodes app in scanning mode, find a barcode, and return
|
||||
* the results.
|
||||
*/
|
||||
public static final String ACTION = "com.android.barcodes.SCAN";
|
||||
|
||||
/**
|
||||
* By default, sending Scan.ACTION will decode all barcodes that we understand. However it
|
||||
* may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with
|
||||
* one of the values below (optional).
|
||||
*/
|
||||
public static final String MODE = "SCAN_MODE";
|
||||
|
||||
/**
|
||||
* Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get
|
||||
* prices, reviews, etc. for products.
|
||||
*/
|
||||
public static final String PRODUCT_MODE = "PRODUCT_MODE";
|
||||
|
||||
/**
|
||||
* Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128).
|
||||
*/
|
||||
public static final String ONE_D_MODE = "ONE_D_MODE";
|
||||
|
||||
/**
|
||||
* Decode only QR codes.
|
||||
*/
|
||||
public static final String QR_CODE_MODE = "QR_CODE_MODE";
|
||||
|
||||
/**
|
||||
* If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which
|
||||
* requested the scan via startSubActivity(). The barcodes contents can be retrieved with
|
||||
* intent.getStringExtra(RESULT). If the user presses Back, the result code will be
|
||||
* RESULT_CANCELED.
|
||||
*/
|
||||
public static final String RESULT = "SCAN_RESULT";
|
||||
|
||||
/**
|
||||
* Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.
|
||||
* See Contents.Format for possible values.
|
||||
*/
|
||||
public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT";
|
||||
}
|
||||
|
||||
public static final class Encode {
|
||||
/**
|
||||
* Send this intent to encode a piece of data as a QR code and display it full screen, so
|
||||
* that another person can scan the barcode from your screen.
|
||||
*/
|
||||
public static final String ACTION = "com.android.barcodes.ENCODE";
|
||||
|
||||
/**
|
||||
* The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a
|
||||
* Bundle, depending on the type specified. See Contents for details.
|
||||
*/
|
||||
public static final String DATA = "ENCODE_DATA";
|
||||
|
||||
/**
|
||||
* The type of data being supplied. Use Intent.putExtra(TYPE, type) with one of
|
||||
* Contents.Type.
|
||||
*/
|
||||
public static final String TYPE = "ENCODE_TYPE";
|
||||
}
|
||||
|
||||
}
|
180
android/src/com/android/barcodes/QRCodeEncoder.java
Executable file
180
android/src/com/android/barcodes/QRCodeEncoder.java
Executable file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.http.AndroidHttpClient;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.Contacts;
|
||||
import android.util.Log;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public class QRCodeEncoder {
|
||||
|
||||
private static final String TAG = "QRCodeEncoder";
|
||||
|
||||
private Activity mActivity;
|
||||
private String mContents;
|
||||
private String mDisplayContents;
|
||||
private String mTitle;
|
||||
private NetworkThread mNetworkThread;
|
||||
|
||||
public QRCodeEncoder(Activity activity, Intent intent) {
|
||||
mActivity = activity;
|
||||
if (!encodeContents(intent)) {
|
||||
throw new IllegalArgumentException("No valid data to encode.");
|
||||
}
|
||||
}
|
||||
|
||||
// Once the core ZXing library supports encoding, we'll be able to generate the bitmap
|
||||
// synchronously. For now, it's a network request, so it's handled on a thread.
|
||||
public void requestBarcode(Handler handler, int pixelResolution) {
|
||||
mNetworkThread = new NetworkThread(mContents, handler, pixelResolution);
|
||||
mNetworkThread.start();
|
||||
}
|
||||
|
||||
public String getContents() {
|
||||
return mContents;
|
||||
}
|
||||
|
||||
public String getDisplayContents() {
|
||||
return mDisplayContents;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
// Perhaps the string encoding should live in the core ZXing library too.
|
||||
private boolean encodeContents(Intent intent) {
|
||||
if (intent == null) return false;
|
||||
String type = intent.getStringExtra(Intents.Encode.TYPE);
|
||||
if (type == null || type.length() == 0) return false;
|
||||
|
||||
if (type.equals(Contents.Type.TEXT)) {
|
||||
String string = intent.getStringExtra(Intents.Encode.DATA);
|
||||
if (string != null && string.length() > 0) {
|
||||
mContents = string;
|
||||
mDisplayContents = string;
|
||||
mTitle = mActivity.getString(R.string.contents_text);
|
||||
}
|
||||
} else if (type.equals(Contents.Type.EMAIL)) {
|
||||
String string = intent.getStringExtra(Intents.Encode.DATA);
|
||||
if (string != null && string.length() > 0) {
|
||||
mContents = "mailto:" + string;
|
||||
mDisplayContents = string;
|
||||
mTitle = mActivity.getString(R.string.contents_email);
|
||||
}
|
||||
} else if (type.equals(Contents.Type.PHONE)) {
|
||||
String string = intent.getStringExtra(Intents.Encode.DATA);
|
||||
if (string != null && string.length() > 0) {
|
||||
mContents = "tel:" + string;
|
||||
mDisplayContents = string;
|
||||
mTitle = mActivity.getString(R.string.contents_phone);
|
||||
}
|
||||
} else if (type.equals(Contents.Type.SMS)) {
|
||||
String string = intent.getStringExtra(Intents.Encode.DATA);
|
||||
if (string != null && string.length() > 0) {
|
||||
mContents = "sms:" + string;
|
||||
mDisplayContents = string;
|
||||
mTitle = mActivity.getString(R.string.contents_sms);
|
||||
}
|
||||
} else if (type.equals(Contents.Type.CONTACT)) {
|
||||
Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
|
||||
if (bundle != null) {
|
||||
String name = bundle.getString(Contacts.Intents.Insert.NAME);
|
||||
if (name != null && !name.equals("")) {
|
||||
mContents = "MECARD:N:" + name + ";";
|
||||
mDisplayContents = name;
|
||||
String phone = bundle.getString(Contacts.Intents.Insert.PHONE);
|
||||
if (phone != null && !phone.equals("")) {
|
||||
mContents += "TEL:" + phone + ";";
|
||||
mDisplayContents += "\n" + phone;
|
||||
}
|
||||
String email = bundle.getString(Contacts.Intents.Insert.EMAIL);
|
||||
if (email != null && !email.equals("")) {
|
||||
mContents += "EMAIL:" + email + ";";
|
||||
mDisplayContents += "\n" + email;
|
||||
}
|
||||
mContents += ";";
|
||||
mTitle = mActivity.getString(R.string.contents_contact);
|
||||
}
|
||||
}
|
||||
} else if (type.equals(Contents.Type.LOCATION)) {
|
||||
Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
|
||||
if (bundle != null) {
|
||||
float latitude = bundle.getFloat("LAT", Float.MAX_VALUE);
|
||||
float longitude = bundle.getFloat("LONG", Float.MAX_VALUE);
|
||||
if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) {
|
||||
mContents = "geo:" + latitude + "," + longitude;
|
||||
mDisplayContents = latitude + "," + longitude;
|
||||
mTitle = mActivity.getString(R.string.contents_location);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mContents != null && mContents.length() > 0;
|
||||
}
|
||||
|
||||
private class NetworkThread extends Thread {
|
||||
|
||||
private String mContents;
|
||||
private Handler mHandler;
|
||||
private int mPixelResolution;
|
||||
|
||||
public NetworkThread(String contents, Handler handler, int pixelResolution) {
|
||||
mContents = contents;
|
||||
mHandler = handler;
|
||||
mPixelResolution = pixelResolution;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
String url = "//chartserver.apis.google.com/chart?cht=qr&chs=";
|
||||
url += mPixelResolution + "x" + mPixelResolution + "&chl=" + mContents;
|
||||
try {
|
||||
URI uri = new URI("http", url, null);
|
||||
HttpGet get = new HttpGet(uri);
|
||||
AndroidHttpClient client = AndroidHttpClient.newInstance("Android-BarcodeScanner/0.1");
|
||||
HttpResponse response = client.execute(get);
|
||||
HttpEntity entity = response.getEntity();
|
||||
Bitmap image = BitmapFactory.decodeStream(entity.getContent());
|
||||
if (image != null) {
|
||||
Message message = Message.obtain(mHandler, R.id.encode_succeeded);
|
||||
message.obj = image;
|
||||
message.sendToTarget();
|
||||
} else {
|
||||
Log.e(TAG, "Could not decode png from the network");
|
||||
Message message = Message.obtain(mHandler, R.id.encode_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.toString());
|
||||
Message message = Message.obtain(mHandler, R.id.encode_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
155
android/src/com/android/barcodes/ResultHandler.java
Executable file
155
android/src/com/android/barcodes/ResultHandler.java
Executable file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.provider.Contacts;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.client.result.AddressBookParsedResult;
|
||||
import com.google.zxing.client.result.EmailAddressParsedResult;
|
||||
import com.google.zxing.client.result.GeoParsedResult;
|
||||
import com.google.zxing.client.result.ParsedResult;
|
||||
import com.google.zxing.client.result.ParsedResultType;
|
||||
import com.google.zxing.client.result.ResultParser;
|
||||
import com.google.zxing.client.result.SMSParsedResult;
|
||||
import com.google.zxing.client.result.TelParsedResult;
|
||||
import com.google.zxing.client.result.UPCParsedResult;
|
||||
import com.google.zxing.client.result.URIParsedResult;
|
||||
|
||||
/**
|
||||
* Handles the result of barcode decoding in the context of the Android platform, by dispatching the
|
||||
* proper intents to open other activities like GMail, Maps, etc.
|
||||
*/
|
||||
final class ResultHandler implements Button.OnClickListener {
|
||||
|
||||
private static final String TAG = "ResultHandler";
|
||||
|
||||
private final Intent mIntent;
|
||||
private final BarcodesCaptureActivity mCaptureActivity;
|
||||
|
||||
ResultHandler(BarcodesCaptureActivity captureActivity, ParsedResult result) {
|
||||
mCaptureActivity = captureActivity;
|
||||
mIntent = resultToIntent(result);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
if (mIntent != null) {
|
||||
mCaptureActivity.startActivity(mIntent);
|
||||
}
|
||||
}
|
||||
|
||||
public Intent getIntent() {
|
||||
return mIntent;
|
||||
}
|
||||
|
||||
public static ParsedResult parseResult(Result rawResult) {
|
||||
ParsedResult result = ResultParser.parseResult(rawResult);
|
||||
if (result.getType().equals(ParsedResultType.TEXT)) {
|
||||
String rawText = rawResult.getText();
|
||||
AndroidIntentParsedResult androidResult = AndroidIntentParsedResult.parse(rawText);
|
||||
if (androidResult != null) {
|
||||
Intent intent = androidResult.getIntent();
|
||||
if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||
// For now, don't take anything that just parses as a View action. A lot
|
||||
// of things are accepted as a View action by default.
|
||||
result = androidResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int getActionButtonText(ParsedResultType type) {
|
||||
int buttonText;
|
||||
if (type.equals(ParsedResultType.ADDRESSBOOK)) {
|
||||
buttonText = R.string.button_add_contact;
|
||||
} else if (type.equals(ParsedResultType.URI)) {
|
||||
buttonText = R.string.button_open_browser;
|
||||
} else if (type.equals(ParsedResultType.EMAIL_ADDRESS)) {
|
||||
buttonText = R.string.button_email;
|
||||
} else if (type.equals(ParsedResultType.UPC)) {
|
||||
buttonText = R.string.button_lookup_product;
|
||||
} else if (type.equals(ParsedResultType.TEL)) {
|
||||
buttonText = R.string.button_dial;
|
||||
} else if (type.equals(ParsedResultType.GEO)) {
|
||||
buttonText = R.string.button_show_map;
|
||||
} else {
|
||||
buttonText = 0;
|
||||
}
|
||||
return buttonText;
|
||||
}
|
||||
|
||||
private static Intent resultToIntent(ParsedResult result) {
|
||||
Intent intent = null;
|
||||
ParsedResultType type = result.getType();
|
||||
if (type.equals(ParsedResultType.ADDRESSBOOK)) {
|
||||
AddressBookParsedResult addressResult = (AddressBookParsedResult) result;
|
||||
intent = new Intent(Contacts.Intents.Insert.ACTION, Contacts.People.CONTENT_URI);
|
||||
putExtra(intent, Contacts.Intents.Insert.NAME, addressResult.getNames());
|
||||
putExtra(intent, Contacts.Intents.Insert.PHONE, addressResult.getPhoneNumbers());
|
||||
putExtra(intent, Contacts.Intents.Insert.EMAIL, addressResult.getEmails());
|
||||
putExtra(intent, Contacts.Intents.Insert.NOTES, addressResult.getNote());
|
||||
putExtra(intent, Contacts.Intents.Insert.POSTAL, addressResult.getAddress());
|
||||
putExtra(intent, Contacts.Intents.Insert.COMPANY, addressResult.getOrg());
|
||||
putExtra(intent, Contacts.Intents.Insert.JOB_TITLE, addressResult.getTitle());
|
||||
} else if (type.equals(ParsedResultType.EMAIL_ADDRESS)) {
|
||||
EmailAddressParsedResult emailResult = (EmailAddressParsedResult) result;
|
||||
intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(emailResult.getMailtoURI()));
|
||||
putExtra(intent, "subject", emailResult.getSubject());
|
||||
putExtra(intent, "body", emailResult.getBody());
|
||||
} else if (type.equals(ParsedResultType.SMS)) {
|
||||
SMSParsedResult smsResult = (SMSParsedResult) result;
|
||||
intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(smsResult.getSMSURI()));
|
||||
putExtra(intent, "subject", smsResult.getSubject());
|
||||
putExtra(intent, "body", smsResult.getBody());
|
||||
} else if (type.equals(ParsedResultType.TEL)) {
|
||||
TelParsedResult telResult = (TelParsedResult) result;
|
||||
intent = new Intent(Intent.ACTION_DIAL, Uri.parse(telResult.getTelURI()));
|
||||
} else if (type.equals(ParsedResultType.GEO)) {
|
||||
GeoParsedResult geoResult = (GeoParsedResult) result;
|
||||
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(geoResult.getGeoURI()));
|
||||
} else if (type.equals(ParsedResultType.UPC)) {
|
||||
UPCParsedResult upcResult = (UPCParsedResult) result;
|
||||
// TODO: Add some UI to choose which product search to do
|
||||
//Uri uri = Uri.parse("http://www.upcdatabase.com/item.asp?upc=" + upcResult.getUPC());
|
||||
Uri uri = Uri.parse("http://www.google.com/products?q=" + upcResult.getUPC());
|
||||
intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
} else if (type.equals(ParsedResultType.URI)) {
|
||||
URIParsedResult uriResult = (URIParsedResult) result;
|
||||
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uriResult.getURI()));
|
||||
} else if (type.equals(ParsedResultType.ANDROID_INTENT)) {
|
||||
intent = ((AndroidIntentParsedResult) result).getIntent();
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
|
||||
private static void putExtra(Intent intent, String key, String value) {
|
||||
if (value != null && value.length() > 0) {
|
||||
intent.putExtra(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void putExtra(Intent intent, String key, String[] value) {
|
||||
if (value != null && value.length > 0) {
|
||||
putExtra(intent, key, value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
136
android/src/com/android/barcodes/ViewfinderView.java
Executable file
136
android/src/com/android/barcodes/ViewfinderView.java
Executable file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import com.google.zxing.ResultPoint;
|
||||
|
||||
/**
|
||||
* This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial
|
||||
* transparency outside it, as well as the laser scanner animation and result points.
|
||||
*/
|
||||
public class ViewfinderView extends View {
|
||||
|
||||
private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
|
||||
private static final int ANIMATION_DELAY = 100;
|
||||
|
||||
private Paint mPaint;
|
||||
private Rect mBox;
|
||||
private Point[] mResultPoints;
|
||||
private int mMaskColor;
|
||||
private int mFrameColor;
|
||||
private int mPointsColor;
|
||||
private int mLaserColor;
|
||||
private int mScannerAlpha;
|
||||
|
||||
// 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);
|
||||
mPointsColor = resources.getColor(R.color.result_points);
|
||||
mLaserColor = resources.getColor(R.color.viewfinder_laser);
|
||||
mScannerAlpha = 0;
|
||||
}
|
||||
|
||||
@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
|
||||
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 black 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);
|
||||
|
||||
if (mResultPoints != null) {
|
||||
// Superimpose a line for 1D or dots for 2D to highlight the key features of the barcode
|
||||
mPaint.setColor(mPointsColor);
|
||||
if (mResultPoints.length == 2) {
|
||||
mPaint.setStrokeWidth(4);
|
||||
canvas.drawLine(mResultPoints[0].x, mResultPoints[0].y, mResultPoints[1].x,
|
||||
mResultPoints[1].y, mPaint);
|
||||
} else {
|
||||
mPaint.setStrokeWidth(10);
|
||||
for (int x = 0; x < mResultPoints.length; x++) {
|
||||
canvas.drawPoint(mResultPoints[x].x, mResultPoints[x].y, mPaint);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Draw a red "laser scanner" line through the middle to show decoding is active
|
||||
mPaint.setColor(mLaserColor);
|
||||
mPaint.setAlpha(SCANNER_ALPHA[mScannerAlpha]);
|
||||
mScannerAlpha = (mScannerAlpha + 1) % SCANNER_ALPHA.length;
|
||||
int middle = frame.height() / 2 + frame.top;
|
||||
mBox.set(frame.left + 2, middle - 1, frame.right - 1, middle + 2);
|
||||
canvas.drawRect(mBox, mPaint);
|
||||
|
||||
// Request another update at the animation interval, but only repaint the laser line,
|
||||
// not the entire viewfinder mask.
|
||||
postInvalidateDelayed(ANIMATION_DELAY, mBox.left, mBox.top, mBox.right, mBox.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawViewfinder() {
|
||||
mResultPoints = null;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a line for 1D barcodes (which return two points) or otherwise a set of points returned
|
||||
* from the decoder to indicate what we found. For efficiency, convert these to drawable
|
||||
* coordinates once here.
|
||||
*
|
||||
* @param resultPoints An array of points from the decoder, whose coordinates are expressed
|
||||
* relative to the still image from the camera.
|
||||
*/
|
||||
public void drawResultPoints(ResultPoint[] resultPoints) {
|
||||
mResultPoints = CameraManager.get().convertResultPoints(resultPoints);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
}
|
74
android/src/com/android/barcodes/YUVMonochromeBitmapSource.java
Executable file
74
android/src/com/android/barcodes/YUVMonochromeBitmapSource.java
Executable file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.android.barcodes;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import com.google.zxing.common.BaseMonochromeBitmapSource;
|
||||
|
||||
/**
|
||||
* This object implements MonochromeBitmapSource around an array of YUV data, giving you the option
|
||||
* to crop to a rectangle within the full data. This can be used to exclude superfluous pixels
|
||||
* around the perimeter and speed up decoding.
|
||||
*/
|
||||
final class YUVMonochromeBitmapSource extends BaseMonochromeBitmapSource {
|
||||
|
||||
private final byte[] mYUVData;
|
||||
private final int mDataWidth;
|
||||
private final Rect mCrop;
|
||||
|
||||
/**
|
||||
* Builds an object around a YUV buffer from the camera.
|
||||
*
|
||||
* @param yuvData A byte array of planar Y data, followed by interleaved U and V
|
||||
* @param dataWidth The width of the Y data
|
||||
* @param dataHeight The height of the Y data
|
||||
* @param crop The rectangle within the yuvData to expose to MonochromeBitmapSource users
|
||||
*/
|
||||
YUVMonochromeBitmapSource(byte[] yuvData, int dataWidth, int dataHeight, Rect crop) {
|
||||
mYUVData = yuvData;
|
||||
mDataWidth = dataWidth;
|
||||
mCrop = crop;
|
||||
assert (crop.width() <= dataWidth);
|
||||
assert (crop.height() <= dataHeight);
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return mCrop.height();
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return mCrop.width();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Y channel is stored as planar data at the head of the array, so we just ignore the
|
||||
* interleavd U and V which follow it.
|
||||
*
|
||||
* @param x The x coordinate to fetch within crop
|
||||
* @param y The y coordinate to fetch within crop
|
||||
* @return The luminance as an int, from 0-255
|
||||
*/
|
||||
public int getLuminance(int x, int y) {
|
||||
return mYUVData[(y + mCrop.top) * mDataWidth + x + mCrop.left] & 0xff;
|
||||
}
|
||||
|
||||
// Nothing to do, since we have direct access to the mYUVData array.
|
||||
public void cacheRowForLuminance(int y) {
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue