diff options
author | Bryan Mawhinney <bryanmawhinney@google.com> | 2012-05-03 18:02:26 +0100 |
---|---|---|
committer | Bryan Mawhinney <bryanmawhinney@google.com> | 2012-05-03 18:02:26 +0100 |
commit | 7620644768ffc235607b3a94671e49518c18686f (patch) | |
tree | 1f19feb5204b38fbeb90b58c535ba6a7e26e51ba | |
parent | 8dab53a2e7248ddba49f06d9f0beeb261b8fa589 (diff) | |
download | zxing-jb-mr1-dev-plus-aosp.tar.gz |
Import zxing-core 1.7 and qr_scannerandroid-sdk-support_r11android-sdk-4.4.2_r1.0.1android-sdk-4.4.2_r1android-l-preview_r2android-cts-4.4_r4android-cts-4.4_r1android-cts-4.2_r2android-cts-4.2_r1android-cts-4.1_r4android-cts-4.1_r2android-cts-4.1_r1android-4.4w_r1android-4.4_r1.2.0.1android-4.4_r1.2android-4.4_r1.1.0.1android-4.4_r1.1android-4.4_r1.0.1android-4.4_r1android-4.4_r0.9android-4.4_r0.8android-4.4_r0.7android-4.4.4_r2.0.1android-4.4.4_r2android-4.4.4_r1.0.1android-4.4.4_r1android-4.4.3_r1.1.0.1android-4.4.3_r1.1android-4.4.3_r1.0.1android-4.4.3_r1android-4.4.2_r2.0.1android-4.4.2_r2android-4.4.2_r1.0.1android-4.4.2_r1android-4.4.1_r1.0.1android-4.4.1_r1android-4.3_r3.1android-4.3_r3android-4.3_r2.3android-4.3_r2.2android-4.3_r2.1android-4.3_r2android-4.3_r1.1android-4.3_r1android-4.3_r0.9.1android-4.3_r0.9android-4.3.1_r1android-4.2_r1android-4.2.2_r1.2android-4.2.2_r1.1android-4.2.2_r1android-4.2.1_r1.2android-4.2.1_r1.1android-4.2.1_r1android-4.1.2_r2.1android-4.1.2_r2android-4.1.2_r1android-4.1.1_r6.1android-4.1.1_r6android-4.1.1_r5android-4.1.1_r4android-4.1.1_r3android-4.1.1_r2android-4.1.1_r1.1android-4.1.1_r1tools_r22.2tools_r22tools_r21l-previewkitkat-wearkitkat-releasekitkat-mr2.2-releasekitkat-mr2.1-releasekitkat-mr2-releasekitkat-mr1.1-releasekitkat-mr1-releasekitkat-devkitkat-cts-releasekitkat-cts-devjb-releasejb-mr2.0.0-releasejb-mr2.0-releasejb-mr2-releasejb-mr2-devjb-mr1.1-releasejb-mr1.1-dev-plus-aospjb-mr1.1-devjb-mr1-releasejb-mr1-dev-plus-aospjb-mr1-devjb-mr0-releasejb-devidea133-weekly-releaseidea133
Change-Id: I0e29ab078807cc5e4f958f36ddf8dd88e627b60e
76 files changed, 2593 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk new file mode 100644 index 000000000..5668d0520 --- /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 000000000..e69de29bb --- /dev/null +++ b/MODULE_LICENSE_APACHE2 @@ -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 000000000..b4027ede8 --- /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 000000000..e69de29bb --- /dev/null +++ b/core/MODULE_LICENSE_APACHE2 diff --git a/core/NOTICE b/core/NOTICE new file mode 100644 index 000000000..261eeb9e9 --- /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 000000000..03c873ef9 --- /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 Binary files differnew file mode 100644 index 000000000..43a314099 --- /dev/null +++ b/core/core.jar diff --git a/qr_scanner/AndroidManifest.xml b/qr_scanner/AndroidManifest.xml new file mode 100644 index 000000000..eb1e711bb --- /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 000000000..fe7a13a27 --- /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 000000000..b1cdf17b5 --- /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 000000000..337e8f37d --- /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 Binary files differnew file mode 100644 index 000000000..8074c4c57 --- /dev/null +++ b/qr_scanner/res/drawable-hdpi/ic_launcher.png diff --git a/qr_scanner/res/drawable-ldpi/ic_launcher.png b/qr_scanner/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..1095584ec --- /dev/null +++ b/qr_scanner/res/drawable-ldpi/ic_launcher.png diff --git a/qr_scanner/res/drawable-mdpi/ic_launcher.png b/qr_scanner/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..a07c69fa5 --- /dev/null +++ b/qr_scanner/res/drawable-mdpi/ic_launcher.png diff --git a/qr_scanner/res/layout/capture.xml b/qr_scanner/res/layout/capture.xml new file mode 100755 index 000000000..eb3ab3e45 --- /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 000000000..a9d6968ac --- /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 000000000..bb6611295 --- /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 000000000..e9dec7fe5 --- /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 000000000..cac83d30d --- /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 000000000..5e80f4bd4 --- /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 000000000..750557208 --- /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 000000000..73478e300 --- /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 000000000..1e0207d1b --- /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 000000000..6eaeb5933 --- /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 000000000..4891bc8c4 --- /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 000000000..bb6591fd0 --- /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 000000000..693e0c683 --- /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 000000000..f00e9bd85 --- /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 000000000..bd7dd9ce6 --- /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 000000000..719aaf881 --- /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 000000000..91e85969e --- /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 000000000..4bccf2911 --- /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 000000000..0f9bac65d --- /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 000000000..1ae12b29d --- /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 000000000..75f4d967a --- /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 000000000..3acdff61e --- /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 000000000..ea6ca4652 --- /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 000000000..b6a411b22 --- /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 000000000..8a9097b51 --- /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 000000000..621097968 --- /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 000000000..c3f1d98ac --- /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 000000000..d169817d4 --- /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 000000000..36d527ec6 --- /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 000000000..12165e965 --- /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 000000000..f119e3fcc --- /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 000000000..debf9964f --- /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 000000000..3abcf5c30 --- /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 000000000..5f9f769f3 --- /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 000000000..512e156dc --- /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 000000000..8eb152b2c --- /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 000000000..db522afbb --- /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 000000000..da681ca12 --- /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 000000000..c79eb8002 --- /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 000000000..0fe38b79b --- /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 000000000..10c37b770 --- /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 000000000..eefe89544 --- /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 000000000..3cead54ee --- /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 000000000..15fa16243 --- /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 000000000..f74f1be6d --- /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 000000000..9739982b7 --- /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 000000000..f57407732 --- /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 000000000..c65aadf25 --- /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 000000000..71751a47a --- /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 000000000..dfc00435e --- /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 000000000..70ea0c006 --- /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 000000000..e8c881348 --- /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 000000000..2883fbacc --- /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 000000000..2bb18052c --- /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 000000000..ed0a8a33f --- /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 000000000..3754769c4 --- /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 000000000..7ec9e3eda --- /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 000000000..1e3f199ff --- /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 000000000..6a694b0ba --- /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 000000000..4df7cb1dd --- /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 000000000..4a75cfef9 --- /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"); + } + } + +} |