Import zxing-core 1.7 and qr_scanner

Change-Id: I0e29ab078807cc5e4f958f36ddf8dd88e627b60e
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..5668d05
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,3 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/core/Android.mk b/core/Android.mk
new file mode 100644
index 0000000..b4027ed
--- /dev/null
+++ b/core/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := zxing-core-1.7:core.jar
+include $(BUILD_MULTI_PREBUILT)
diff --git a/core/MODULE_LICENSE_APACHE2 b/core/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/MODULE_LICENSE_APACHE2
diff --git a/core/NOTICE b/core/NOTICE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/core/NOTICE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/core/README.google b/core/README.google
new file mode 100644
index 0000000..03c873e
--- /dev/null
+++ b/core/README.google
@@ -0,0 +1,16 @@
+URL: svn checkout -r 1937 http://zxing.googlecode.com/svn/trunk/ zxing-read-only
+
+Version: 1.7.1 (Revision: r1937)
+
+License: Apache License 2.0
+
+License File: LICENSE
+
+Description:
+ZXing (pronounced "zebra crossing") is an open-source, multi-format 1D/2D
+barcode reader library implemented in Java. Our goal is to support decoding of
+QR Codes, Data Matrix, and the UPC family of 1D barcodes. It will provide
+clients for J2ME, J2SE, and Android.
+
+Local Modifications:
+No modifications.
diff --git a/core/core.jar b/core/core.jar
new file mode 100644
index 0000000..43a3140
--- /dev/null
+++ b/core/core.jar
Binary files differ
diff --git a/qr_scanner/AndroidManifest.xml b/qr_scanner/AndroidManifest.xml
new file mode 100644
index 0000000..eb1e711
--- /dev/null
+++ b/qr_scanner/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.google.zxing.client.android"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk android:minSdkVersion="7" />
+
+    <application >
+        <activity android:name="com.google.android.youtube.CaptureActivity" />
+    </application>
+
+    <uses-permission android:name="android.permission.CAMERA" />
+</manifest>
\ No newline at end of file
diff --git a/qr_scanner/README.google b/qr_scanner/README.google
new file mode 100644
index 0000000..fe7a13a
--- /dev/null
+++ b/qr_scanner/README.google
@@ -0,0 +1,14 @@
+URL: http://code.google.com/p/zxing/
+Version: 1.7.1
+License: Apache License 2.0
+License File: LICENSE
+
+Description:
+Android library that exposes an activity to capture QR codes. It is basically
+a stripped down version of ZXing's BarcodeScanner application, with all the 
+non-QR code scanning and the products, books and all other product recognition
+features remove.
+
+Local Modificaitons:
+Removed all code that is not directly related to scanning a QR code, such as product search, book
+search, 2D barcode scanning etc.
diff --git a/qr_scanner/proguard.cfg b/qr_scanner/proguard.cfg
new file mode 100644
index 0000000..b1cdf17
--- /dev/null
+++ b/qr_scanner/proguard.cfg
@@ -0,0 +1,40 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+   public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+  public static final android.os.Parcelable$Creator *;
+}
diff --git a/qr_scanner/project.properties b/qr_scanner/project.properties
new file mode 100644
index 0000000..337e8f3
--- /dev/null
+++ b/qr_scanner/project.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-7
+android.library=true
diff --git a/qr_scanner/res/drawable-hdpi/ic_launcher.png b/qr_scanner/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/qr_scanner/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/qr_scanner/res/drawable-ldpi/ic_launcher.png b/qr_scanner/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/qr_scanner/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/qr_scanner/res/drawable-mdpi/ic_launcher.png b/qr_scanner/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/qr_scanner/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/qr_scanner/res/layout/capture.xml b/qr_scanner/res/layout/capture.xml
new file mode 100755
index 0000000..eb3ab3e
--- /dev/null
+++ b/qr_scanner/res/layout/capture.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2008 ZXing authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="fill_parent"
+             android:layout_height="fill_parent">
+
+  <SurfaceView android:id="@+id/preview_view"
+               android:layout_width="fill_parent"
+               android:layout_height="fill_parent"
+               android:layout_centerInParent="true"/>
+
+  <com.google.zxing.client.android.ViewfinderView
+      android:id="@+id/viewfinder_view"
+      android:layout_width="fill_parent"
+      android:layout_height="fill_parent"
+      android:background="@color/transparent"/>
+
+  <TextView android:id="@+id/status_view"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="bottom|center_horizontal"
+            android:background="@color/transparent"
+            android:text="@string/msg_default_status"
+            android:textColor="@color/status_text"
+            android:textSize="14sp"/>
+
+</FrameLayout>
diff --git a/qr_scanner/res/values-ar/strings.xml b/qr_scanner/res/values-ar/strings.xml
new file mode 100644
index 0000000..a9d6968
--- /dev/null
+++ b/qr_scanner/res/values-ar/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"ضع رمز QR داخل مستطيل محدد المنظر لفحصه."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"عذرًا، لقد واجهت كاميرا Android مشكلة. قد تحتاج إلى إعادة تشغيل الجهاز."</string>
+</resources>
diff --git a/qr_scanner/res/values-bg/strings.xml b/qr_scanner/res/values-bg/strings.xml
new file mode 100644
index 0000000..bb66112
--- /dev/null
+++ b/qr_scanner/res/values-bg/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Поставете кода за бърза реакция в правоъгълника на визьора, за да го сканирате."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"За съжаление камерата на Android откри проблем. Може да се наложи да рестартирате устройството."</string>
+</resources>
diff --git a/qr_scanner/res/values-ca/strings.xml b/qr_scanner/res/values-ca/strings.xml
new file mode 100644
index 0000000..e9dec7f
--- /dev/null
+++ b/qr_scanner/res/values-ca/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Poseu un codi QR al rectangle del visor per explorar-lo."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"La càmera d\'Android ha detectat un problema. És possible que hàgiu de reiniciar el dispositiu."</string>
+</resources>
diff --git a/qr_scanner/res/values-cs/strings.xml b/qr_scanner/res/values-cs/strings.xml
new file mode 100644
index 0000000..cac83d3
--- /dev/null
+++ b/qr_scanner/res/values-cs/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Chcete-li naskenovat QR kód, umístěte jej do obdélníku hledáčku."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Došlo k potížím s fotoaparátem zařízení Android. Možná bude potřeba zařízení restartovat."</string>
+</resources>
diff --git a/qr_scanner/res/values-da/strings.xml b/qr_scanner/res/values-da/strings.xml
new file mode 100644
index 0000000..5e80f4b
--- /dev/null
+++ b/qr_scanner/res/values-da/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Placer en QR-kode inde i søgerens rektangel for at scanne den."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Der er desværre opstået et problem med Android-kameraet. Du er muligvis nødt til at genstarte enheden."</string>
+</resources>
diff --git a/qr_scanner/res/values-de/strings.xml b/qr_scanner/res/values-de/strings.xml
new file mode 100644
index 0000000..7505572
--- /dev/null
+++ b/qr_scanner/res/values-de/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Um einen QR-Code zu scannen, erfassen Sie diesen im Rechteck des Suchers."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Mit der Android-Kamera ist ein Problem aufgetreten. Sie müssen das Gerät möglicherweise neu starten."</string>
+</resources>
diff --git a/qr_scanner/res/values-el/strings.xml b/qr_scanner/res/values-el/strings.xml
new file mode 100644
index 0000000..73478e3
--- /dev/null
+++ b/qr_scanner/res/values-el/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Προσθέστε έναν κωδικό QR μέσα στο ορθογώνιο του στόχαστρου για να τον σαρώσετε."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Λυπούμαστε, παρουσιάστηκε πρόβλημα με τη φωτογραφική μηχανή Android. Ίσως χρειαστεί να πραγματοποιήσετε επανεκκίνηση της συσκευής."</string>
+</resources>
diff --git a/qr_scanner/res/values-en-rGB/strings.xml b/qr_scanner/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..1e0207d
--- /dev/null
+++ b/qr_scanner/res/values-en-rGB/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Place a QR code inside the viewfinder rectangle to scan it."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Sorry, the Android camera encountered a problem. You may need to restart the device."</string>
+</resources>
diff --git a/qr_scanner/res/values-es-rUS/strings.xml b/qr_scanner/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..6eaeb59
--- /dev/null
+++ b/qr_scanner/res/values-es-rUS/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Establece un código QR dentro del rectángulo del visor para analizarlo."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Lo sentimos, se ha producido un problema con la cámara de Android. Es posible que debas reiniciar el dispositivo."</string>
+</resources>
diff --git a/qr_scanner/res/values-es/strings.xml b/qr_scanner/res/values-es/strings.xml
new file mode 100644
index 0000000..4891bc8
--- /dev/null
+++ b/qr_scanner/res/values-es/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Coloca un código QR en el rectángulo del visor para escanearlo."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Se ha producido un error con la cámara de Android. Es posible que tengas que reiniciar el dispositivo."</string>
+</resources>
diff --git a/qr_scanner/res/values-et/strings.xml b/qr_scanner/res/values-et/strings.xml
new file mode 100644
index 0000000..bb6591f
--- /dev/null
+++ b/qr_scanner/res/values-et/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Kontrollimiseks paigutage QR-kood pildinäidiku ristkülikusse."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Kahjuks ilmnes Android-kaameraga probleem. Võib tekkida vajadus seade taaskäivitada."</string>
+</resources>
diff --git a/qr_scanner/res/values-fa/strings.xml b/qr_scanner/res/values-fa/strings.xml
new file mode 100644
index 0000000..693e0c6
--- /dev/null
+++ b/qr_scanner/res/values-fa/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"یک کد QR در داخل مستطیل نمایاب قرار دهید تا آن را اسکن کنید."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"متأسفیم، دوربین Android با مشکل مواجه شد. ممکن است لازم باشد دستگاه را مجداً راه اندازی کنید."</string>
+</resources>
diff --git a/qr_scanner/res/values-fi/strings.xml b/qr_scanner/res/values-fi/strings.xml
new file mode 100644
index 0000000..f00e9bd
--- /dev/null
+++ b/qr_scanner/res/values-fi/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Aseta QR-koodi etsimen suorakulmion sisälle lukeaksesi sen."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Virhe Android-kamerassa, pahoittelemme. Voit joutua käynnistämään laitteen uudelleen."</string>
+</resources>
diff --git a/qr_scanner/res/values-fr/strings.xml b/qr_scanner/res/values-fr/strings.xml
new file mode 100644
index 0000000..bd7dd9c
--- /dev/null
+++ b/qr_scanner/res/values-fr/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Positionnez un code 2D à l\'intérieur du rectangle du viseur pour le scanner."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Désolé, un problème est survenu au niveau de l\'appareil photo Android. Vous devrez peut-être redémarrer l\'appareil."</string>
+</resources>
diff --git a/qr_scanner/res/values-hi/strings.xml b/qr_scanner/res/values-hi/strings.xml
new file mode 100644
index 0000000..719aaf8
--- /dev/null
+++ b/qr_scanner/res/values-hi/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"दृश्यदर्शी आयत को स्कैन करने के लिए उसके अंदर एक QR कोड रखें."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"क्षमा करें, Android कैमरे में कोई समस्‍या आ गई है. आपको उपकरण पुन: प्रारंभ करने की आवश्यकता हो सकती है."</string>
+</resources>
diff --git a/qr_scanner/res/values-hr/strings.xml b/qr_scanner/res/values-hr/strings.xml
new file mode 100644
index 0000000..91e8596
--- /dev/null
+++ b/qr_scanner/res/values-hr/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Postavite QR kod unutar pravokutnika tražila da biste ga skenirali."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Žao nam je, Androidova kamera naišla je na problem. Možda ćete morati ponovo pokrenuti uređaj."</string>
+</resources>
diff --git a/qr_scanner/res/values-hu/strings.xml b/qr_scanner/res/values-hu/strings.xml
new file mode 100644
index 0000000..4bccf29
--- /dev/null
+++ b/qr_scanner/res/values-hu/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"A beolvasáshoz pozicionálja a QR-kódot a beolvasási mezőbe."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Elnézést kérünk, de az Android-kamera hibát észlelt. Lehet, hogy újra kell indítania az eszközt."</string>
+</resources>
diff --git a/qr_scanner/res/values-in/strings.xml b/qr_scanner/res/values-in/strings.xml
new file mode 100644
index 0000000..0f9bac6
--- /dev/null
+++ b/qr_scanner/res/values-in/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Masukkan kode QR ke dalam kotak bidang tilik untuk memindainya."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Maaf, kamera Android mengalami masalah. Anda mungkin harus memulai ulang perangkat."</string>
+</resources>
diff --git a/qr_scanner/res/values-it/strings.xml b/qr_scanner/res/values-it/strings.xml
new file mode 100644
index 0000000..1ae12b2
--- /dev/null
+++ b/qr_scanner/res/values-it/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Posiziona il rettangolo del mirino sopra il codice QR per eseguirne la scansione."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Spiacenti, si è verificato un problema con la fotocamera di Android. Potrebbe essere necessario riavviare il dispositivo."</string>
+</resources>
diff --git a/qr_scanner/res/values-iw/strings.xml b/qr_scanner/res/values-iw/strings.xml
new file mode 100644
index 0000000..75f4d96
--- /dev/null
+++ b/qr_scanner/res/values-iw/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"מקם קוד תגובה מהירה בתוך מלבן העינית כדי לסרוק אותו."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"מצטערים. מצלמת Android נתקלה בבעיה. ייתכן שתידרש להפעיל מחדש את המכשיר."</string>
+</resources>
diff --git a/qr_scanner/res/values-ja/strings.xml b/qr_scanner/res/values-ja/strings.xml
new file mode 100644
index 0000000..3acdff6
--- /dev/null
+++ b/qr_scanner/res/values-ja/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"QRコードをスキャンするには、ファインダーの四角形でQRコードを写してください。"</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Androidカメラで問題が発生しました。携帯端末の再起動をおすすめします。"</string>
+</resources>
diff --git a/qr_scanner/res/values-ko/strings.xml b/qr_scanner/res/values-ko/strings.xml
new file mode 100644
index 0000000..ea6ca46
--- /dev/null
+++ b/qr_scanner/res/values-ko/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"QR 코드를 스캔하려면 화면에 표시되는 사각형 안에 놓으세요."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"죄송합니다. Android 카메라에 문제가 발생했습니다. 기기를 다시 시작해야 할 수 있습니다."</string>
+</resources>
diff --git a/qr_scanner/res/values-lt/strings.xml b/qr_scanner/res/values-lt/strings.xml
new file mode 100644
index 0000000..b6a411b
--- /dev/null
+++ b/qr_scanner/res/values-lt/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Jei norite nuskaityti QR kodą, jis turi būti vaizdo ieškiklio stačiakampyje."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Apgailestaujame, bet iškilo su „Android“ fotoaparatu susijusi problema. Gali reikėti iš naujo paleisti įrenginį."</string>
+</resources>
diff --git a/qr_scanner/res/values-lv/strings.xml b/qr_scanner/res/values-lv/strings.xml
new file mode 100644
index 0000000..8a9097b
--- /dev/null
+++ b/qr_scanner/res/values-lv/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Lai skenētu ātrās atbildes kodu, ievietojiet to skatu meklētāja taisnstūrī."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Diemžēl Android kamerā radās problēma. Iespējams, jārestartē ierīce."</string>
+</resources>
diff --git a/qr_scanner/res/values-ms/strings.xml b/qr_scanner/res/values-ms/strings.xml
new file mode 100644
index 0000000..6210979
--- /dev/null
+++ b/qr_scanner/res/values-ms/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Letakkan kod QR di dalam segi empat tepat pemidang tilik untuk mengimbasnya."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Maaf, kamera Android menghadapai masalah. Anda mungkin perlu memulakan semula peranti ini."</string>
+</resources>
diff --git a/qr_scanner/res/values-nb/strings.xml b/qr_scanner/res/values-nb/strings.xml
new file mode 100644
index 0000000..c3f1d98
--- /dev/null
+++ b/qr_scanner/res/values-nb/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Plasser en QR-kode inne i synsvinkelrektanglet for å skanne den."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Beklager, men det oppsto et problem med Android-kameraet. Forsøk å starte enheten på nytt."</string>
+</resources>
diff --git a/qr_scanner/res/values-nl/strings.xml b/qr_scanner/res/values-nl/strings.xml
new file mode 100644
index 0000000..d169817
--- /dev/null
+++ b/qr_scanner/res/values-nl/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Plaats een QR-code in de rechthoek van de beeldzoeker om de code te scannen."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Er is een probleem met de Android-camera opgetreden. U moet het apparaat mogelijk opnieuw opstarten."</string>
+</resources>
diff --git a/qr_scanner/res/values-pl/strings.xml b/qr_scanner/res/values-pl/strings.xml
new file mode 100644
index 0000000..36d527e
--- /dev/null
+++ b/qr_scanner/res/values-pl/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Wyśrodkuj kod QR w prostokącie, by go zeskanować."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Niestety, wystąpił problem z obsługą aparatu w Androidzie. Może być konieczne ponowne uruchomienie urządzenia."</string>
+</resources>
diff --git a/qr_scanner/res/values-pt-rPT/strings.xml b/qr_scanner/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..12165e9
--- /dev/null
+++ b/qr_scanner/res/values-pt-rPT/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Coloque um código QR dentro do retângulo do visor para o ler."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"A câmara do Android encontrou um problema. Poderá ser necessário reiniciar o aparelho."</string>
+</resources>
diff --git a/qr_scanner/res/values-pt/strings.xml b/qr_scanner/res/values-pt/strings.xml
new file mode 100644
index 0000000..f119e3f
--- /dev/null
+++ b/qr_scanner/res/values-pt/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Coloque um código QR dentro do retângulo do visor para digitalizá-lo."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"A câmera do Android encontrou um problema. Talvez seja necessário reiniciar o dispositivo."</string>
+</resources>
diff --git a/qr_scanner/res/values-ro/strings.xml b/qr_scanner/res/values-ro/strings.xml
new file mode 100644
index 0000000..debf996
--- /dev/null
+++ b/qr_scanner/res/values-ro/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Pentru a scana un cod QR, plasaţi-l în interiorul dreptunghiului vizorului."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Ne pare rău, dar camera foto Android a întâmpinat o problemă. Ar putea fi nevoie să reporniţi dispozitivul."</string>
+</resources>
diff --git a/qr_scanner/res/values-ru/strings.xml b/qr_scanner/res/values-ru/strings.xml
new file mode 100644
index 0000000..3abcf5c
--- /dev/null
+++ b/qr_scanner/res/values-ru/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Чтобы отсканировать QR-код, наведите на него рамку видоискателя."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Ошибка камеры Android. Перезапустите устройство."</string>
+</resources>
diff --git a/qr_scanner/res/values-sk/strings.xml b/qr_scanner/res/values-sk/strings.xml
new file mode 100644
index 0000000..5f9f769
--- /dev/null
+++ b/qr_scanner/res/values-sk/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Ak chcete naskenovať kód QR, umiestnite ho do obdĺžnika hľadáčika."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Je nám ľúto, vyskytol sa problém s fotoaparátom v zariadení so systémom Android. Možno budete musieť zariadenie reštartovať."</string>
+</resources>
diff --git a/qr_scanner/res/values-sl/strings.xml b/qr_scanner/res/values-sl/strings.xml
new file mode 100644
index 0000000..512e156
--- /dev/null
+++ b/qr_scanner/res/values-sl/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Če želite optično prebrati kodo QR, jo postavite v pravokotnik iskala."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Težava v fotoaparatu Android. Morda bo treba znova zagnati napravo."</string>
+</resources>
diff --git a/qr_scanner/res/values-sr/strings.xml b/qr_scanner/res/values-sr/strings.xml
new file mode 100644
index 0000000..8eb152b
--- /dev/null
+++ b/qr_scanner/res/values-sr/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Поставите QR кôд у правоугаоник визира да бисте га скенирали."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Нажалост, Android камера је наишла на проблем. Можда ћете морати поново да покренете уређај."</string>
+</resources>
diff --git a/qr_scanner/res/values-sv/strings.xml b/qr_scanner/res/values-sv/strings.xml
new file mode 100644
index 0000000..db522af
--- /dev/null
+++ b/qr_scanner/res/values-sv/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Placera QR-koden i sökarens rektangel om du vill skanna den."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Det uppstod ett problem med Android-kameran. Du måste eventuellt starta om enheten."</string>
+</resources>
diff --git a/qr_scanner/res/values-th/strings.xml b/qr_scanner/res/values-th/strings.xml
new file mode 100644
index 0000000..da681ca
--- /dev/null
+++ b/qr_scanner/res/values-th/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"เล็งให้โค้ด QR อยู่ในสี่เหลี่ยมช่องมองภาพเพื่อทำการสแกน"</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"ขออภัย เกิดปัญหากับกล้องถ่ายรูปแอนดรอยด์ คุณอาจต้องรีสตาร์ทอุปกรณ์"</string>
+</resources>
diff --git a/qr_scanner/res/values-tl/strings.xml b/qr_scanner/res/values-tl/strings.xml
new file mode 100644
index 0000000..c79eb80
--- /dev/null
+++ b/qr_scanner/res/values-tl/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Maglagay ng QR code sa loob ng parihaba ng viewfinder upang i-scan ito."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Paumanhin, nakatagpo ng problema ang camera ng Android. Maaaring kailanganin mong i-restart ang device."</string>
+</resources>
diff --git a/qr_scanner/res/values-tr/strings.xml b/qr_scanner/res/values-tr/strings.xml
new file mode 100644
index 0000000..0fe38b7
--- /dev/null
+++ b/qr_scanner/res/values-tr/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Taranacak QR kodunu vizör çerçevesinin içine yerleştirin."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Maalesef, Android kamera bir sorunla karşılaştı. Cihazı yeniden başlatmanız gerekebilir."</string>
+</resources>
diff --git a/qr_scanner/res/values-uk/strings.xml b/qr_scanner/res/values-uk/strings.xml
new file mode 100644
index 0000000..10c37b7
--- /dev/null
+++ b/qr_scanner/res/values-uk/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Щоб зісканувати QR-код, розмістіть його в прямокутнику видошукача."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"На жаль, виникла проблема з камерою Android. Можливо, потрібно перезавантажити пристрій."</string>
+</resources>
diff --git a/qr_scanner/res/values-vi/strings.xml b/qr_scanner/res/values-vi/strings.xml
new file mode 100644
index 0000000..eefe895
--- /dev/null
+++ b/qr_scanner/res/values-vi/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"Đưa mã QR vào bên trong hình chữ nhật của kính ngắm để quét mã."</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"Rất tiếc, máy ảnh Android đã gặp sự cố. Bạn có thể cần khởi động lại thiết bị."</string>
+</resources>
diff --git a/qr_scanner/res/values-zh-rCN/strings.xml b/qr_scanner/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..3cead54
--- /dev/null
+++ b/qr_scanner/res/values-zh-rCN/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"将 QR 码放在取景器的矩形框内以便对它进行扫描。"</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"抱歉,此 Android 相机遇到问题,您可能需要重新启动此设备。"</string>
+</resources>
diff --git a/qr_scanner/res/values-zh-rTW/strings.xml b/qr_scanner/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..15fa162
--- /dev/null
+++ b/qr_scanner/res/values-zh-rTW/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="msg_default_status" msgid="639431501805022060">"將 QR 圖碼置入取景器的方框中即可開始掃描。"</string>
+    <string name="msg_camera_framework_bug" msgid="2167124836274973533">"很抱歉,Android 相機發生問題。您可能需要重新啟動裝置。"</string>
+</resources>
diff --git a/qr_scanner/res/values/colors.xml b/qr_scanner/res/values/colors.xml
new file mode 100644
index 0000000..f74f1be
--- /dev/null
+++ b/qr_scanner/res/values/colors.xml
@@ -0,0 +1,25 @@
+<resources>
+<color name="contents_text">#ff000000</color>
+<color name="encode_view">#ffffffff</color>
+<color name="help_button_view">#ffcccccc</color>
+<color name="help_view">#ff404040</color>
+<color name="possible_result_points">#c0ffff00</color>
+<color name="result_image_border">#ffffffff</color>
+<color name="result_minor_text">#ffc0c0c0</color>
+<color name="result_points">#c000ff00</color>
+<color name="result_text">#ffffffff</color>
+<color name="result_view">#b0000000</color>
+<color name="sbc_header_text">#ff808080</color>
+<color name="sbc_header_view">#ffffffff</color>
+<color name="sbc_list_item">#fffff0e0</color>
+<color name="sbc_layout_view">#ffffffff</color>
+<color name="sbc_page_number_text">#ff000000</color>
+<color name="sbc_snippet_text">#ff4b4b4b</color>
+<color name="share_text">#ff000000</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">#ffff0000</color>
+<color name="viewfinder_mask">#60000000</color>
+</resources>
\ No newline at end of file
diff --git a/qr_scanner/res/values/ids.xml b/qr_scanner/res/values/ids.xml
new file mode 100644
index 0000000..9739982
--- /dev/null
+++ b/qr_scanner/res/values/ids.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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="launch_product_query"/>
+  <item type="id" name="quit"/>
+  <item type="id" name="restart_preview"/>
+  <item type="id" name="return_scan_result"/>
+  <item type="id" name="search_book_contents_failed"/>
+  <item type="id" name="search_book_contents_succeeded"/>
+</resources>
diff --git a/qr_scanner/res/values/strings.xml b/qr_scanner/res/values/strings.xml
new file mode 100644
index 0000000..f574077
--- /dev/null
+++ b/qr_scanner/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Caption shown below the viewfinder rectangle, explaining how to scan a QR code [CHAR LIMIT=NONE] -->
+    <string name="msg_default_status">Place a QR code inside the viewfinder rectangle to scan it.</string>
+    <!-- Error message displayed when starting up the phone/tablet's camera to scan a QR code has failed [CHAR LIMIT=NONE] -->
+    <string name="msg_camera_framework_bug">Sorry, the Android camera encountered a problem. You may need to restart the device.</string>
+</resources>
\ No newline at end of file
diff --git a/qr_scanner/src/com/google/zxing/client/android/CaptureActivity.java b/qr_scanner/src/com/google/zxing/client/android/CaptureActivity.java
new file mode 100755
index 0000000..c65aadf
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/CaptureActivity.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.zxing.client.android;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.Result;
+import com.google.zxing.ResultPoint;
+import com.google.zxing.client.android.camera.CameraManager;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import java.io.IOException;
+
+/**
+ * This activity opens the camera and does the actual scanning on a background
+ * thread. It draws a viewfinder to help the user place the barcode correctly,
+ * shows feedback as the image processing is happening, and then overlays the
+ * results when a scan is successful.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ * @author Sean Owen
+ */
+public final class CaptureActivity extends Activity implements SurfaceHolder.Callback {
+
+  private static final String LOG_TAG = CaptureActivity.class.getCanonicalName();
+
+  private CameraManager cameraManager;
+  private CaptureActivityHandler handler;
+  private ViewfinderView viewfinderView;
+  private TextView statusView;
+  private boolean hasSurface;
+  private String characterSet;
+  private InactivityTimer inactivityTimer;
+
+  ViewfinderView getViewfinderView() {
+    return viewfinderView;
+  }
+
+  public Handler getHandler() {
+    return handler;
+  }
+
+  CameraManager getCameraManager() {
+    return cameraManager;
+  }
+
+  @Override
+  public void onCreate(Bundle icicle) {
+    super.onCreate(icicle);
+
+    Window window = getWindow();
+    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+    setContentView(R.layout.capture);
+
+    statusView = (TextView) findViewById(R.id.status_view);
+    handler = null;
+    hasSurface = false;
+    inactivityTimer = new InactivityTimer(this);
+  }
+
+  @Override
+  protected void onResume() {
+    super.onResume();
+
+    // CameraManager must be initialized here, not in onCreate(). This is
+    // necessary because we don't want to open the camera driver and measure the
+    // screen size if we're going to show the help on first launch. That led to
+    // bugs where the scanning rectangle was the wrong size and partially off
+    // screen.
+    cameraManager = new CameraManager(getApplication());
+    viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
+    viewfinderView.setCameraManager(cameraManager);
+
+    resetStatusView();
+
+    SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
+    SurfaceHolder surfaceHolder = surfaceView.getHolder();
+    if (hasSurface) {
+      // The activity was paused but not stopped, so the surface still exists.
+      // Therefore
+      // surfaceCreated() won't be called, so init the camera here.
+      initCamera(surfaceHolder);
+    } else {
+      // Install the callback and wait for surfaceCreated() to init the camera.
+      surfaceHolder.addCallback(this);
+      surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+    }
+
+    Intent intent = getIntent();
+    String action = intent == null ? null : intent.getAction();
+    String dataString = intent == null ? null : intent.getDataString();
+    if (intent != null && action != null) {
+      if (action.equals(Intents.Scan.ACTION)) {
+        if (intent.hasExtra(Intents.Scan.WIDTH) && intent.hasExtra(Intents.Scan.HEIGHT)) {
+          int width = intent.getIntExtra(Intents.Scan.WIDTH, 0);
+          int height = intent.getIntExtra(Intents.Scan.HEIGHT, 0);
+          if (width > 0 && height > 0) {
+            cameraManager.setManualFramingRect(width, height);
+          }
+        }
+      }
+      characterSet = intent.getStringExtra(Intents.Scan.CHARACTER_SET);
+    } else {
+      finish();
+    }
+
+    inactivityTimer.onResume();
+  }
+
+  @Override
+  protected void onPause() {
+    if (handler != null) {
+      handler.quitSynchronously();
+      handler = null;
+    }
+    inactivityTimer.onPause();
+    cameraManager.closeDriver();
+    if (!hasSurface) {
+      SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
+      SurfaceHolder surfaceHolder = surfaceView.getHolder();
+      surfaceHolder.removeCallback(this);
+    }
+    super.onPause();
+  }
+
+  @Override
+  protected void onDestroy() {
+    inactivityTimer.shutdown();
+    super.onDestroy();
+  }
+
+  @Override
+  public boolean onKeyDown(int keyCode, KeyEvent event) {
+    if (keyCode == KeyEvent.KEYCODE_BACK) {
+      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);
+  }
+
+  public void surfaceCreated(SurfaceHolder holder) {
+    if (holder == null) {
+      Log.e(LOG_TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
+    }
+    if (!hasSurface) {
+      hasSurface = true;
+      initCamera(holder);
+    }
+  }
+
+  public void surfaceDestroyed(SurfaceHolder holder) {
+    hasSurface = false;
+  }
+
+  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 barcode A greyscale bitmap of the camera data which was decoded.
+   */
+  public void handleDecode(Result rawResult, Bitmap barcode) {
+    inactivityTimer.onActivity();
+
+    if (barcode == null) {
+      Log.e(LOG_TAG, "Barcode not recognized");
+      setResult(RESULT_CANCELED, null);
+    } else {
+      drawResultPoints(barcode, rawResult);
+      Log.d(LOG_TAG, "Barcode is: " + rawResult.getText());
+      Intent result = new Intent();
+      result.putExtra("SCAN_RESULT", rawResult.getText());
+      setResult(RESULT_OK, result);
+    }
+    finish();
+  }
+
+  /**
+   * Superimpose a line for 1D or dots for 2D to highlight the key features of
+   * the barcode.
+   *
+   * @param barcode A bitmap of the captured image.
+   * @param rawResult The decoded results which contains the points to draw.
+   */
+  private void drawResultPoints(Bitmap barcode, Result rawResult) {
+    ResultPoint[] points = rawResult.getResultPoints();
+    if (points != null && points.length > 0) {
+      Canvas canvas = new Canvas(barcode);
+      Paint paint = new Paint();
+      paint.setColor(getResources().getColor(R.color.result_image_border));
+      paint.setStrokeWidth(3.0f);
+      paint.setStyle(Paint.Style.STROKE);
+      Rect border = new Rect(2, 2, barcode.getWidth() - 2, barcode.getHeight() - 2);
+      canvas.drawRect(border, paint);
+
+      paint.setColor(getResources().getColor(R.color.result_points));
+      if (points.length == 2) {
+        paint.setStrokeWidth(4.0f);
+        drawLine(canvas, paint, points[0], points[1]);
+      } else if (points.length == 4 && (rawResult.getBarcodeFormat() == BarcodeFormat.UPC_A
+          || rawResult.getBarcodeFormat() == BarcodeFormat.EAN_13)) {
+        // Hacky special case -- draw two lines, for the barcode and metadata
+        drawLine(canvas, paint, points[0], points[1]);
+        drawLine(canvas, paint, points[2], points[3]);
+      } else {
+        paint.setStrokeWidth(10.0f);
+        for (ResultPoint point : points) {
+          canvas.drawPoint(point.getX(), point.getY(), paint);
+        }
+      }
+    }
+  }
+
+  private static void drawLine(Canvas canvas, Paint paint, ResultPoint a, ResultPoint b) {
+    canvas.drawLine(a.getX(), a.getY(), b.getX(), b.getY(), paint);
+  }
+
+  private void initCamera(SurfaceHolder surfaceHolder) {
+    try {
+      cameraManager.openDriver(surfaceHolder);
+      // Creating the handler starts the preview, which can also throw a
+      // RuntimeException.
+      if (handler == null) {
+        handler = new CaptureActivityHandler(this, characterSet, cameraManager);
+      }
+    } catch (IOException ioe) {
+      Log.w(LOG_TAG, ioe);
+      displayFrameworkBugMessageAndExit();
+    } catch (RuntimeException e) {
+      // Barcode Scanner has seen crashes in the wild of this variety:
+      // java.?lang.?RuntimeException: Fail to connect to camera service
+      Log.w(LOG_TAG, "Unexpected error initializing camera", e);
+      displayFrameworkBugMessageAndExit();
+    }
+  }
+
+  private void displayFrameworkBugMessageAndExit() {
+    AlertDialog.Builder builder = new AlertDialog.Builder(this);
+    builder.setTitle("");
+    builder.setMessage(getString(R.string.msg_camera_framework_bug));
+    builder.setPositiveButton(android.R.string.ok, new FinishListener(this));
+    builder.setOnCancelListener(new FinishListener(this));
+    builder.show();
+  }
+
+  private void resetStatusView() {
+    statusView.setText(R.string.msg_default_status);
+    statusView.setVisibility(View.VISIBLE);
+    viewfinderView.setVisibility(View.VISIBLE);
+  }
+
+  public void drawViewfinder() {
+    viewfinderView.drawViewfinder();
+  }
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/CaptureActivityHandler.java b/qr_scanner/src/com/google/zxing/client/android/CaptureActivityHandler.java
new file mode 100755
index 0000000..71751a4
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/CaptureActivityHandler.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import com.google.zxing.Result;
+import com.google.zxing.client.android.camera.CameraManager;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * This class handles all the messaging which comprises the state machine for capture.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+public final class CaptureActivityHandler extends Handler {
+
+  private static final String TAG = CaptureActivityHandler.class.getSimpleName();
+
+  private final CaptureActivity activity;
+  private final DecodeThread decodeThread;
+  private State state;
+  private final CameraManager cameraManager;
+
+  private enum State {
+    PREVIEW,
+    SUCCESS,
+    DONE
+  }
+
+  CaptureActivityHandler(CaptureActivity activity,
+                         String characterSet,
+                         CameraManager cameraManager) {
+    this.activity = activity;
+    decodeThread = new DecodeThread(activity, characterSet,
+        new ViewfinderResultPointCallback(activity.getViewfinderView()));
+    decodeThread.start();
+    state = State.SUCCESS;
+
+    // Start ourselves capturing previews and decoding.
+    this.cameraManager = cameraManager;
+    cameraManager.startPreview();
+    restartPreviewAndDecode();
+  }
+
+  @Override
+  public void handleMessage(Message message) {
+    if (message.what == R.id.auto_focus) {
+      //Log.d(TAG, "Got auto-focus message");
+      // 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.
+      if (state == State.PREVIEW) {
+        cameraManager.requestAutoFocus(this, R.id.auto_focus);
+      }
+    } else if (message.what == R.id.restart_preview) {
+      Log.d(TAG, "Got restart preview message");
+      restartPreviewAndDecode();
+    } else if (message.what == R.id.decode_succeeded) {
+      Log.d(TAG, "Got decode succeeded message");
+      state = State.SUCCESS;
+      Bundle bundle = message.getData();
+      Bitmap barcode = bundle == null ? null :
+          (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);
+      activity.handleDecode((Result) message.obj, barcode);
+    } else if (message.what == R.id.decode_failed) {
+      // We're decoding as fast as possible, so when one decode fails, start another.
+      state = State.PREVIEW;
+      cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
+    } else if (message.what == R.id.return_scan_result) {
+      Log.d(TAG, "Got return scan result message");
+      activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
+      activity.finish();
+    } else if (message.what == R.id.launch_product_query) {
+      Log.d(TAG, "Got product query message");
+      String url = (String) message.obj;
+      Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+      intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+      activity.startActivity(intent);
+    }
+  }
+
+  public void quitSynchronously() {
+    state = State.DONE;
+    cameraManager.stopPreview();
+    Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
+    quit.sendToTarget();
+    try {
+      // Wait at most half a second; should be enough time, and onPause() will timeout quickly
+      decodeThread.join(500L);
+    } catch (InterruptedException e) {
+      // continue
+    }
+
+    // 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 (state == State.SUCCESS) {
+      state = State.PREVIEW;
+      cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
+      cameraManager.requestAutoFocus(this, R.id.auto_focus);
+      activity.drawViewfinder();
+    }
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/DecodeHandler.java b/qr_scanner/src/com/google/zxing/client/android/DecodeHandler.java
new file mode 100644
index 0000000..dfc0043
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/DecodeHandler.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.ReaderException;
+import com.google.zxing.Result;
+import com.google.zxing.common.HybridBinarizer;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import java.util.Hashtable;
+
+final class DecodeHandler extends Handler {
+
+  private static final String TAG = DecodeHandler.class.getSimpleName();
+
+  private final CaptureActivity activity;
+  private final MultiFormatReader multiFormatReader;
+  private boolean running = true;
+
+  DecodeHandler(CaptureActivity activity, Hashtable<DecodeHintType,Object> hints) {
+    multiFormatReader = new MultiFormatReader();
+    multiFormatReader.setHints(hints);
+    this.activity = activity;
+  }
+
+  @Override
+  public void handleMessage(Message message) {
+    if (!running) {
+      return;
+    }
+    if (message.what == R.id.decode) {
+      decode((byte[]) message.obj, message.arg1, message.arg2);
+    } else if (message.what == R.id.quit) {
+      running = false;
+      Looper.myLooper().quit();
+    }
+  }
+
+  /**
+   * 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) {
+    long start = System.currentTimeMillis();
+    Result rawResult = null;
+    PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);
+    if (source != null) {
+      BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+      try {
+        rawResult = multiFormatReader.decodeWithState(bitmap);
+      } catch (ReaderException re) {
+        // continue
+      } finally {
+        multiFormatReader.reset();
+      }
+    }
+
+    Handler handler = activity.getHandler();
+    if (rawResult != null) {
+      // Don't log the barcode contents for security.
+      long end = System.currentTimeMillis();
+      Log.d(TAG, "Found barcode in " + (end - start) + " ms");
+      if (handler != null) {
+        Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
+        message.setData(bundle);
+        message.sendToTarget();
+      }
+    } else {
+      if (handler != null) {
+        Message message = Message.obtain(handler, R.id.decode_failed);
+        message.sendToTarget();
+      }
+    }
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/DecodeThread.java b/qr_scanner/src/com/google/zxing/client/android/DecodeThread.java
new file mode 100755
index 0000000..70ea0c0
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/DecodeThread.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.ResultPointCallback;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * This thread does all the heavy lifting of decoding the images.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+final class DecodeThread extends Thread {
+
+  public static final String BARCODE_BITMAP = "barcode_bitmap";
+
+  private final CaptureActivity activity;
+  private final Hashtable<DecodeHintType,Object> hints;
+  private Handler handler;
+  private final CountDownLatch handlerInitLatch;
+
+  DecodeThread(CaptureActivity activity,
+               String characterSet,
+               ResultPointCallback resultPointCallback) {
+
+    this.activity = activity;
+    handlerInitLatch = new CountDownLatch(1);
+
+    hints = new Hashtable<DecodeHintType,Object>();
+    Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>();
+    formats.add(BarcodeFormat.QR_CODE);
+    hints.put(DecodeHintType.POSSIBLE_FORMATS, formats);
+
+    if (characterSet != null) {
+      hints.put(DecodeHintType.CHARACTER_SET, characterSet);
+    }
+    hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
+  }
+
+  Handler getHandler() {
+    try {
+      handlerInitLatch.await();
+    } catch (InterruptedException ie) {
+      // continue?
+    }
+    return handler;
+  }
+
+  @Override
+  public void run() {
+    Looper.prepare();
+    handler = new DecodeHandler(activity, hints);
+    handlerInitLatch.countDown();
+    Looper.loop();
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/FinishListener.java b/qr_scanner/src/com/google/zxing/client/android/FinishListener.java
new file mode 100644
index 0000000..e8c8813
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/FinishListener.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import android.app.Activity;
+import android.content.DialogInterface;
+
+/**
+ * Simple listener used to exit the app in a few cases.
+ *
+ * @author Sean Owen
+ */
+public final class FinishListener
+    implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable {
+
+  private final Activity activityToFinish;
+
+  public FinishListener(Activity activityToFinish) {
+    this.activityToFinish = activityToFinish;
+  }
+
+  public void onCancel(DialogInterface dialogInterface) {
+    run();
+  }
+
+  public void onClick(DialogInterface dialogInterface, int i) {
+    run();
+  }
+
+  public void run() {
+    activityToFinish.finish();
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/InactivityTimer.java b/qr_scanner/src/com/google/zxing/client/android/InactivityTimer.java
new file mode 100644
index 0000000..2883fba
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/InactivityTimer.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Finishes an activity after a period of inactivity if the device is on battery power.
+ */
+final class InactivityTimer {
+
+  private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
+
+  private final ScheduledExecutorService inactivityTimer =
+      Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
+  private final Activity activity;
+  private ScheduledFuture<?> inactivityFuture = null;
+  private final BroadcastReceiver powerStatusReceiver = new PowerStatusReceiver();
+
+  InactivityTimer(Activity activity) {
+    this.activity = activity;
+    onActivity();
+  }
+
+  void onActivity() {
+    cancel();
+    if (!inactivityTimer.isShutdown()) {
+      try {
+        inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
+            INACTIVITY_DELAY_SECONDS,
+            TimeUnit.SECONDS);
+      } catch (RejectedExecutionException ree) {
+        // surprising, but could be normal if for some reason the implementation just doesn't
+        // think it can shcedule again. Since this time-out is non-essential, just forget it
+      }
+    }
+  }
+
+  public void onPause() {
+    cancel();
+    activity.unregisterReceiver(powerStatusReceiver);
+  }
+
+  public void onResume(){
+    activity.registerReceiver(powerStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+    onActivity();
+  }
+
+  private void cancel() {
+    ScheduledFuture<?> future = inactivityFuture;
+    if (future != null) {
+      future.cancel(true);
+      inactivityFuture = null;
+    }
+  }
+
+  void shutdown() {
+    cancel();
+    inactivityTimer.shutdown();
+  }
+
+  private static final class DaemonThreadFactory implements ThreadFactory {
+    public Thread newThread(Runnable runnable) {
+      Thread thread = new Thread(runnable);
+      thread.setDaemon(true);
+      return thread;
+    }
+  }
+
+  private final class PowerStatusReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent){
+      if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
+        // 0 indicates that we're on battery
+        // In Android 2.0+, use BatteryManager.EXTRA_PLUGGED
+        int batteryPlugged = intent.getIntExtra("plugged", -1);
+        if (batteryPlugged > 0) {
+          InactivityTimer.this.cancel();
+        }
+      }
+    }
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/Intents.java b/qr_scanner/src/com/google/zxing/client/android/Intents.java
new file mode 100755
index 0000000..2bb1805
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/Intents.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+/**
+ * This class provides the constants to use when sending an Intent to Barcode Scanner.
+ * These strings are effectively API and cannot be changed.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+public final class Intents {
+  private 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.google.zxing.client.android.YOUTUBE_SCAN";
+
+    /**
+     * @see com.google.zxing.DecodeHintType#CHARACTER_SET
+     */
+    public static final String CHARACTER_SET = "CHARACTER_SET";
+
+    /**
+     * Optional parameters to specify the width and height of the scanning rectangle in pixels.
+     * The app will try to honor these, but will clamp them to the size of the preview frame.
+     * You should specify both or neither, and pass the size as an int.
+     */
+    public static final String WIDTH = "SCAN_WIDTH";
+    public static final String HEIGHT = "SCAN_HEIGHT";
+
+    private Scan() {
+    }
+  }
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/PlanarYUVLuminanceSource.java b/qr_scanner/src/com/google/zxing/client/android/PlanarYUVLuminanceSource.java
new file mode 100644
index 0000000..ed0a8a3
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/PlanarYUVLuminanceSource.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2009 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import com.google.zxing.LuminanceSource;
+
+import android.graphics.Bitmap;
+
+/**
+ * This object extends LuminanceSource around an array of YUV data returned from the camera driver,
+ * with 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.
+ *
+ * It works for any pixel format where the Y channel is planar and appears first, including
+ * YCbCr_420_SP and YCbCr_422_SP.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+public final class PlanarYUVLuminanceSource extends LuminanceSource {
+
+  private final byte[] yuvData;
+  private final int dataWidth;
+  private final int dataHeight;
+  private final int left;
+  private final int top;
+
+  public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top,
+      int width, int height, boolean reverseHorizontal) {
+    super(width, height);
+
+    if (left + width > dataWidth || top + height > dataHeight) {
+      throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
+    }
+
+    this.yuvData = yuvData;
+    this.dataWidth = dataWidth;
+    this.dataHeight = dataHeight;
+    this.left = left;
+    this.top = top;
+    if (reverseHorizontal) {
+      reverseHorizontal(width, height);
+    }
+  }
+
+  @Override
+  public byte[] getRow(int y, byte[] row) {
+    if (y < 0 || y >= getHeight()) {
+      throw new IllegalArgumentException("Requested row is outside the image: " + y);
+    }
+    int width = getWidth();
+    if (row == null || row.length < width) {
+      row = new byte[width];
+    }
+    int offset = (y + top) * dataWidth + left;
+    System.arraycopy(yuvData, offset, row, 0, width);
+    return row;
+  }
+
+  @Override
+  public byte[] getMatrix() {
+    int width = getWidth();
+    int height = getHeight();
+
+    // If the caller asks for the entire underlying image, save the copy and give them the
+    // original data. The docs specifically warn that result.length must be ignored.
+    if (width == dataWidth && height == dataHeight) {
+      return yuvData;
+    }
+
+    int area = width * height;
+    byte[] matrix = new byte[area];
+    int inputOffset = top * dataWidth + left;
+
+    // If the width matches the full width of the underlying data, perform a single copy.
+    if (width == dataWidth) {
+      System.arraycopy(yuvData, inputOffset, matrix, 0, area);
+      return matrix;
+    }
+
+    // Otherwise copy one cropped row at a time.
+    byte[] yuv = yuvData;
+    for (int y = 0; y < height; y++) {
+      int outputOffset = y * width;
+      System.arraycopy(yuv, inputOffset, matrix, outputOffset, width);
+      inputOffset += dataWidth;
+    }
+    return matrix;
+  }
+
+  @Override
+  public boolean isCropSupported() {
+    return true;
+  }
+
+  public Bitmap renderCroppedGreyscaleBitmap() {
+    int width = getWidth();
+    int height = getHeight();
+    int[] pixels = new int[width * height];
+    byte[] yuv = yuvData;
+    int inputOffset = top * dataWidth + left;
+
+    for (int y = 0; y < height; y++) {
+      int outputOffset = y * width;
+      for (int x = 0; x < width; x++) {
+        int grey = yuv[inputOffset + x] & 0xff;
+        pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);
+      }
+      inputOffset += dataWidth;
+    }
+
+    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
+    return bitmap;
+  }
+
+  private void reverseHorizontal(int width, int height) {
+    byte[] yuvData = this.yuvData;
+    for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) {
+      int middle = rowStart + width / 2;
+      for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {
+        byte temp = yuvData[x1];
+        yuvData[x1] = yuvData[x2];
+        yuvData[x2] = temp;
+      }
+    }
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/ViewfinderResultPointCallback.java b/qr_scanner/src/com/google/zxing/client/android/ViewfinderResultPointCallback.java
new file mode 100644
index 0000000..3754769
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/ViewfinderResultPointCallback.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import com.google.zxing.ResultPoint;
+import com.google.zxing.ResultPointCallback;
+
+final class ViewfinderResultPointCallback implements ResultPointCallback {
+
+  private final ViewfinderView viewfinderView;
+
+  ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
+    this.viewfinderView = viewfinderView;
+  }
+
+  public void foundPossibleResultPoint(ResultPoint point) {
+    viewfinderView.addPossibleResultPoint(point);
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/ViewfinderView.java b/qr_scanner/src/com/google/zxing/client/android/ViewfinderView.java
new file mode 100755
index 0000000..7ec9e3e
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/ViewfinderView.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android;
+
+import com.google.zxing.ResultPoint;
+import com.google.zxing.client.android.camera.CameraManager;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 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.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+public final class ViewfinderView extends View {
+
+  private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
+  private static final long ANIMATION_DELAY = 80L;
+  private static final int CURRENT_POINT_OPACITY = 0xA0;
+  private static final int MAX_RESULT_POINTS = 20;
+  private static final int POINT_SIZE = 6;
+
+  private CameraManager cameraManager;
+  private final Paint paint;
+  private Bitmap resultBitmap;
+  private final int maskColor;
+  private final int resultColor;
+  private final int frameColor;
+  private final int laserColor;
+  private final int resultPointColor;
+  private int scannerAlpha;
+  private List<ResultPoint> possibleResultPoints;
+  private List<ResultPoint> lastPossibleResultPoints;
+
+  // This constructor is used when the class is built from an XML resource.
+  public ViewfinderView(Context context, AttributeSet attrs) {
+    super(context, attrs);
+
+    // Initialize these once for performance rather than calling them every time in onDraw().
+    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    Resources resources = getResources();
+    maskColor = resources.getColor(R.color.viewfinder_mask);
+    resultColor = resources.getColor(R.color.result_view);
+    frameColor = resources.getColor(R.color.viewfinder_frame);
+    laserColor = resources.getColor(R.color.viewfinder_laser);
+    resultPointColor = resources.getColor(R.color.possible_result_points);
+    scannerAlpha = 0;
+    possibleResultPoints = new ArrayList<ResultPoint>(5);
+    lastPossibleResultPoints = null;
+  }
+
+  public void setCameraManager(CameraManager cameraManager) {
+    this.cameraManager = cameraManager;
+  }
+
+  @Override
+  public void onDraw(Canvas canvas) {
+    Rect frame = cameraManager.getFramingRect();
+    if (frame == null) {
+      return;
+    }
+    int width = canvas.getWidth();
+    int height = canvas.getHeight();
+
+    // Draw the exterior (i.e. outside the framing rect) darkened
+    paint.setColor(resultBitmap != null ? resultColor : maskColor);
+    canvas.drawRect(0, 0, width, frame.top, paint);
+    canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
+    canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
+    canvas.drawRect(0, frame.bottom + 1, width, height, paint);
+
+    if (resultBitmap != null) {
+      // Draw the opaque result bitmap over the scanning rectangle
+      paint.setAlpha(CURRENT_POINT_OPACITY);
+      canvas.drawBitmap(resultBitmap, null, frame, paint);
+    } else {
+
+      // Draw a two pixel solid black border inside the framing rect
+      paint.setColor(frameColor);
+      canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
+      canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
+      canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
+      canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);
+
+      // Draw a red "laser scanner" line through the middle to show decoding is active
+      paint.setColor(laserColor);
+      paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
+      scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
+      int middle = frame.height() / 2 + frame.top;
+      canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
+      
+      Rect previewFrame = cameraManager.getFramingRectInPreview();
+      float scaleX = frame.width() / (float) previewFrame.width();
+      float scaleY = frame.height() / (float) previewFrame.height();
+
+      List<ResultPoint> currentPossible = possibleResultPoints;
+      List<ResultPoint> currentLast = lastPossibleResultPoints;
+      int frameLeft = frame.left;
+      int frameTop = frame.top;
+      if (currentPossible.isEmpty()) {
+        lastPossibleResultPoints = null;
+      } else {
+        possibleResultPoints = new ArrayList<ResultPoint>(5);
+        lastPossibleResultPoints = currentPossible;
+        paint.setAlpha(CURRENT_POINT_OPACITY);
+        paint.setColor(resultPointColor);
+        synchronized (currentPossible) {
+          for (ResultPoint point : currentPossible) {
+            canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX),
+                              frameTop + (int) (point.getY() * scaleY),
+                              POINT_SIZE, paint);
+          }
+        }
+      }
+      if (currentLast != null) {
+        paint.setAlpha(CURRENT_POINT_OPACITY / 2);
+        paint.setColor(resultPointColor);
+        synchronized (currentLast) {
+          for (ResultPoint point : currentLast) {
+            canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX),
+                              frameTop + (int) (point.getY() * scaleY),
+                              POINT_SIZE / 2, paint);
+          }
+        }
+      }
+
+      // Request another update at the animation interval, but only repaint the laser line,
+      // not the entire viewfinder mask.
+      postInvalidateDelayed(ANIMATION_DELAY,
+                            frame.left - POINT_SIZE,
+                            frame.top - POINT_SIZE,
+                            frame.right + POINT_SIZE,
+                            frame.bottom + POINT_SIZE);
+    }
+  }
+
+  public void drawViewfinder() {
+    Bitmap resultBitmap = this.resultBitmap;
+    this.resultBitmap = null;
+    if (resultBitmap != null) {
+      resultBitmap.recycle();
+    }
+    invalidate();
+  }
+
+  /**
+   * Draw a bitmap with the result points highlighted instead of the live scanning display.
+   *
+   * @param barcode An image of the decoded barcode.
+   */
+  public void drawResultBitmap(Bitmap barcode) {
+    resultBitmap = barcode;
+    invalidate();
+  }
+
+  public void addPossibleResultPoint(ResultPoint point) {
+    List<ResultPoint> points = possibleResultPoints;
+    synchronized (point) {
+      points.add(point);
+      int size = points.size();
+      if (size > MAX_RESULT_POINTS) {
+        // trim it
+        points.subList(0, size - MAX_RESULT_POINTS / 2).clear();
+      }
+    }
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/camera/AutoFocusCallback.java b/qr_scanner/src/com/google/zxing/client/android/camera/AutoFocusCallback.java
new file mode 100644
index 0000000..1e3f199
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/camera/AutoFocusCallback.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android.camera;
+
+import android.hardware.Camera;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+final class AutoFocusCallback implements Camera.AutoFocusCallback {
+
+  private static final String TAG = AutoFocusCallback.class.getSimpleName();
+
+  private static final long AUTOFOCUS_INTERVAL_MS = 1500L;
+
+  private Handler autoFocusHandler;
+  private int autoFocusMessage;
+
+  void setHandler(Handler autoFocusHandler, int autoFocusMessage) {
+    this.autoFocusHandler = autoFocusHandler;
+    this.autoFocusMessage = autoFocusMessage;
+  }
+
+  public void onAutoFocus(boolean success, Camera camera) {
+    if (autoFocusHandler != null) {
+      Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
+      // Simulate continuous autofocus by sending a focus request every
+      // AUTOFOCUS_INTERVAL_MS milliseconds.
+      //Log.d(TAG, "Got auto-focus callback; requesting another");
+      autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);
+      autoFocusHandler = null;
+    } else {
+      Log.d(TAG, "Got auto-focus callback, but no handler for it");
+    }
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/camera/CameraConfigurationManager.java b/qr_scanner/src/com/google/zxing/client/android/camera/CameraConfigurationManager.java
new file mode 100644
index 0000000..6a694b0
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/camera/CameraConfigurationManager.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android.camera;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Point;
+import android.hardware.Camera;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.Display;
+import android.view.WindowManager;
+
+import java.util.Collection;
+
+/**
+ * A class which deals with reading, parsing, and setting the camera parameters which are used to
+ * configure the camera hardware.
+ */
+final class CameraConfigurationManager {
+
+  private static final String TAG = "CameraConfiguration";
+  private static final int MIN_PREVIEW_PIXELS = 320 * 240; // small screen
+  private static final int MAX_PREVIEW_PIXELS = 800 * 480; // large/HD screen
+
+  private final Context context;
+  private Point screenResolution;
+  private Point cameraResolution;
+
+  CameraConfigurationManager(Context context) {
+    this.context = context;
+  }
+
+  /**
+   * Reads, one time, values from the camera that are needed by the app.
+   */
+  void initFromCameraParameters(Camera camera) {
+    Camera.Parameters parameters = camera.getParameters();
+    WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+    Display display = manager.getDefaultDisplay();
+    int width = display.getWidth();
+    int height = display.getHeight();
+    // We're landscape-only, and have apparently seen issues with display thinking it's portrait 
+    // when waking from sleep. If it's not landscape, assume it's mistaken and reverse them:
+    if (width < height) {
+      Log.i(TAG, "Display reports portrait orientation; assuming this is incorrect");
+      int temp = width;
+      width = height;
+      height = temp;
+    }
+    screenResolution = new Point(width, height);
+    Log.i(TAG, "Screen resolution: " + screenResolution);
+    cameraResolution = findBestPreviewSizeValue(parameters, screenResolution, false);
+    Log.i(TAG, "Camera resolution: " + cameraResolution);
+  }
+
+  void setDesiredCameraParameters(Camera camera) {
+    Camera.Parameters parameters = camera.getParameters();
+
+    if (parameters == null) {
+      Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration.");
+      return;
+    }
+
+    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+    initializeTorch(parameters, prefs);
+    String focusMode = findSettableValue(parameters.getSupportedFocusModes(),
+                                         Camera.Parameters.FOCUS_MODE_AUTO,
+                                         Camera.Parameters.FOCUS_MODE_MACRO);
+    if (focusMode != null) {
+      parameters.setFocusMode(focusMode);
+    }
+
+    parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
+    camera.setParameters(parameters);
+  }
+
+  Point getCameraResolution() {
+    return cameraResolution;
+  }
+
+  Point getScreenResolution() {
+    return screenResolution;
+  }
+
+  void setTorch(Camera camera, boolean newSetting) {
+    Camera.Parameters parameters = camera.getParameters();
+    doSetTorch(parameters, newSetting);
+    camera.setParameters(parameters);
+    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+    boolean currentSetting = false; // prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false);
+//    if (currentSetting != newSetting) {
+//      SharedPreferences.Editor editor = prefs.edit();
+//      editor.putBoolean(PreferencesActivity.KEY_FRONT_LIGHT, newSetting);
+//      editor.commit();
+//    }
+  }
+
+  private static void initializeTorch(Camera.Parameters parameters, SharedPreferences prefs) {
+    boolean currentSetting = false;// prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false);
+    doSetTorch(parameters, currentSetting);
+  }
+
+  private static void doSetTorch(Camera.Parameters parameters, boolean newSetting) {
+    String flashMode;
+    if (newSetting) {
+      flashMode = findSettableValue(parameters.getSupportedFlashModes(),
+                                    Camera.Parameters.FLASH_MODE_TORCH,
+                                    Camera.Parameters.FLASH_MODE_ON);
+    } else {
+      flashMode = findSettableValue(parameters.getSupportedFlashModes(),
+                                    Camera.Parameters.FLASH_MODE_OFF);
+    }
+    if (flashMode != null) {
+      parameters.setFlashMode(flashMode);
+    }
+  }
+
+  private static Point findBestPreviewSizeValue(Camera.Parameters parameters,
+                                                Point screenResolution,
+                                                boolean portrait) {
+    Point bestSize = null;
+    int diff = Integer.MAX_VALUE;
+    for (Camera.Size supportedPreviewSize : parameters.getSupportedPreviewSizes()) {
+      int pixels = supportedPreviewSize.height * supportedPreviewSize.width;
+      if (pixels < MIN_PREVIEW_PIXELS || pixels > MAX_PREVIEW_PIXELS) {
+        continue;
+      }
+      int supportedWidth = portrait ? supportedPreviewSize.height : supportedPreviewSize.width;
+      int supportedHeight = portrait ? supportedPreviewSize.width : supportedPreviewSize.height;
+      int newDiff = Math.abs(screenResolution.x * supportedHeight - supportedWidth * screenResolution.y);
+      if (newDiff == 0) {
+        bestSize = new Point(supportedWidth, supportedHeight);
+        break;
+      }
+      if (newDiff < diff) {
+        bestSize = new Point(supportedWidth, supportedHeight);
+        diff = newDiff;
+      }
+    }
+    if (bestSize == null) {
+      Camera.Size defaultSize = parameters.getPreviewSize();
+      bestSize = new Point(defaultSize.width, defaultSize.height);
+    }
+    return bestSize;
+  }
+
+  private static String findSettableValue(Collection<String> supportedValues,
+                                          String... desiredValues) {
+    Log.i(TAG, "Supported values: " + supportedValues);
+    String result = null;
+    if (supportedValues != null) {
+      for (String desiredValue : desiredValues) {
+        if (supportedValues.contains(desiredValue)) {
+          result = desiredValue;
+          break;
+        }
+      }
+    }
+    Log.i(TAG, "Settable value: " + result);
+    return result;
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/camera/CameraManager.java b/qr_scanner/src/com/google/zxing/client/android/camera/CameraManager.java
new file mode 100755
index 0000000..4df7cb1
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/camera/CameraManager.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android.camera;
+
+import com.google.zxing.client.android.PlanarYUVLuminanceSource;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.Camera;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.IOException;
+
+/**
+ * This object wraps the Camera service object and expects to be the only one talking to it. The
+ * implementation encapsulates the steps needed to take preview-sized images, which are used for
+ * both preview and decoding.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+public final class CameraManager {
+
+  private static final String TAG = CameraManager.class.getSimpleName();
+
+  private static final int MIN_FRAME_WIDTH = 240;
+  private static final int MIN_FRAME_HEIGHT = 240;
+  private static final int MAX_FRAME_WIDTH = 600;
+  private static final int MAX_FRAME_HEIGHT = 400;
+
+  private final Context context;
+  private final CameraConfigurationManager configManager;
+  private Camera camera;
+  private Rect framingRect;
+  private Rect framingRectInPreview;
+  private boolean initialized;
+  private boolean previewing;
+  private boolean reverseImage;
+  private int requestedFramingRectWidth;
+  private int requestedFramingRectHeight;
+  /**
+   * 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 PreviewCallback previewCallback;
+  /** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */
+  private final AutoFocusCallback autoFocusCallback;
+
+  public CameraManager(Context context) {
+    this.context = context;
+    this.configManager = new CameraConfigurationManager(context);
+    previewCallback = new PreviewCallback(configManager);
+    autoFocusCallback = new AutoFocusCallback();
+  }
+
+  /**
+   * Opens the camera driver and initializes the hardware parameters.
+   *
+   * @param holder The surface object which the camera will draw preview frames into.
+   * @throws IOException Indicates the camera driver failed to open.
+   */
+  public void openDriver(SurfaceHolder holder) throws IOException {
+    Camera theCamera = camera;
+    if (theCamera == null) {
+      theCamera = Camera.open();
+      if (theCamera == null) {
+        throw new IOException();
+      }
+      camera = theCamera;
+    }
+    theCamera.setPreviewDisplay(holder);
+
+    if (!initialized) {
+      initialized = true;
+      configManager.initFromCameraParameters(theCamera);
+      if (requestedFramingRectWidth > 0 && requestedFramingRectHeight > 0) {
+        setManualFramingRect(requestedFramingRectWidth, requestedFramingRectHeight);
+        requestedFramingRectWidth = 0;
+        requestedFramingRectHeight = 0;
+      }
+    }
+    configManager.setDesiredCameraParameters(theCamera);
+
+    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+    reverseImage = false;
+  }
+
+  /**
+   * Closes the camera driver if still in use.
+   */
+  public void closeDriver() {
+    if (camera != null) {
+      camera.release();
+      camera = null;
+      // Make sure to clear these each time we close the camera, so that any scanning rect
+      // requested by intent is forgotten.
+      framingRect = null;
+      framingRectInPreview = null;
+    }
+  }
+
+  /**
+   * Asks the camera hardware to begin drawing preview frames to the screen.
+   */
+  public void startPreview() {
+    Camera theCamera = camera;
+    if (theCamera != null && !previewing) {
+      theCamera.startPreview();
+      previewing = true;
+    }
+  }
+
+  /**
+   * Tells the camera to stop drawing preview frames.
+   */
+  public void stopPreview() {
+    if (camera != null && previewing) {
+      camera.stopPreview();
+      previewCallback.setHandler(null, 0);
+      autoFocusCallback.setHandler(null, 0);
+      previewing = false;
+    }
+  }
+
+  /**
+   * A single preview frame will be returned to the handler supplied. The data will arrive as byte[]
+   * in the message.obj field, with width and height encoded as message.arg1 and message.arg2,
+   * respectively.
+   *
+   * @param handler The handler to send the message to.
+   * @param message The what field of the message to be sent.
+   */
+  public void requestPreviewFrame(Handler handler, int message) {
+    Camera theCamera = camera;
+    if (theCamera != null && previewing) {
+      previewCallback.setHandler(handler, message);
+      theCamera.setOneShotPreviewCallback(previewCallback);
+    }
+  }
+
+  /**
+   * Asks the camera hardware to perform an autofocus.
+   *
+   * @param handler The Handler to notify when the autofocus completes.
+   * @param message The message to deliver.
+   */
+  public void requestAutoFocus(Handler handler, int message) {
+    if (camera != null && previewing) {
+      autoFocusCallback.setHandler(handler, message);
+      camera.autoFocus(autoFocusCallback);
+    }
+  }
+
+  /**
+   * Calculates the framing rect which the UI should draw to show the user where to place the
+   * barcode. This target helps with alignment as well as forces the user to hold the device
+   * far enough away to ensure the image will be in focus.
+   *
+   * @return The rectangle to draw on screen in window coordinates.
+   */
+  public Rect getFramingRect() {
+    if (framingRect == null) {
+      if (camera == null) {
+        return null;
+      }
+      Point screenResolution = configManager.getScreenResolution();
+      int width = screenResolution.x * 3 / 4;
+      if (width < MIN_FRAME_WIDTH) {
+        width = MIN_FRAME_WIDTH;
+      } else if (width > MAX_FRAME_WIDTH) {
+        width = MAX_FRAME_WIDTH;
+      }
+      int height = screenResolution.y * 3 / 4;
+      if (height < MIN_FRAME_HEIGHT) {
+        height = MIN_FRAME_HEIGHT;
+      } else if (height > MAX_FRAME_HEIGHT) {
+        height = MAX_FRAME_HEIGHT;
+      }
+      int leftOffset = (screenResolution.x - width) / 2;
+      int topOffset = (screenResolution.y - height) / 2;
+      framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
+      Log.d(TAG, "Calculated framing rect: " + framingRect);
+    }
+    return framingRect;
+  }
+
+  /**
+   * Like {@link #getFramingRect} but coordinates are in terms of the preview frame,
+   * not UI / screen.
+   */
+  public Rect getFramingRectInPreview() {
+    if (framingRectInPreview == null) {
+      Rect framingRect = getFramingRect();
+      if (framingRect == null) {
+        return null;
+      }
+      Rect rect = new Rect(framingRect);
+      Point cameraResolution = configManager.getCameraResolution(); 
+      if (cameraResolution == null) {
+        return framingRect;
+      }
+      Point screenResolution = configManager.getScreenResolution();
+      rect.left = rect.left * cameraResolution.x / screenResolution.x;
+      rect.right = rect.right * cameraResolution.x / screenResolution.x;
+      rect.top = rect.top * cameraResolution.y / screenResolution.y;
+      rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
+      framingRectInPreview = rect;
+    }
+    return framingRectInPreview;
+  }
+
+  /**
+   * Allows third party apps to specify the scanning rectangle dimensions, rather than determine
+   * them automatically based on screen resolution.
+   *
+   * @param width The width in pixels to scan.
+   * @param height The height in pixels to scan.
+   */
+  public void setManualFramingRect(int width, int height) {
+    if (initialized) {
+      Point screenResolution = configManager.getScreenResolution();
+      if (width > screenResolution.x) {
+        width = screenResolution.x;
+      }
+      if (height > screenResolution.y) {
+        height = screenResolution.y;
+      }
+      int leftOffset = (screenResolution.x - width) / 2;
+      int topOffset = (screenResolution.y - height) / 2;
+      framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
+      Log.d(TAG, "Calculated manual framing rect: " + framingRect);
+      framingRectInPreview = null;
+    } else {
+      requestedFramingRectWidth = width;
+      requestedFramingRectHeight = height;
+    }
+  }
+
+  /**
+   * A factory method to build the appropriate LuminanceSource object based on the format
+   * of the preview buffers, as described by Camera.Parameters.
+   *
+   * @param data A preview frame.
+   * @param width The width of the image.
+   * @param height The height of the image.
+   * @return A PlanarYUVLuminanceSource instance.
+   */
+  public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
+    Rect rect = getFramingRectInPreview();
+    if (rect == null) {
+      return null;
+    }
+    // Go ahead and assume it's YUV rather than die.
+    return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
+                                        rect.width(), rect.height(), reverseImage);
+  }
+
+}
diff --git a/qr_scanner/src/com/google/zxing/client/android/camera/PreviewCallback.java b/qr_scanner/src/com/google/zxing/client/android/camera/PreviewCallback.java
new file mode 100644
index 0000000..4a75cfe
--- /dev/null
+++ b/qr_scanner/src/com/google/zxing/client/android/camera/PreviewCallback.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android.camera;
+
+import android.graphics.Point;
+import android.hardware.Camera;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+final class PreviewCallback implements Camera.PreviewCallback {
+
+  private static final String TAG = PreviewCallback.class.getSimpleName();
+
+  private final CameraConfigurationManager configManager;
+  private Handler previewHandler;
+  private int previewMessage;
+
+  PreviewCallback(CameraConfigurationManager configManager) {
+    this.configManager = configManager;
+  }
+
+  void setHandler(Handler previewHandler, int previewMessage) {
+    this.previewHandler = previewHandler;
+    this.previewMessage = previewMessage;
+  }
+
+  public void onPreviewFrame(byte[] data, Camera camera) {
+    Point cameraResolution = configManager.getCameraResolution();
+    Handler thePreviewHandler = previewHandler;
+    if (thePreviewHandler != null) {
+      Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
+          cameraResolution.y, data);
+      message.sendToTarget();
+      previewHandler = null;
+    } else {
+      Log.d(TAG, "Got preview callback, but no handler for it");
+    }
+  }
+
+}