commit d44bc27a4b2ccd1c255b01fffd237ba8553314ad Author: fandd Date: Fri Sep 21 01:37:18 2018 +0800 init diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..551531f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,448 @@ +# Change Log + +## [v6.0.8](https://github.com/* remote origin + Fetch URL: https://github.com//tree/v6.0.8) (2017-07-18) +[Full Changelog](https://github.com/* remote origin + Fetch URL: https://github.com//compare/v6.0.7...v6.0.8) + +- 6.0.8 [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/b3e99476b768df3fb4da50ff3bca4aea6f863710) +- :bookmark: Bumping plugin version to 6.0.8 [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/7cf0c179ca40c8fefaec4016ac2d759ae728cd7a) +- :bug: Issue #364: UPC_A codes now scans with extra 0 at the start [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/f311beeb945f80ac8790391f8238bd57d9fa0cd9) +- Merge pull request #505 from renanbandeira/patch-1 [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/919a626daf6df124c79c792863b352ca0a87044d) +- Updates README.md with new saveHistory prop [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/e63ab0db5e278d9565b50ab1f5140dd75ecd1742) +- reverts 523501d [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/7b3c22aeb9cf0683937ae43cc30ccbff1dfbd83c) +- Gets saveHistory from preference defined in config [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/523501d8d7199928093c8dbebf67d9358476cc77) +- Adds saveHistory flag [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/132359c564750651a9b10a01caf4b8dc30862556) +- Updating CHANGELOG [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/20727f81f2add352433c0649a9e5e3e5093467ac) + +## [v6.0.7](https://github.com/* remote origin + Fetch URL: https://github.com//tree/v6.0.7) (2017-07-12) +[Full Changelog](https://github.com/* remote origin + Fetch URL: https://github.com//compare/v6.0.6...v6.0.7) + +- 6.0.7 [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/78dbf1cccb30935b832dc659eb377541edc52786) +- :bookmark: Bumping plugin version to 6.0.7 [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/d0a2b4c52169553a86fc3fb5e00c0caa489d097d) +- :wrench: update pluginpub version [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/fc7e3be16f3b1c811e5013f028bed934ebd7c9c1) +- :apple: Issue #238: ios callbacks not called [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/e33e64ef462d00a95a0c6f3258a087f61f0e15da) +- Merge pull request #431 from phonegap/ios-fix-426 [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/c65ba2f987838331eaa8a569b739515cad7a91e0) +- :apple: Issue #340: iOS WebThreadLock crash on barcodeScanFailed [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/217d673644b6df96b175ce78ffa9cd8aee24135b) +- Merge pull request #472 from jcesarmobile/beep-fix [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/8091c92f5e1e68e50f22fd171754a77740a76859) +- :memo: Issue #470: PDF417 vs PDF_417, which one is valid [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/7ed5b212d25f2c0918e7ac0353cc3d59d8094a4c) +- :fire: Removing these tests [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/54a28dd8871b81db810aed7df0a9909d71937b8b) +- :wrench: Issue #473: Travis fails [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/68a2c5d9064bf927df0c5a862009d5b9812785b7) +- :white_check_mark: Issue #473: Travis fails [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/2e335b82b7bd3ad9b7efc2c87adcb441c0d88bda) +- Issue #330: Add a LICENSE file [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/a2f59f7adba728006c40dec431ecedf1c229f6e6) +- :memo: Issue #471: README.md fix [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/cce5f050b8861dd05e6e8e0a03fc4b301ed3788f) +- Fix beep [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/3cf20a6eb3397f3a2bb61a044c02f1e4810b5810) +- Merge pull request #429 from jcesarmobile/pgb-usage-description [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/b5a135c6788e1a9ecb9f06a087931701f0b7a321) +- Camera cannot focus due to wrong aspect ratio since plugin 6.0.5 #392 [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/04e0b3dadfe9aad8ec90e1d9480efe149f7e64f1) +- [ios] re-add support for formats option [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/75ab7396d0e86b78188369d5f27a5c4fea602921) +- Document usage description for phonegap build [view commit](http://github.com/* remote origin + Fetch URL: https://github.com//commit/01a9f77961be74581fe25786c17e351026f1bbb5) + +# Change Log + +[6.0.5](https://github.com/phonegap/phonegap-plugin-barcodescanner/tree/6.0.5) (2016-12-22) +[Full Changelog](https://github.com/phonegap/phonegap-plugin-barcodescanner/compare/6.0.4...6.0.5) + +- Flashlight default value #385, Turning off found plain text #259, Remove Result Prompt #234, Custom Result Messages #219 [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fee66a7d1b4c3bca845beb3fa8c99365b4c15ce2) +- Flipping orientation on Android crashes app [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/72ae2c75d3d66df24c124a6da9c26e48f7ad36a0) +- Focus improvements [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/52a23b0f42d454d6a9f2e29a693b5e984c0bb13f) +- Crash on iOS on low memory devices [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6e3718c2db03fda3d8ea439a9471b3a08e121f21) +- Disable Animation [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f9960f9b81aef35bd85ecba856c63058bc109ac1) +- Flashlight option [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a7ed6890d4e5e2cb386c8754aca081fad559ba1a) +- Merge pull request #343 from cepm-nate/master [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/77622ca92f5607a8d22131f62f2dea720857a5ed) +- Merge pull request #334 from lucatorella/patch-1 [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/10f94bc81aff5329291272a4922837e04569a339) +- Merge pull request #346 from kunder-lab/master [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1cdbf871c9d290630e4535e8ed9db0804b413f74) +- Catch Class not registered exception in case of missing Media Player [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d43964f06c8eb57fc168d7b19027462e957ba23d) +- Adds promise scan .done particularly to handle "No cameras" error [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/68b6fd14a95f34b32ea2bb651f9715ff880e4ade) +- Merge pull request #358 from vladimir-kotikov/explicit_intent [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/75cffc3282f09f6973d078d8ce9b306bff210bd5) +- Use explicit intent to launch scan activity [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4c046898543dee838b259997a5ec360240e26354) +- Merge pull request #338 from jlowe234/master [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7f4e4daf19951692873a490c845446cfa0fbda68) +- 6.0.2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/18f958796ee9587d5bc21e6229f40139dd4f0c8a) +- Bumping plugin version to 6.0.2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8728015c06d6d201cbd421621384cd19857f6720) +- Update pluginpub [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ca4973214b3f99a135d3844d52f40a086022ddcb) +- Merge pull request #303 from vladimir-kotikov/memory_consumption_fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/631ab8fabe16266fb8ea6168d96250be11b8efd1) +- Merge pull request #318 from vladimir-kotikov/surface3_crash [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4fffc8d187ddd7ee8df90ba285a5ae6eaac980fe) +- Add contribution doc, issue and pull request templates [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/31d9badd9b9b3278a78650bcccd105a95a7b4c78) +- Add editorconfig [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c33c2ab4d63f476bc63c3dd8a5b18f0301baf30f) +- Setup CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1c2491db0f3e15322e543e87def64159cc4b3bb9) +- Setup regression tests [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4d6ee25e8f1ca3b2589c979a23f987afa60bb701) +- Issue #270: OS 10 requires Camera permission reason [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/380a56a0b5236bf867bd11d10ceaa185351ea892) +- Merge pull request #302 from jcesarmobile/add-permission-check [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7dd0e8404394b1bcb14fef49cf0301f5b32503c4) +- Merge pull request #271 from EddyVerbruggen/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8004584a8f266fc4715ffc69fb7148a0a83724ae) +- Merge pull request #307 from timkim/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d775cc7995c4ef6935c127a02d2d8164243bb795) +- Avoid crash on Surface3 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1473daa0a8d2a4c9a0a7b5330be771acaf5a295a) +- Merge pull request #314 from ben-8409/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2af63247c8f379bedbfb323734995b7420005367) +- only set cdvMinSdkVersion if not set or smaller then 15. Fixes #275 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5513f5c99d9363582e5e77a77b0b6fd3ac8f85c9) +- Merge pull request #183 from stigok/readme-update [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/97a29911c49ad7aa4406ae99a9b74219212ee608) +- Require camera [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5e58c0a1b8dabb301836440d6765f2423b3a9482) +- [#277] - fix for crash on iOS switching cameras [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6c3d74dcbde681a464ba0abc29c5a3d084b09739) +- Crash fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7841f6deba953121bc6d74bbf60d3380a466d73f) +- Reduce memory consumption by using smaller video resolution [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/89a9c69f6d2ba2d0e3d5ae25d937d3772c48b67c) +- iOS: Added permission ckeck and fail if it's not permited [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/59301afe045509f53d44c2f17bc7cd9927c357c1) +- Updated version to 6.0.1 for release [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3cf975bda01cdddd71b03d74ce31c97595ae98af) +- Merge pull request #285 from daserge/visibilitychange [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9d4a96123030f71f2f85676c61a4bfb8b3846592) +- [Windows] Handled visibilitychange to avoid camera freeze on minimize [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/005c30309d3c0b371c5fc4ceceb2ab8f7f2ffb40) +- Merge pull request #284 from daserge/version-bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/11dd6b5ad2d3528df57a63f3b6ff093452e3bfb9) +- Updated version to 6.0.0 for release [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0f534db7e2dcee9348a2e707c7f47ebd0df48b8c) +- https://github.com/phonegap/phonegap-plugin-barcodescanner/issues/270 iOS 10 requires Camera permission reason [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2895b3b85506dd7dd91c93a741e1cc13acc59f09) +- Merge pull request #263 from daserge/check-arch [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/dd85e2530d9638ecac2774c2a00a7b9ec2a573b3) +- Adds a windows pre compile/run hook to ensure an arch is specified [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/49e33a85a08cfe0b1c5559d24d7f6f42a60334b5) +- Merge pull request #269 from daserge/win8-deprecation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/865e1b678fd93b1f712084d65140f41f6ebc4a29) +- Merge pull request #256 from daserge/cleanup-on-events [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d3344f2d0a0666357a2e9bc4230902227cdd039d) +- Retargeted WinRTBarcodeReader component, deprecated windows8 platform support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/eba7eb3a4cc9f558feed571ed589134fd3a7cfa4) +- Merge pull request #170 from jcesarmobile/callback-with-blocks [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ae9f6e2a2e14aa0b16d86c039ea50ae1183f7bbe) +- send callbacks on dismissViewControllerAnimated completion [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/21152cf42978623ae6c67488124fb6474342f9bc) +- Merge pull request #266 from daserge/multiple-focus-3 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d92af72bd1ce76eb2f40b6fbb0a32292b4fa8817) +- Merge pull request #267 from daserge/multiple-scan [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/78a53459d3c0b9abd6fa510571a422e279dfadde) +- [Windows] Focus fails on multiple taps [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f18ed1a78c3b720ee88497b84734bcd77699ea2d) +- Prevent multiple calls to scanner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2aa5bdcda508bd4164326298da18638f955e0873) +- [Windows] Cleanup camera on app suspension Save/restore scanning state on suspend/resume [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/49489db0678e6e80a3b0744533d432681b9cfdb7) +- Merge pull request #260 from Telerik-Verified-Plugins/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/55e693843e3a556ee9ba9f2dab13fd9ca652396f) +- Stable plugin id [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/363335c13b96f7f2c5a728d99a8be137b6601e34) +- Stable plugin id - revert after PR [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/be3e490b95b99078740f473466b60cb0c7348796) +- Stable plugin id for PR [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/73c32f4e62467694ecf725e5d9d307d3ed94a3e1) +- Merge remote-tracking branch 'upstream/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c0546f71e60991ff2dcbbde2d1e23443db5d19a7) +- https://github.com/phonegap/phonegap-plugin-barcodescanner/issues/40 https://github.com/phonegap/phonegap-plugin-barcodescanner/pull/171 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e9f1b1bfe18edfae2db087f91c9112b82909bd83) +- Scanning crashes on Windows phone on device rotation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c3bcd87e1c66dc0fca7c04a2bbbd405ea9fbed2f) +- Merge pull request #257 from daserge/multiple-focus-2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/45ec98fb46e4f5d18bbc5fb4d6627065cccac248) +- Added missing CHECK_PLAYING_TIMEOUT Added a timeout before initial focus to prevent focusAsync hang on slow devices [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/eb31d2e3416f64bb3312ed639f2fa046b4551414) +- Merge pull request #250 from daserge/multipleFocus [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e65272ad4536bc49200d4ca8b23cd970d7a118db) +- [Windows] Focus fails on multiple taps, this closes #249 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b836297ed5139d495bd0f0b4aeabaaa9734e4154) +- Merge pull request #251 from daserge/close-button [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/128c80f63ae2aa490adbe0c27250598fdabdd722) +- Merge pull request #253 from daserge/win10-CameraStreamState [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5161af4c7f92d7b0edc71230f6b43127502e3568) +- Windows Mobile 10 - Close button does not work, this fixes #196 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/942d1ed199ec0ea7488bcf3d8ec0a9d6b711ec82) +- [Windows10] Fix The request is invalid in the current state [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2a3e4fd532fba820979046b85e573529742f3b62) +- Merge pull request #252 from daserge/css-fixes [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a3d4dfa18adeeb6ecb62a40ac0492d9825372458) +- [Windows] CSS fixes - no-select, no-zoom, no-scroll [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5364553b1e00d4515dfc5293f4baae3629d8c48b) +- Added a note about PGB [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b20c04648b4cfcd1170e098c257e535cd6762f72) +- Merge remote-tracking branch 'upstream/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ce0cf94603c526a261cb80654be19652eae9d239) +- Merge remote-tracking branch 'upstream/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d4b22bb0094fc216a7837f61ddfabb91b4f3450d) +- #221 updated version to 5.0.0 for release [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/27227e9d2b00174e816869bc6123071d470ade87) +- stable plugin id [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/762dea0958937ee2cc1b76831312733bb59a401f) +- Merge pull request #217 from Telerik-Verified-Plugins/merge-phonegap-official [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/bd6c295908a22a23d1a473f39db39956e6bc62bf) +- Bump plugin version to 4.2.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0cda49bfe1229977d6bec855942c199d5357c7ee) +- Fix iOS issues after merge [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/06f4a7d04bec902ffa2109b79602f3955175a17a) +- Fixing Android after merge [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5641c8ea17d036f806fd2f15763ce16cc79ada3c) +- Re-added old platform files we removed after forking Wildabeast [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/172f164b68d620699ac14bcf6468a21a65a57ada) +- Merge remote-tracking branch 'upstream/master' into merge-phonegap-official [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6a7d7208b15000e004b894184860cc0f298b6e32) +- fix Android M permission [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/29d3308b7d46a94fbda10945d3ecb78a7d6d1c08) +- merge [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f0ad027425313f3edbfb9350ab81068ed4898894) +- #28 Plugin renaming my app [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/55b716ad8e6dd4bfad1921d2efa00eec45fd414b) +- #28 Plugin renaming my app [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1778bee6b028081ff4761c32748eca0c939b4368) +- #10 Warnings on IOS 8.4 when using library [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/57babcc2beb1f6f2d45b738b126e4588b1b1643e) +- #26 App crashes if the CordovaActivity is stopped during scanning - Moved `scan` to a background thread so it won't block the UI for about 50ms while initiating the scanner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d0bf407951f13759484a8fd2a77e6c3d1fb8ecc1) +- Documented the new "orientation" feature for Android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8dea274bb72d01039173c305cc4a276a9985a5c2) +- This fixes a few issues in our fork: Image upside down on tablet #20 Android UI doesn't support Portrait and is small #4 Prebuilt Zebra Crossing (xzing) Library #3 Forcing landscape on camera android #17 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/25e00cd9e2d3a6789663ef9c0b9210f5ebf6776b) +- Merge pull request #206 from sarangan12/Windows10Fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2a5e289085e8a9a11b4863d7ddbdfcea58b22510) +- Fix for the crash in Windows 10 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8e46fcb76d49c76f4598be195e489cd81fc29217) +- #25 iOS app scans randomly UPC and other EAN formats when scanning EAN-13 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/dde3c197026412811e719e016d2adad14330ad78) +- #14 Cannot read code_128 barcodes in iOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c0673038124e623e2c6f6558b87f75dd611d3171) +- Update README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b8ea34e5ac4b4e7b34b991e4e1065ef8619f776b) +- Fixes Windows Mobile - Issue with Orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/383406708e265ef4eddea28a3c07163fc4787519) +- Merge pull request #168 from MSOpenTech/escape_fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d1dcfe0763cfdb24d0fc1f5c5811dcd05bfa74d8) +- Fix plugin installation failure in VS2015 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4c0dcf4b27e9c6c4851f0b642a9436ab1c85bde9) +- Merge pull request #135 from MSOpenTech/windows_refactor [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e22581cb56e9c6a147860ee6e6f4ce4991186493) +- Refactor windows implementation in promise manner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0d01bde3a6ce1e499099d051d3fb54111537cf9c) +- Merge pull request #134 from MSOpenTech/orientation_change [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/02c67a20d9f6c59388a1be8f71fa568358f984b2) +- Add support for orientation change from #62 and #97 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/51216ff3dd0375a694eb4f9352bb78046ae47505) +- Resolve merge conflicts and address feedback for #62 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cabb67e6425e23366ebed47b58ddbcd93c6925ee) +- fixing issues for windows platform [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d68cdce6f920c3db0bf7a1345f60a6fdabedde95) +- Merge pull request #132 from MSOpenTech/windows_barcode_format_fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8b5739fc692ab30e807feb7530d618ec7ba7ac8e) +- Correct scan result to expose format name instead of format code. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/dc84cac7844d3fdf64d3bfbdf0765930bc0a6b9e) +- Add information about windows 10 support to README [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b25d71061693f716658f0769c9be789b58b2b65e) +- Removes intermediate winmd component from Win10 implementation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/521d427ed418d2288a1b31a11398b99f54fb1f5d) +- Add Windows 10 Support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9c2da016e4ddbd973a596568c750b7bb48ea4409) +- Merge pull request #131 from MSOpenTech/backbutton-fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9dec84ced0050f7f7221bb49d0fad4f39ccb819b) +- Improve native look and feel for windows platform [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/23b4343483104b21ce501f481e0001827f7f994b) +- Merge pull request #128 from MSOpenTech/autofocus-fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4606ac6d2465e83742d436cf351902f2f09854b7) +- Rework autofocus logic for windows. This fixes #41 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a905251130a5a956d28ed849bef69a3d6df6dee9) +- Merge pull request #127 from timwindsor/barcodeEncodeBB [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f4d5d5c638085169c10d54dde887b6203332a6ec) +- Merge branch 'master' into barcodeEncodeBB [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d9f47951442cefe939a61d1f9c5ee72316d82863) +- comments [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2219f194a6c4b5d87a1fb7d5bec2e60b91f41c07) +- added data type check, and uri prepending for encode method [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1cf63768bf5b3e991b2b62d9f34f1f1283f92ef8) +- error checking, data validation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d5e84c9f09480a0f5f2782e206c61b0cf92c8c37) +- qrcode encode working [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2830a6d85c8be6f07aa503931c702e5f7444c879) +- encode method or blackberry [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c662c85c9db8b43bc259e966a40203b74b8552f5) +- Use maven reference to android-support-v4 library [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fb0a4f80092ab173366c98c6a1555bbed0ad864f) +- bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/df1210276412c72d428d13d382141a200e811986) +- fixes #162 button bar not working in ios8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1f51bb9561c92be3abf676dd56b82c86f207b204) +- #15 Android M (6) compatibility [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/82bd97ef65b4b609a8d7a8be5a8068a5961b7cac) +- #15 Android M (6) compatibility [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f028ec469a60031e31033fc2d44fd69358d95be0) +- 4.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6b5f7fb7626f24b45fb643dcdd841e3fa0e5361f) +- updated to version 4.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6452c9802f0e0a4b686e5b94f043cc23d2380acd) +- Ignore linting [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/64845f4cf4726f1b50610463daa703b7a3a7f649) +- Removing custom strings [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/607efeb158f12e651e8555eec9abdd8d9480010a) +- Merge pull request #78 from timwindsor/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/940e98babdcc27e8dea6120a42412a3b8161e9ca) +- Merge remote-tracking branch 'phonegap/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/28174b118447b86bdf4acebbc24913775db3fc7c) +- revert obsolete workaround. Fixes delayed error. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b8f2fa5c4efcc72732ebadb8bb304cc46465e93e) +- Parses result so it's consistent with other platforms. Removes obsolete, unused file. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0632e345a63b22e4a52b250cac427f9649ab9858) +- #13 Cordova-iOS 4 support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/de5700cc233cc845453bb98356e7b2cce67b6d92) +- #11 PDF417 support on Android. Version bump. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/009175b0ac39f8eea71c928708af97226a636d44) +- #11 PDF417 support on Android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e413345fa765c61d46c8c5437eb08d754b9c4dd1) +- updated version in plugin.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/74f33d5d14107915c357753684e9276eb37a3f66) +- 4.0.2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/07322cb29310ad1f5b19f43472de8b86c558d19f) +- Merge pull request #66 from olimortimer/patch-1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/346472ff22b94f94cef25dea9f6f7eb851974c43) +- Merge pull request #52 from nlsdg/patch-1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/001a1be747183e5b727d367236ae477dc9b49613) +- Fixed iPhone / iPod scanning issue [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c92bc8ac49e72a064093e83da4597aba2e68dab7) +- Add BlackBerry namespace [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7175796244403b9b3de42ac5c1df2ca576606678) +- Update README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/49571fbb7b79742481c230daa7b146cc7b2d9e7c) +- 4.0.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f72bc48f7508c84a52a2cbe9e31c31408063def9) +- #48 fixed version in plugin.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7b7c4c6d8751005a0ac762d29f179244dbe68866) +- 4.0.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b005d77852b22073c1b618ddec0d713453f5b69a) +- Merge pull request #32 from timwindsor/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7bbc73c82eb3dfb41c285103771d11451a1ae666) +- Adds blackberry10 to package.json [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0ecd01e1104b4a89efee38ec598f89a6a1b51cd8) +- Merge pull request #1 from timwindsor/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/30196b3dfc2ef0f36c30253f6765cfbde283127b) +- Completes merge of BB10 implementation into phonegap API [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/52b5adb8d40e6116c20df2416cf1a78ec24f4b7e) +- Unifying API for BlackBerry10 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/02c5ba86d5752df841359ba42df32db0b74ff10b) +- Restore location of BlackBerry repo [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8cf9df1c65d047d61b3dc6a59c30f1dbda4f7f54) +- Restore location of iOS and Android repositories [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d801b7687dcb7b02ce7114e166d0cddf82adf12f) +- Merge in BlackBerry 10 support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6043674b179295489936ba81b8fd5ff1ff2fdfa8) +- indentation fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cce09e379351065a303ad9af93dd463fc049da53) +- stopRead error handling [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/66e572e3eb3f0febfa52b5ac2b334bfde11f2557) +- Merges in BlackBerry 10 support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7b320e1dfe3216937dc0bb77a4ba65d790169bf9) +- Android 'encode' crashes [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1feb36d34313077c2dd145c59d9009088542d347) +- bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c484e0a754d67e2136ade27b9a3e4a4d115253e6) +- Android 'encode' crashes [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3632edc0cd0aa85b6a04d3f6671005a6215f6a82) +- Ugh, AB build errors because of lint config [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/31a7ebfcc2159e5c5075668bba508e67bd00db30) +- Ugh, AB build errors because of lint config [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c5cf295c7207ea3433f21b7319f1e29d538911a2) +- V3.1.2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/70ca00be45a675b1b1d6963ad6f72430e579788e) +- Merge pull request #7 from mlaponder/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3d96f565e450f50fe0d36fb6d119c4e0d0268147) +- Update version to 3.1.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/405c00b616a41dd6041c5daf359795dd7e4831a4) +- 3.1.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b58323f54c72c0e93089d1e1fb81592a708309b4) +- Merge pull request #6 from mlaponder/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9d12d19f9af5ae9379b8c11b658079e234b39d9d) +- Fix incorrect uri for wp8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5f1fb8865264576b8be8b6bdce7a4e34d40ee8ce) +- 3.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/78cc3fbcdf6f21e35614578409494d767193786b) +- updated to version 3.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4647c48c2ee683437f36589a3ad27868698840e7) +- Merge pull request #4 from komola/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/41c6e8c475b5028883478f22ed6694502e1b6b9d) +- fixed issue with readme [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5fbee99fc7bf561f99f7fcbb90ad8b41669797a3) +- added travis-ci support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/616a2700f60e3789505737330bc6446acc42c7c9) +- fixed tests, made compatible with cordova-test-framework and paramedic [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/652d50967a8754a623e3a9de04b8b9565b4aa06d) +- Merge pull request #5 from stevengill/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b17891c002a04dc31c24e66ca5a50f31254d0e98) +- updated ID to phonegap-plugin-barcodescanner, V3.0.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/50d3f0a23bb1313d128c00d9634f8ef6f4d7cc3d) +- removed cordova.define from js [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/729f2caddd96041dc671188cae95648927fcb860) +- Merge pull request #1 from trongrg/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/262ef2b03b906043c05ca4f2283300eaa0fdff8c) +- Updated src/android/com.google.zxing.client.android.captureactivity.jar [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fa13720cf7cf664f6cc7a6d5721038d4f0e92ad1) +- Remove unnecessary retain calls [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5fce7a4d78c767e2e32e1d6173743c138e230406) +- [#4] Android UI doesn't support Portrait and is small - support for tablets with default landscape orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/408adbf364c4336901d017d5176d27721271a439) +- [#4] Android UI doesn't support Portrait and is small - support for tablets with default landscape orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f412fbc0db37cba9d96df3b6502715150794a70d) +- [#4] Android UI doesn't support Portrait and is small - support for 320x240 screens [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6c120b984c2adb86cfd8c2cddc55cf2719e17731) +- [#4] Android UI doesn't support Portrait and is small - portrait scanning of non-QR codes didn't work [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e197d222cd6b6c879eb0fed79316ee960674736f) +- [#4] Android UI doesn't support Portrait and is small - support Android projects which have not set targetSDK (crashed without it) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f74da676341aaa9a9cfbcb23440408e35449fbd2) +- [#4] Android UI doesn't support Portrait and is small [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a250540bec7b179820af584f3b714cc7920b1eda) +- Restore MultiFormat Reader [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/bd459f4b9c5aea7e7d20b7e7aaf7d61847ab48bb) +- Merge pull request #1 from MSOpenTech/2.1-windows [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4e5af0ca1b782fe4c54f9f849495d5678edc95b8) +- Include winmd source as subproject instead of prebuilt winmd [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/21083d4974e471e9233f66ed8b84f53df74b6eea) +- Merge pull request #2 from MSOpenTech/2.0-wp8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/47aa58873097ad763c932c2fa2d7e0e0aa442ae5) +- Check if the last n scans returned the same result and only then accept the code [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1d264dae30895a3edb07938c95c9902ef0ad69c3) +- windows: fixes "class not registered" error [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/96284b34430dd8824c517a24eef8fd23046b6de2) +- #616 Use single proxy for both windows8 and windows [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/eabae9e10be2e21f8c5f917748bd769c9fe11b43) +- #616 Adds support for windows platform [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/aa80367059e1a6c68a0947d56a7f6d63e896177b) +- Windows Phone 8.0 improvements and bugfixes: [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d0b2b27a77e02af5afec0cfd6c3566d1a3f65d62) +- v2.2.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c74e37a40cbf5ecbec5be8f6677e3bf01f0920bf) +- added support for adding config parameter which is passed to barcode scanner activity [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7773e4dae0afbe85ee50e3681df9ffbe7611a04e) +- Restrict to EAN13 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f70288d7b27cbe96d134db68c5bf517f85ce8e92) +- v2.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7b3302282215b4d41e1168cbef8af9a3abf122a6) +- Played beep sound after scan succeeded. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b1bb4fa2fad9d27bf5d25b8aa2f7872c92ffcf2b) +- iOS update encode method return format [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f04a2a0e4c8bc9c09d76a725ee771423e042837e) +- Add QR code encoder implementation for IOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8b10b8ae33fb672018fa9230079d8c6f096c4b13) +- fixes #162 button bar not working in ios8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a1f216d4413596ca18251c3fe543f862acf972a5) +- fixed size to int conversion and cordova 3.6 deprecation warnings for iOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c2dcd871d25b480dfaf65b2eab878bc5a4775746) +- Removed ARC code [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/22a23b171a89322709bb1020fbdc02e90a079c21) +- Version bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/30236cda293f6e4de564e3adfc7fb847e1dbc0ba) +- Merge pull request #9 from galexandrov/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/35ad6da69b10f8107ad90491b4afb25ca9f5d971) +- Remove unnecessary retain calls [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a44f7403649e7727b2b65a72585e631d703386e1) +- up version to 2.0.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fb600c1710ff2f786a1c3a31cd135d69846817fe) +- [#4] Android UI doesn't support Portrait and is small - support for tablets with default landscape orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/044de265661e17abb0aefcdf8230d9e357b6cfc0) +- [#4] Android UI doesn't support Portrait and is small - support for tablets with default landscape orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d0aa7d75ee35fc951d66b3b094deba00ef17db97) +- [#4] Android UI doesn't support Portrait and is small - support for 320x240 screens [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7e60c7c1e830113b34673784ce0764ae450e7dfd) +- Support browser. encode is NOT ready yet. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/116a3bb4e797b75292867900b626b8f2bae10fb9) +- [#4] Android UI doesn't support Portrait and is small - portrait scanning of non-QR codes didn't work [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fe7746456defcb7f6d16ce4b023712c515bdb748) +- [#4] Android UI doesn't support Portrait and is small - support Android projects which have not set targetSDK (crashed without it) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/20799f14ade1e2a1399428377fdea2f608c84b49) +- [#4] Android UI doesn't support Portrait and is small [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b163ab694f1e49ae1667a2e4635f43a1bd6de74d) +- Documented new features [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8b9d6a5835b5c1a7f487b9ba38a5cb4e4d323dd9) +- Merge pull request #2 from EddyVerbruggen/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5f37fb12c6081809aa237b7896a5e7b26b32eeca) +- Added option to select choose to show a 'flip camera' button (default: false) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9f194201327ed4cbe0eee21f67ed38496e2a5003) +- Added option to select frontcamera via JS api [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/80a828516c1512964a85e0f2fdd44e09d206e418) +- added repo + issue tags [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5268a02fd7f6c96aa2c2bc022ab777e89ae6cc23) +- Upped version to 2.0.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c3090dcf5347c1cc10caaeff225bb2c0a0deeede) +- [readme] fix encode example code [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3a0978076fab0c5180d4c2989a4a3844a980fbe2) +- Enabled ITF support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/740aa3a33b55c5d51ae07dbb8bf40620bdd7b7b6) +- Added support for front face camera. Signed-off-by: Emil Marashliev [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a209c6d396a53c6304582f89f59300066ad56149) +- Updated link to Cordova plugin spec to fix 404 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5a7aa5c29d98679513209247e5c65559cd2e275d) +- Updated README links to the original iOS and Android repos to fix 404 errors [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a8c2a2609399cee2799c873863257b9ce870ac80) +- avoid calling other apps activity [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/84af3e9f72bd12f172853f6c091b08eb556572cf) +- [plugin.xml] updated description [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f766ba2536b93cae56875060bf25af55cf80c178) +- [plugin-xml] upped version to 1.2.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/552974245e156960bc48b991520f82d696d125b5) +- Adds documentation for Windows Phone 8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/602dad12e506ec0f8601d144d1fde716d021814f) +- Adds support for Windows phone 8.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b94b4f67c417d431094da193f2a40da7876b498b) +- Adds documentation for Windows8. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/74f78db8ac7fb6b5aec25584a5a9518286a1de9d) +- Adds Windows8 implementation (scan method only) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3a7d7610ab8b2c0c94feecbaff854c564018ba9d) +- [1.1.0] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2a2fc654bcc2a68598d04d417a84c5a64fe3fb24) +- [js] plugin.xml asset backwards compat [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a6ed222163792190ce5b4b684b6ad746bfd7662d) +- Compiled jar [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c93d7569c4fb88baa8a2546e5c278249f7961887) +- Added a flip-camera button for Android - missing icon [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/332f12fe9c79a7a8210914f747ce8353368c1266) +- Added a flip-camera button for Android - missing icon [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/48be871057bac642724de63c1c3707c99f9976ab) +- Added a flip-camera button for Android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1a2b8c6126f9d61ff229bbee2f9f8109a78e806d) +- Front camera scanning for iOS ([#108]) deserves a version bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/98f158aa4dde990c6d2bc89ff418039c77b6e15c) +- Added support for front face camera. Signed-off-by: Emil Marashliev [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d3c8ad2df92743bc8fd038ec37d89e0bce2053f9) +- avoid calling other apps activity [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ef1155d09d53856b4d8dfd6326c734e05e702885) +- [plugin.xml] updated description [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cfa698d93773fa7d737fc1adf02d6a2e46538d09) +- Change plugin.xml to use framework element [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/619f6984c3db640c14fa2505d06b659913018137) +- Change barcode scanner to work similar to the iOS and Android versions. In plugin.xml added reference to ZXing.Net so it is refered as plugin is installed. Similar to other platforms' versions, there is a focus area - only this area is scanned for barcodes. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3a377ef883d0e5db138ed40f5e5f6838d1407f3a) +- removed unused reference [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/05a5a17eceed4e377faa9674b2f3564ca37b422e) +- [1.2.0] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/53ad095e86434adc7694b8a26bdf16d6c381238d) +- ignore Intellij module files [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1654970ac5b5b89c4e5008d71f93a755df71add0) +- Updated Plugin, refactored some library parts, added description to read me [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/719f19d3f003a19313d29f81c8d668030980db7e) +- added windows phone version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/039d1d0ea45d75902c748ba9f7f115a9b94887c7) +- window.plugins is not defined anymore, replaced it with cordova.plugins [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7d831d83ed3967ce438551bed1b8a86ec2f7fb84) +- Add missing iOS framework "QuartzCore" to plugin.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ec4de624ae9f68a59557f21a1a5a4e18d3cfa425) +- [plugin.xml] corrected supported cordova versions [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/24acf29896fa39578238a0269c9b1a3d643c6a3b) +- delete plugin.xml.generate.php [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a310fda2d7d55e650a65b9d0327eff87356c0818) +- Use in favour of for the JS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8bf3cce0737f7435b979b55433c87657dab792a1) +- [readme] fixed encode syntax typo [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2d8701634f4d761f3c3cc961d8eb337b44de79e5) +- [android][0.7.2] remove busted menu items + fixes #11 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7880bf7b5c4a619acaff8e8b905e0710eb3f41b5) +- [0.7.1] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/12a31b76b015d3218874437a37d9a78fe710b161) +- [README] fix typo [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a2857ba5f8ed2a4ef7277fae8dc108239a2f15ee) +- Merge branch 'ios_warnings' of https://github.com/agrieve/BarcodeScanner into agrive-ios_warnings [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f046f651ceb06e35a6867e3e3df0cbb2c58a0f13) +- Use in favour of for the JS. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6ad6dafc1169d62871663d013d49312df64acb2b) +- Fix plugin for iOS on Cordova 3.0 by disabling ARC and using newer plugin signature. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/14d63e35ac9d1333f178cb3ae95a88b530d73538) +- Fix some compile warnings on iOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d901977064078efec335f3309c30bc8038372447) +- [0.7.0] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7094cc6eda5ef8a225c550e463bc49907c36ac40) +- Cordova 2.8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fc3dcd56d1558415043aaa538c724426b6caa726) +- minor [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/50a2f8bf5236e643635caf8cabba5e0d2df8ba69) +- Merge remote-tracking branch 'upstream/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8966e5207fdf506f5c94a9dee9f9e25b847aa5c7) +- ident [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8fa142ca9d1d400ca91d651865b6eb5d9f79d204) +- Encode object access fix. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6fd905a8e60a0341fc4a4453f594222eb7cd0b8d) +- 3.0 fixed README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/32880fc1fa78dd0911a66c86895303d7479a2be5) +- typo [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/903b02f142534057cb02d79772d874c37fdbd553) +- Fix for https://issues.apache.org/jira/browse/CB-4379 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6fdac151eb089043c6147e6822e46ebea4604375) +- Changes for crodova 3.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c84bf0e66d0ac14b44283261a2a3c9813e4750db) +- PG 3.0 changes [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e728d331554837a3c905e569a579f290125d4717) +- [readme] correct ios supported formats [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1242c551424e31270035929c024b4d7de55ae9ef) +- [readme] plugman not pluginstall [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3b1ad506b2a4e387405f62263ec3b5dd550775bc) +- [0.6.0] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fab895ab3002da39e3fdaf0f11eee2a3f8ad4e9d) +- app_name fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c5c60c88568b78898bd08a042b5e0087053cc9b1) +- Update README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5b01acb999fcc9f5316212a8887fcd29ebbf78a5) +- minor refactoring ;-) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/db30964d5113d4ac4a63fe8997165d07e7bb9e20) +- plugin spec. update [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6e29489982aae3f761195647b18c8c1ccd2ff850) +- Update to 4.3.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8c50a121e87425ffcf4c09f7c4a08669c7bb7a71) +- [plugin.xml] update license tag [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e2cef45cb8b2a85f6979eee17dc96a6ec55d01e5) +- [plugin.xml] license tag [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c24882311fc880f4881dc02bcb14f9816d1808cc) +- Merge branch 'master' of https://github.com/Eccenux/BarcodeScanner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5833a1fa9e5adcd1f823e86b76a28800af1980ae) +- app_name fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9ed602fdacd4da7e8b083946089a4d04b51a46fd) +- Update README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/06b05fc6c98fae2b7c45502d6bd1ee315a339265) +- minor refactoring ;-) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2f86c728e5953a35efe236e293a0eca48353be2a) +- plugin spec. update [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/01a74e4c6c198750dc9149c8e90bd363dc0670ff) +- [0.5.4] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/18f2f7a9fe67ac42a1deafb11992050009df2ea2) +- Update to 4.3.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cf2be813cb3fb28b61fd2fedf4803ed70d2d5c16) +- Merge branch 'master' of github.com:wildabeast/BarcodeScanner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/10d66a4e67221957a8c5b02e7cd05b25539c4970) +- [readme] reference plugman not pluginstall [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/27d6d653fc51e6cb2eca1a7e610934d7f0a140a4) +- [plugin-xml] added engines [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4efcc86a24144c40fd60e372f0a4a6d02ce8578a) +- [plugin-xml] Add description [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4d38047b41fe4bed48b63249c1ce12b85f252089) +- [readme] reference plugman not pluginstall [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/af21cd20f6c14bbd803e83f904573c9af9de225d) +- [plugin-xml] added engines [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e38147f27f661137240b6ff673a08ca6e10c9c6d) +- [0.5.3] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b45ce29fec8f2c062661670a5651684234545b12) +- [spec] update specs to cordova.require/define [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/77d4a3dda27a10ec956c1e9e5f3281c76c54a25a) +- [plugman] plugman don't like spec/config.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6f4e09be4f2e0fe17a3372bec5cb2309372395d7) +- [plugin-xml] Add description [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b0747cadcef11fd1fd90fd94d0ffc8729e8256d3) +- [0.5.3] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3332885acd3072085dbbee8bc6389d83ff18dfcb) +- [spec] update specs to cordova.require/define [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2331218b5a597d1c5888e66461a2d4bd7358a8ae) +- [plugman] plugman don't like spec/config.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7ec3d477c208d7476eede4959f8675c6be1cc5f3) +- [js] cordova.require instead of PhoneGap.require [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3ab188539c8529d4fa79497abb84f509d1411318) +- [readme] formatting [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d9f9f2dc9bf5ede06df8b5d9f407456b8c938582) +- [js] cordova.require instead of PhoneGap.require [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ea1586b0ffbf9a6774bcedab1f988c4f3d8c7fcf) +- [readme] formatting [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/10f8e6b1164da3e108f3e8e52ca8953e7980c0c4) +- [spec] FIXED IT [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6cf71f0a3ea1bbfa06806ba1d447a96321eec02f) +- [spec] 2.5.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6d95b33987c1ee5d903ee51dd1ea496d8d786ae5) +- [spec] removing a maybe bunk spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ec5e1dc843cf6f9c4090d597efc03a33a50373b0) +- [spec] removing filsystem init [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/507c726215846a56c30cb85d309588166ab95ab9) +- [spec] more specs [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fceafa235a14a3f4d783c02e9529a1f96ecd64c3) +- [spec] formatting for medic [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/666387e132148cf332d5dd7cb3e379a735bca23d) +- [spec] app id [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/eb557c48279ebcc5147e474e73c4f374c1b9ec63) +- [spec] Fixed spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/33b2e914a4420024fde9cb2206ac2f9e32bf7931) +- [spec] app id, title [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/657ec4512268e56d5478bcc93c8a018da026dd32) +- [spec] fixing spec app [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/52ce70de60d6ad83b05e9639777cf8fa1f9126cd) +- [spec] add barcodescanner.js [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ab95b1342d0ccabcd006f5691c39875c54c68c19) +- [spec] Initial version of spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7e7c39dda69bd64359a8963b3cb5aa679b6047c9) +- Do not copy the scanned barcode to the clipboard. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5c46e8d93f0b711963e88248f71a7be6babe6b75) +- readme fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3bc65ebbaa3f0e7f96948b7a3484b9e4e9b3ea7b) +- Update for Cordova/PhoneGap 2.0 plugins (http://simonmacdonald.blogspot.ca/2012/08/so-you-wanna-write-phonegap-200-android.html) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5d6f0d52f9e495aa34f9d6fec9c77743b2ea6c9a) +- fix for a java ref [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f26cde76f54f3377d2e385c9fa97ebc65886d50c) +- full paths for android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5d452348dabed181cb3a8b970d94c9deead44be3) +- fully qualified paths [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4d8646e26d9ac7008b6b1ba75c24de40960b6ef8) +- Merge pull request #3 from filmaj/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b1f643f6f48c0dd7909c1e45da3807b35b2769f5) +- fix for a java ref [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9c533da17ed0554394fee2aa98f79b4caf56a574) +- full paths for android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f568cc6d3e63837ecaa057b666d1913cad2b0e43) +- fully qualified paths [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/215e077510b26981007500af27e503cc3f6211ae) +- [spec] FIXED IT [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cc0f7d82a1723616033be2b25ad554fc614b1fe6) +- [spec] 2.5.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f94c6129ae6c336660a240458b3371a1c501dfa9) +- [spec] removing a maybe bunk spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4579d40dc05964521f1e97026810d439e8e7be58) +- [spec] removing filsystem init [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/40849d52d645ac5bda784ce44de2b18bb1cfac61) +- [spec] more specs [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2f7d652587b234362cc86c5205fce9ac10814c13) +- [spec] formatting for medic [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c1d0b47929171a45df1bbe9ff095e128d4e7c74e) +- [spec] app id [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/381ee1c6ace4ff2919ea0d33cf770700f5e70c2f) +- [spec] Fixed spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/560cecc5b83c2257215398a9bee5ec12fdfea0b3) +- [spec] app id, title [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a0373c766fb8d9fca0c01a9b5dd1c0bd3c1161a7) +- [spec] fixing spec app [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f9e3d0cffa88a09941aed82f515edeccd8773ad7) +- [spec] add barcodescanner.js [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/604ebdf14485736b7d543812017812a40cada2b6) +- [spec] Initial version of spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7c47973f78d6caad4b3c92709d0d82d59a4fb163) +- update BarcodeScanner plugin for 2.5.0+ [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1661cc4387e1e4110f88b4ef561453030d795182) +- Merge pull request #14 from jwark/do_not_copy_to_clipboard [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/15b5cb9442e1c43ce306fb91f8e2d07e42dd1244) +- update BarcodeScanner plugin for 2.5.0+ [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/58e773af70c59d04012d51ded8ba408037142f95) +- Do not copy the scanned barcode to the clipboard. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1d8ee5ca8d2e2878b82e4db95d7465c15c6fa5f4) +- Merge pull request #7 from JaysonRaymond/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3c73e21796118c3a97ba944e67d6a06c80ca08b4) +- [iOS][2.3.0] add plugin to config.xml for 2.3.0+ + upped version to 0.3.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/bb3812c0cb7b525065101c251b211e320d76c45a) +- readme fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c7158af58ee9aeb0e325ae733c4bbfd1db51e563) +- Update for Cordova/PhoneGap 2.0 plugins (http://simonmacdonald.blogspot.ca/2012/08/so-you-wanna-write-phonegap-200-android.html) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3f166162a05c79782cbcf162154f16b94efa2609) +- [0.2.2] updated version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/029cb4de7d30953811690dba6939b88d9a9ceca7) +- [ios] Fixes AVCaptureSession leak, thanks @markus-olsson [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1e2535ad010e94ee0319f727e0f444035b02742d) +- [android] syntax error, missing else [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/695f524777f9b0ea49dcfe3e980a5053da2e3e4a) +- [0.2.1][ios] lock scanner to portrait [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/084594d86c7cafb98f0985101629fa910141fa6a) +- [0.2.0] updated version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/87ffa13f2c5e63e7388ef37bacf9b02ead8fc0d9) +- [ios] lock scanner orientation to portrait [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/413b0236978186d5c2e3b2675c72997867bcee6a) +- [0.1.2] version update [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/566c1f166a27108c995fd77d5fa20454c7311196) +- [ios] Integrated shazron's iOS6 orientation updates [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e0f7b9a33e647b9763934c09259be01edba88d5c) +- [version] updated to 0.1.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f1fb499e42f31e06d1805dcdf40bd3edcb0fd384) +- [android] Removed app_name string resource [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b145a21012f1b997e0060f8d1c0e6fd25add1cca) +- [readme] corrected supported types for iOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7119054ce63bffdb3bfb77d97aec12307536d795) +- [readme] [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9211290b7656697f7b7a87a05b77286d1f85b2c8) +- [readme] [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/89ed3727372815966fd83b2b925b51d22a18b001) +- [0.1.0] version updated [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3e3093969f0544ede202e6646a655da6fb22f1ac) +- [android] Added translated resource files [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/47a8bdd29c277e69ab1750b94b3c4ac5c01ba19b) +- [android] Modified zxing client to access resources from main package [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9cff772bfc4f404337830a974a9593883cb81d23) +- [android][plugin-xml] Added resource files [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e3505aea3a65a967e7bb710f77f94d05fc556409) +- [android] Added Zxing Library project [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8421719edb1f7005b3a2a46a24c62d2d69479d7a) +- [gitignore] [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c432f127c593791aedc3008a83f7a1a818568700) +- [readme] license [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/274b122932517ccea144d5e279c38beb4ad991aa) +- [plugin-xml] fixed up plugin.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/097548504dd6c192e26256e582882e6b5f12daec) +- [ios] removed CORDOVA_FRAMEWORK ref [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cb2e830ee5223076c9f126d80e07ef614ca3cff1) +- Initial commit. Zeppelin rules. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/92197289049bfd4aab63b6467dddb93449a8a7ef) +- Initial commit [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6de30878ff7ada1b43a01d1037dcee6e419a8050) diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..4458581 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright 2010 Matt Kane +Copyright 2011 IBM Corporation +Copyright 2012-2017 Adobe Systems + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6deb946 --- /dev/null +++ b/README.md @@ -0,0 +1,181 @@ +# PhoneGap Plugin BarcodeScanner +================================ + +[![Build Status](https://travis-ci.org/phonegap/phonegap-plugin-barcodescanner.svg)](https://travis-ci.org/phonegap/phonegap-plugin-barcodescanner) + +Cross-platform BarcodeScanner for Cordova / PhoneGap. + +Follows the [Cordova Plugin spec](https://cordova.apache.org/docs/en/latest/plugin_ref/spec.html), so that it works with [Plugman](https://github.com/apache/cordova-plugman). + +## Installation + + +This requires phonegap 7.1.0+ ( current stable v8.0.0 ) + + phonegap plugin add phonegap-plugin-barcodescanner + +It is also possible to install via repo url directly ( unstable ) + + phonegap plugin add https://github.com/phonegap/phonegap-plugin-barcodescanner.git + +Optional variables: +This plugin requires the Android support library v4. The minimum version is `24.1.0`. Default value is `27.+`. Check out the latest version [here](https://developer.android.com/topic/libraries/support-library/revisions.html). +``` +phonegap plugin add phonegap-plugin-barcodescanner --variable ANDROID_SUPPORT_V4_VERSION="27.1.1" +``` +### Supported Platforms + +- Android +- iOS +- Windows (Windows/Windows Phone 8.1 and Windows 10) +- Browser + +Note: the Android source for this project includes an Android Library Project. +plugman currently doesn't support Library Project refs, so its been +prebuilt as a jar library. Any updates to the Library Project should be +committed with an updated jar. + +Note: Windows 10 applications can not be build for `AnyCPU` architecture, which is default for Windows platform. If you want to build/run Windows 10 app, you should specify target architecture explicitly, for example (Cordova CLI): + +``` +cordova run windows -- --archs=x86 +``` + +### PhoneGap Build Usage + +Add the following to your config.xml: + +``` + + +``` +On PhoneGap Build if you're using a version of cordova-android of 4 or less, ensure you're building with gradle: +``` + +``` + +## Using the plugin ## +The plugin creates the object `cordova.plugins.barcodeScanner` with the method `scan(success, fail)`. + +The following barcode types are currently supported: + +| Barcode Type | Android | iOS | Windows | +|---------------|:-------:|:---:|:--------:| +| QR_CODE | ✔ | ✔ | ✔ | +| DATA_MATRIX | ✔ | ✔ | ✔ | +| UPC_A | ✔ | ✔ | ✔ | +| UPC_E | ✔ | ✔ | ✔ | +| EAN_8 | ✔ | ✔ | ✔ | +| EAN_13 | ✔ | ✔ | ✔ | +| CODE_39 | ✔ | ✔ | ✔ | +| CODE_93 | ✔ | ✖ | ✔ | +| CODE_128 | ✔ | ✔ | ✔ | +| CODABAR | ✔ | ✖ | ✔ | +| ITF | ✔ | ✔ | ✔ | +| RSS14 | ✔ | ✖ | ✔ | +| PDF417 | ✔ | ✖ | ✔ | +| RSS_EXPANDED | ✔ | ✖ | ✖ | +| MSI | ✖ | ✖ | ✔ | +| AZTEC | ✖ | ✖ | ✔ | + +`success` and `fail` are callback functions. Success is passed an object with data, type and cancelled properties. Data is the text representation of the barcode data, type is the type of barcode detected and cancelled is whether or not the user cancelled the scan. + +A full example could be: +```js + cordova.plugins.barcodeScanner.scan( + function (result) { + alert("We got a barcode\n" + + "Result: " + result.text + "\n" + + "Format: " + result.format + "\n" + + "Cancelled: " + result.cancelled); + }, + function (error) { + alert("Scanning failed: " + error); + }, + { + preferFrontCamera : true, // iOS and Android + showFlipCameraButton : true, // iOS and Android + showTorchButton : true, // iOS and Android + torchOn: true, // Android, launch with the torch switched on (if available) + saveHistory: true, // Android, save scan history (default false) + prompt : "Place a barcode inside the scan area", // Android + resultDisplayDuration: 500, // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500 + formats : "QR_CODE,PDF_417", // default: all but PDF_417 and RSS_EXPANDED + orientation : "landscape", // Android only (portrait|landscape), default unset so it rotates with the device + disableAnimations : true, // iOS + disableSuccessBeep: false // iOS and Android + } + ); +``` + +## Encoding a Barcode ## + +The plugin creates the object `cordova.plugins.barcodeScanner` with the method `encode(type, data, success, fail)`. + +Supported encoding types: + +* TEXT_TYPE +* EMAIL_TYPE +* PHONE_TYPE +* SMS_TYPE + +``` +A full example could be: + + cordova.plugins.barcodeScanner.encode(cordova.plugins.barcodeScanner.Encode.TEXT_TYPE, "http://www.nytimes.com", function(success) { + alert("encode success: " + success); + }, function(fail) { + alert("encoding failed: " + fail); + } + ); +``` + +## iOS quirks ## + +Since iOS 10 it's mandatory to add a `NSCameraUsageDescription` in the `Info.plist`. + +`NSCameraUsageDescription` describes the reason that the app accesses the user's camera. +When the system prompts the user to allow access, this string is displayed as part of the dialog box. If you didn't provide the usage description, the app will crash before showing the dialog. Also, Apple will reject apps that access private data but don't provide an usage description. + +To add this entry you can use the `edit-config` tag in the `config.xml` like this: + +``` + + To scan barcodes + +``` + +## Windows quirks ## + +* Windows implementation currently doesn't support encode functionality. + +* On Windows 10 desktop ensure that you have Windows Media Player and Media Feature pack installed. + +## Thanks on Github ## + +So many -- check out the original [iOS](https://github.com/phonegap/phonegap-plugins/tree/DEPRECATED/iOS/BarcodeScanner), [Android](https://github.com/phonegap/phonegap-plugins/tree/DEPRECATED/Android/BarcodeScanner) and +[BlackBerry 10](https://github.com/blackberry/WebWorks-Community-APIs/tree/master/BB10-Cordova/BarcodeScanner) repos. + +## Licence ## + +The MIT License + +Copyright (c) 2010 Matt Kane + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hooks/windows/check-arch.js b/hooks/windows/check-arch.js new file mode 100644 index 0000000..3ae6660 --- /dev/null +++ b/hooks/windows/check-arch.js @@ -0,0 +1,52 @@ +module.exports = function(ctx) { + if (ctx.opts && ctx.opts.platforms && ctx.opts.platforms.indexOf('windows') > -1 + && ctx.opts.options) { + var path = require('path'); + var shell = ctx.requireCordovaModule('shelljs'); + var nopt = ctx.requireCordovaModule('nopt'); + + // parse and validate args + var args = nopt({ + 'archs': [String], + 'appx': String, + 'phone': Boolean, + 'win': Boolean, + 'bundle': Boolean, + 'packageCertificateKeyFile': String, + 'packageThumbprint': String, + 'publisherId': String, + 'buildConfig': String + }, {}, ctx.opts.options.argv, 0); + + // Check if --appx flag is passed so that we have a project build version override: + var isWin10 = args.appx && args.appx.toLowerCase() === 'uap'; + + // Else check "windows-target-version" preference: + if (!isWin10) { + var configXml = shell.ls(path.join(ctx.opts.projectRoot, 'config.xml'))[0]; + + var reTargetVersion = //i; + var targetVersion = shell.grep(reTargetVersion, configXml); + + var result = reTargetVersion.exec(targetVersion); + if (result !== null) { + var match = result[1]; + isWin10 = parseInt(match.split('.'), 10) > 8; + } + } + + // Non-AnyCPU arch is required for Windows 10 (UWP) projects only: + if (isWin10) { + var rawArchs = ctx.opts.options.archs || args.archs; + var archs = rawArchs ? rawArchs.split(' ') : []; + + // Avoid "anycpu" arch: + if (archs.length === 0 || archs.some(function (item) { + return item.toLowerCase() === 'anycpu'; + })) { + throw new Error('You must specify an architecture to include the proper ZXing library version.' + + '\nUse \'cordova run windows -- --arch="x64"\' or \'cordova run windows -- --arch="arm" --phone --device\' for example.'); + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..00a7bfb --- /dev/null +++ b/package.json @@ -0,0 +1,86 @@ +{ + "_from": "phonegap-plugin-barcodescanner@^8.0.0", + "_id": "phonegap-plugin-barcodescanner@8.0.0", + "_inBundle": false, + "_integrity": "sha512-8mWI2bsCwkuvqCFdG7tBXdUH4X3Ay1uXpnjxCS/If8qJIbv1eaI2XMNHN+V2+YUemJoZC7chlF76YXjeQXVEFg==", + "_location": "/phonegap-plugin-barcodescanner", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "phonegap-plugin-barcodescanner@^8.0.0", + "name": "phonegap-plugin-barcodescanner", + "escapedName": "phonegap-plugin-barcodescanner", + "rawSpec": "^8.0.0", + "saveSpec": null, + "fetchSpec": "^8.0.0" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/phonegap-plugin-barcodescanner/-/phonegap-plugin-barcodescanner-8.0.0.tgz", + "_shasum": "bdad5454bcbb1c27b0ded0bc5c646227e7a91f06", + "_spec": "phonegap-plugin-barcodescanner@^8.0.0", + "_where": "D:\\ionic_temp\\vanke", + "author": { + "name": "Adobe PhoneGap Team" + }, + "bugs": { + "url": "https://github.com/phonegap/phonegap-plugin-barcodescanner/issues" + }, + "bundleDependencies": false, + "cordova": { + "id": "phonegap-plugin-barcodescanner", + "platforms": [ + "ios", + "android", + "windows", + "browser" + ] + }, + "deprecated": false, + "description": "You can use the BarcodeScanner plugin to scan different types of barcodes (using the device's camera) and get the metadata encoded in them for processing within your application.", + "devDependencies": { + "jasmine-node": "1.14.5", + "pluginpub": "^0.0.9" + }, + "engines": { + "cordovaDependencies": { + "7.0.0": { + "cordova-android": ">=6.3.0" + }, + "7.1.0": { + "cordova": ">=7.1.0", + "cordova-android": ">=6.3.0" + }, + "8.0.0": { + "cordova": ">=7.1.0", + "cordova-android": ">=6.3.0" + }, + "<7.0.0": { + "cordova-android": "<6.3.0" + } + } + }, + "homepage": "https://github.com/phonegap/phonegap-plugin-barcodescanner#readme", + "keywords": [ + "ecosystem:cordova", + "ecosystem:phonegap", + "cordova-ios", + "cordova-android", + "cordova-windows", + "cordova-browser", + "cordova:plugin" + ], + "license": "MIT", + "name": "phonegap-plugin-barcodescanner", + "repository": { + "type": "git", + "url": "git+https://github.com/phonegap/phonegap-plugin-barcodescanner.git" + }, + "scripts": { + "test": "jasmine-node --color spec" + }, + "version": "8.0.0" +} diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..6967d2e --- /dev/null +++ b/plugin.xml @@ -0,0 +1,71 @@ + + + BarcodeScanner + You can use the BarcodeScanner plugin to scan different types of barcodes (using the device's camera) and get the metadata encoded in them for processing within your application. + MIT + https://github.com/phonegap/phonegap-plugin-barcodescanner + https://github.com/phonegap/phonegap-plugin-barcodescanner/issues + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin.xml.bak b/plugin.xml.bak new file mode 100644 index 0000000..71c1de8 --- /dev/null +++ b/plugin.xml.bak @@ -0,0 +1,71 @@ + + + BarcodeScanner + You can use the BarcodeScanner plugin to scan different types of barcodes (using the device's camera) and get the metadata encoded in them for processing within your application. + MIT + https://github.com/phonegap/phonegap-plugin-barcodescanner + https://github.com/phonegap/phonegap-plugin-barcodescanner/issues + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spec/helper/cordova.js b/spec/helper/cordova.js new file mode 100644 index 0000000..02bdee5 --- /dev/null +++ b/spec/helper/cordova.js @@ -0,0 +1,83 @@ +/* global cordova:true */ + +/*! + * Module dependencies. + */ + +/** + * cordova.js for node. + * + * Think of this as cordova-node, which would be simliar to cordova-android + * or cordova-browser. The purpose of this module is to enable testing + * of a plugin's JavaScript interface. + * + * When this module is first required, it will insert a global cordova + * instance, which can hijack cordova-specific commands within the pluin's + * implementation. + * + * Remember to require this module before the plugin that you want to test. + * + * Example: + * + * var cordova = require('./helper/cordova'), + * myPlugin = require('../www/myPlugin'); + */ + +module.exports = global.cordova = cordova = { + + /** + * cordova.require Mock. + * + * Hijacks all cordova.requires. By default, it returns an empty function. + * You can define your own implementation of each required module before + * or after it has been required. + * + * See `cordova.required` to learn how to add your own module implemtnation. + */ + + require: function(moduleId) { + // define a default function if it doesn't exist + if (!cordova.required[moduleId]) { + cordova.required[moduleId] = function() {}; + } + // create a new module mapping between the module Id and cordova.required. + return new ModuleMap(moduleId); + }, + + /** + * Cordova module implementations. + * + * A key-value hash, where the key is the module such as 'cordova/exec' + * and the value is the function or object returned. + * + * For example: + * + * var exec = require('cordova/exec'); + * + * Will map to: + * + * cordova.required['cordova/exec']; + */ + + required: { + // populated at runtime + } +}; + +/** + * Module Mapper. + * + * Returns a function that when executed will lookup the implementation + * in cordova.required[id]. + * + * @param {String} moduleId is the module name/path, such as 'cordova/exec' + * @return {Function}. + */ + +function ModuleMap(moduleId) { + return function() { + // lookup and execute the module's mock implementation, passing + // in any parameters that were provided. + return cordova.required[moduleId].apply(this, arguments); + }; +} diff --git a/spec/index.spec.js b/spec/index.spec.js new file mode 100644 index 0000000..8015b30 --- /dev/null +++ b/spec/index.spec.js @@ -0,0 +1,78 @@ +/* globals require */ + +/*! + * Module dependencies. + */ + +var cordova = require('./helper/cordova'), + BarcodeScanner = require('../www/barcodescanner'), + execSpy, + execWin, + options; + +/*! + * Specification. + */ + +describe('phonegap-plugin-barcodescanner', function () { + beforeEach(function () { + execWin = jasmine.createSpy(); + execSpy = spyOn(cordova.required, 'cordova/exec').andCallFake(execWin); + }); + + describe('BarcodeScanner', function () { + it("BarcodeScanner plugin should exist", function() { + expect(BarcodeScanner).toBeDefined(); + expect(typeof BarcodeScanner == 'object').toBe(true); + }); + + it("should contain a scan function", function() { + expect(BarcodeScanner.scan).toBeDefined(); + expect(typeof BarcodeScanner.scan == 'function').toBe(true); + }); + + it("should contain an encode function", function() { + expect(BarcodeScanner.encode).toBeDefined(); + expect(typeof BarcodeScanner.encode == 'function').toBe(true); + }); + + it("should contain three DestinationType constants", function() { + expect(BarcodeScanner.Encode.TEXT_TYPE).toBe("TEXT_TYPE"); + expect(BarcodeScanner.Encode.EMAIL_TYPE).toBe("EMAIL_TYPE"); + expect(BarcodeScanner.Encode.PHONE_TYPE).toBe("PHONE_TYPE"); + expect(BarcodeScanner.Encode.SMS_TYPE).toBe("SMS_TYPE"); + }); + }); + + describe('BarcodeScanner instance', function () { + describe('cordova.exec', function () { + it('should call cordova.exec on next process tick', function (done) { + BarcodeScanner.scan(function() {}, function() {}, {}); + setTimeout(function () { + expect(execSpy).toHaveBeenCalledWith( + jasmine.any(Function), + jasmine.any(Function), + 'BarcodeScanner', + 'scan', + jasmine.any(Object) + ); + done(); + }, 100); + }); + + it('should call cordova.exec on next process tick', function (done) { + BarcodeScanner.encode("", "",function() {}, function() {}, {}); + setTimeout(function () { + expect(execSpy).toHaveBeenCalledWith( + jasmine.any(Function), + jasmine.any(Function), + 'BarcodeScanner', + 'encode', + jasmine.any(Object) + ); + done(); + }, 100); + }); + }); + }); +}); diff --git a/src/android/README.md b/src/android/README.md new file mode 100644 index 0000000..537afd2 --- /dev/null +++ b/src/android/README.md @@ -0,0 +1 @@ +The Android .aar sources are [here](https://github.com/EddyVerbruggen/barcodescanner-lib-aar). \ No newline at end of file diff --git a/src/android/barcodescanner-release-2.1.5.aar b/src/android/barcodescanner-release-2.1.5.aar new file mode 100644 index 0000000..bd497a9 Binary files /dev/null and b/src/android/barcodescanner-release-2.1.5.aar differ diff --git a/src/android/barcodescanner.gradle b/src/android/barcodescanner.gradle new file mode 100644 index 0000000..93c8d61 --- /dev/null +++ b/src/android/barcodescanner.gradle @@ -0,0 +1,17 @@ +repositories{ + jcenter() + flatDir{ + dirs 'libs' + } +} + +dependencies { + compile(name:'barcodescanner-release-2.1.5', ext:'aar') +} + +android { + packagingOptions { + exclude 'META-INF/NOTICE' + exclude 'META-INF/LICENSE' + } +} diff --git a/src/android/com/phonegap/plugins/barcodescanner/BarcodeScanner.java b/src/android/com/phonegap/plugins/barcodescanner/BarcodeScanner.java new file mode 100644 index 0000000..97803a5 --- /dev/null +++ b/src/android/com/phonegap/plugins/barcodescanner/BarcodeScanner.java @@ -0,0 +1,328 @@ +/** + * PhoneGap is available under *either* the terms of the modified BSD license *or* the + * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text. + * + * Copyright (c) Matt Kane 2010 + * Copyright (c) 2011, IBM Corporation + * Copyright (c) 2013, Maciej Nux Jaros + */ +package com.phonegap.plugins.barcodescanner; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.Manifest; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.content.pm.PackageManager; + +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CallbackContext; +import org.apache.cordova.PluginResult; +import org.apache.cordova.PermissionHelper; + +import org.google.zxing.client.android.CaptureActivity; +import org.google.zxing.client.android.encode.EncodeActivity; +import org.google.zxing.client.android.Intents; + +/** + * This calls out to the ZXing barcode reader and returns the result. + * + * @sa https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java + */ +public class BarcodeScanner extends CordovaPlugin { + public static final int REQUEST_CODE = 0x0ba7c; + + private static final String SCAN = "scan"; + private static final String ENCODE = "encode"; + private static final String CANCELLED = "cancelled"; + private static final String FORMAT = "format"; + private static final String TEXT = "text"; + private static final String DATA = "data"; + private static final String TYPE = "type"; + private static final String PREFER_FRONTCAMERA = "preferFrontCamera"; + private static final String ORIENTATION = "orientation"; + private static final String SHOW_FLIP_CAMERA_BUTTON = "showFlipCameraButton"; + private static final String RESULTDISPLAY_DURATION = "resultDisplayDuration"; + private static final String SHOW_TORCH_BUTTON = "showTorchButton"; + private static final String TORCH_ON = "torchOn"; + private static final String SAVE_HISTORY = "saveHistory"; + private static final String DISABLE_BEEP = "disableSuccessBeep"; + private static final String FORMATS = "formats"; + private static final String PROMPT = "prompt"; + private static final String TEXT_TYPE = "TEXT_TYPE"; + private static final String EMAIL_TYPE = "EMAIL_TYPE"; + private static final String PHONE_TYPE = "PHONE_TYPE"; + private static final String SMS_TYPE = "SMS_TYPE"; + + private static final String LOG_TAG = "BarcodeScanner"; + + private String [] permissions = { Manifest.permission.CAMERA }; + + private JSONArray requestArgs; + private CallbackContext callbackContext; + + /** + * Constructor. + */ + public BarcodeScanner() { + } + + /** + * Executes the request. + * + * This method is called from the WebView thread. To do a non-trivial amount of work, use: + * cordova.getThreadPool().execute(runnable); + * + * To run on the UI thread, use: + * cordova.getActivity().runOnUiThread(runnable); + * + * @param action The action to execute. + * @param args The exec() arguments. + * @param callbackContext The callback context used when calling back into JavaScript. + * @return Whether the action was valid. + * + * @sa https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java + */ + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) { + this.callbackContext = callbackContext; + this.requestArgs = args; + + if (action.equals(ENCODE)) { + JSONObject obj = args.optJSONObject(0); + if (obj != null) { + String type = obj.optString(TYPE); + String data = obj.optString(DATA); + + // If the type is null then force the type to text + if (type == null) { + type = TEXT_TYPE; + } + + if (data == null) { + callbackContext.error("User did not specify data to encode"); + return true; + } + + encode(type, data); + } else { + callbackContext.error("User did not specify data to encode"); + return true; + } + } else if (action.equals(SCAN)) { + + //android permission auto add + if(!hasPermisssion()) { + requestPermissions(0); + } else { + scan(args); + } + } else { + return false; + } + return true; + } + + /** + * Starts an intent to scan and decode a barcode. + */ + public void scan(final JSONArray args) { + + final CordovaPlugin that = this; + + cordova.getThreadPool().execute(new Runnable() { + public void run() { + + Intent intentScan = new Intent(that.cordova.getActivity().getBaseContext(), CaptureActivity.class); + intentScan.setAction(Intents.Scan.ACTION); + intentScan.addCategory(Intent.CATEGORY_DEFAULT); + + // add config as intent extras + if (args.length() > 0) { + + JSONObject obj; + JSONArray names; + String key; + Object value; + + for (int i = 0; i < args.length(); i++) { + + try { + obj = args.getJSONObject(i); + } catch (JSONException e) { + Log.i("CordovaLog", e.getLocalizedMessage()); + continue; + } + + names = obj.names(); + for (int j = 0; j < names.length(); j++) { + try { + key = names.getString(j); + value = obj.get(key); + + if (value instanceof Integer) { + intentScan.putExtra(key, (Integer) value); + } else if (value instanceof String) { + intentScan.putExtra(key, (String) value); + } + + } catch (JSONException e) { + Log.i("CordovaLog", e.getLocalizedMessage()); + } + } + + intentScan.putExtra(Intents.Scan.CAMERA_ID, obj.optBoolean(PREFER_FRONTCAMERA, false) ? 1 : 0); + intentScan.putExtra(Intents.Scan.SHOW_FLIP_CAMERA_BUTTON, obj.optBoolean(SHOW_FLIP_CAMERA_BUTTON, false)); + intentScan.putExtra(Intents.Scan.SHOW_TORCH_BUTTON, obj.optBoolean(SHOW_TORCH_BUTTON, false)); + intentScan.putExtra(Intents.Scan.TORCH_ON, obj.optBoolean(TORCH_ON, false)); + intentScan.putExtra(Intents.Scan.SAVE_HISTORY, obj.optBoolean(SAVE_HISTORY, false)); + boolean beep = obj.optBoolean(DISABLE_BEEP, false); + intentScan.putExtra(Intents.Scan.BEEP_ON_SCAN, !beep); + if (obj.has(RESULTDISPLAY_DURATION)) { + intentScan.putExtra(Intents.Scan.RESULT_DISPLAY_DURATION_MS, "" + obj.optLong(RESULTDISPLAY_DURATION)); + } + if (obj.has(FORMATS)) { + intentScan.putExtra(Intents.Scan.FORMATS, obj.optString(FORMATS)); + } + if (obj.has(PROMPT)) { + intentScan.putExtra(Intents.Scan.PROMPT_MESSAGE, obj.optString(PROMPT)); + } + if (obj.has(ORIENTATION)) { + intentScan.putExtra(Intents.Scan.ORIENTATION_LOCK, obj.optString(ORIENTATION)); + } + } + + } + + // avoid calling other phonegap apps + intentScan.setPackage(that.cordova.getActivity().getApplicationContext().getPackageName()); + + that.cordova.startActivityForResult(that, intentScan, REQUEST_CODE); + } + }); + } + + /** + * Called when the barcode scanner intent completes. + * + * @param requestCode The request code originally supplied to startActivityForResult(), + * allowing you to identify who this result came from. + * @param resultCode The integer result code returned by the child activity through its setResult(). + * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). + */ + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + if (requestCode == REQUEST_CODE && this.callbackContext != null) { + if (resultCode == Activity.RESULT_OK) { + JSONObject obj = new JSONObject(); + try { + obj.put(TEXT, intent.getStringExtra("SCAN_RESULT")); + obj.put(FORMAT, intent.getStringExtra("SCAN_RESULT_FORMAT")); + obj.put(CANCELLED, false); + } catch (JSONException e) { + Log.d(LOG_TAG, "This should never happen"); + } + //this.success(new PluginResult(PluginResult.Status.OK, obj), this.callback); + this.callbackContext.success(obj); + } else if (resultCode == Activity.RESULT_CANCELED) { + JSONObject obj = new JSONObject(); + try { + obj.put(TEXT, ""); + obj.put(FORMAT, ""); + obj.put(CANCELLED, true); + } catch (JSONException e) { + Log.d(LOG_TAG, "This should never happen"); + } + //this.success(new PluginResult(PluginResult.Status.OK, obj), this.callback); + this.callbackContext.success(obj); + } else { + //this.error(new PluginResult(PluginResult.Status.ERROR), this.callback); + this.callbackContext.error("Unexpected error"); + } + } + } + + /** + * Initiates a barcode encode. + * + * @param type Endoiding type. + * @param data The data to encode in the bar code. + */ + public void encode(String type, String data) { + Intent intentEncode = new Intent(this.cordova.getActivity().getBaseContext(), EncodeActivity.class); + intentEncode.setAction(Intents.Encode.ACTION); + intentEncode.putExtra(Intents.Encode.TYPE, type); + intentEncode.putExtra(Intents.Encode.DATA, data); + // avoid calling other phonegap apps + intentEncode.setPackage(this.cordova.getActivity().getApplicationContext().getPackageName()); + + this.cordova.getActivity().startActivity(intentEncode); + } + + /** + * check application's permissions + */ + public boolean hasPermisssion() { + for(String p : permissions) + { + if(!PermissionHelper.hasPermission(this, p)) + { + return false; + } + } + return true; + } + + /** + * We override this so that we can access the permissions variable, which no longer exists in + * the parent class, since we can't initialize it reliably in the constructor! + * + * @param requestCode The code to get request action + */ + public void requestPermissions(int requestCode) + { + PermissionHelper.requestPermissions(this, requestCode, permissions); + } + + /** + * processes the result of permission request + * + * @param requestCode The code to get request action + * @param permissions The collection of permissions + * @param grantResults The result of grant + */ + public void onRequestPermissionResult(int requestCode, String[] permissions, + int[] grantResults) throws JSONException + { + PluginResult result; + for (int r : grantResults) { + if (r == PackageManager.PERMISSION_DENIED) { + Log.d(LOG_TAG, "Permission Denied!"); + result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION); + this.callbackContext.sendPluginResult(result); + return; + } + } + + switch(requestCode) + { + case 0: + scan(this.requestArgs); + break; + } + } + + /** + * This plugin launches an external Activity when the camera is opened, so we + * need to implement the save/restore API in case the Activity gets killed + * by the OS while it's in the background. + */ + public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) { + this.callbackContext = callbackContext; + } + +} diff --git a/src/browser/BarcodeScannerProxy.js b/src/browser/BarcodeScannerProxy.js new file mode 100644 index 0000000..6670dc6 --- /dev/null +++ b/src/browser/BarcodeScannerProxy.js @@ -0,0 +1,24 @@ +function scan(success, error) { + var code = window.prompt("Enter barcode value (empty value will fire the error handler):"); + if(code) { + var result = { + text:code, + format:"Fake", + cancelled:false + }; + success(result); + } else { + error("No barcode"); + } +} + +function encode(type, data, success, errorCallback) { + success(); +} + +module.exports = { + scan: scan, + encode: encode +}; + +require("cordova/exec/proxy").add("BarcodeScanner",module.exports); \ No newline at end of file diff --git a/src/ios/CDVBarcodeScanner.bundle/beep.caf b/src/ios/CDVBarcodeScanner.bundle/beep.caf new file mode 100644 index 0000000..4bce167 Binary files /dev/null and b/src/ios/CDVBarcodeScanner.bundle/beep.caf differ diff --git a/src/ios/CDVBarcodeScanner.bundle/torch.png b/src/ios/CDVBarcodeScanner.bundle/torch.png new file mode 100644 index 0000000..bc61037 Binary files /dev/null and b/src/ios/CDVBarcodeScanner.bundle/torch.png differ diff --git a/src/ios/CDVBarcodeScanner.bundle/torch@2x.png b/src/ios/CDVBarcodeScanner.bundle/torch@2x.png new file mode 100644 index 0000000..a3e4e85 Binary files /dev/null and b/src/ios/CDVBarcodeScanner.bundle/torch@2x.png differ diff --git a/src/ios/CDVBarcodeScanner.bundle/torch@3x.png b/src/ios/CDVBarcodeScanner.bundle/torch@3x.png new file mode 100644 index 0000000..d76584a Binary files /dev/null and b/src/ios/CDVBarcodeScanner.bundle/torch@3x.png differ diff --git a/src/ios/CDVBarcodeScanner.mm b/src/ios/CDVBarcodeScanner.mm new file mode 100644 index 0000000..bb2a3ba --- /dev/null +++ b/src/ios/CDVBarcodeScanner.mm @@ -0,0 +1,1051 @@ +/* + * PhoneGap is available under *either* the terms of the modified BSD license *or* the + * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text. + * + * Copyright 2011 Matt Kane. All rights reserved. + * Copyright (c) 2011, IBM Corporation + */ + +#import +#import +#import + + +//------------------------------------------------------------------------------ +// Delegate to handle orientation functions +//------------------------------------------------------------------------------ +@protocol CDVBarcodeScannerOrientationDelegate + +- (NSUInteger)supportedInterfaceOrientations; +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; +- (BOOL)shouldAutorotate; + +@end + +//------------------------------------------------------------------------------ +// Adds a shutter button to the UI, and changes the scan from continuous to +// only performing a scan when you click the shutter button. For testing. +//------------------------------------------------------------------------------ +#define USE_SHUTTER 0 + +//------------------------------------------------------------------------------ +@class CDVbcsProcessor; +@class CDVbcsViewController; + +//------------------------------------------------------------------------------ +// plugin class +//------------------------------------------------------------------------------ +@interface CDVBarcodeScanner : CDVPlugin {} +- (NSString*)isScanNotPossible; +- (void)scan:(CDVInvokedUrlCommand*)command; +- (void)encode:(CDVInvokedUrlCommand*)command; +- (void)returnImage:(NSString*)filePath format:(NSString*)format callback:(NSString*)callback; +- (void)returnSuccess:(NSString*)scannedText format:(NSString*)format cancelled:(BOOL)cancelled flipped:(BOOL)flipped callback:(NSString*)callback; +- (void)returnError:(NSString*)message callback:(NSString*)callback; +@end + +//------------------------------------------------------------------------------ +// class that does the grunt work +//------------------------------------------------------------------------------ +@interface CDVbcsProcessor : NSObject {} +@property (nonatomic, retain) CDVBarcodeScanner* plugin; +@property (nonatomic, retain) NSString* callback; +@property (nonatomic, retain) UIViewController* parentViewController; +@property (nonatomic, retain) CDVbcsViewController* viewController; +@property (nonatomic, retain) AVCaptureSession* captureSession; +@property (nonatomic, retain) AVCaptureVideoPreviewLayer* previewLayer; +@property (nonatomic, retain) NSString* alternateXib; +@property (nonatomic, retain) NSMutableArray* results; +@property (nonatomic, retain) NSString* formats; +@property (nonatomic) BOOL is1D; +@property (nonatomic) BOOL is2D; +@property (nonatomic) BOOL capturing; +@property (nonatomic) BOOL isFrontCamera; +@property (nonatomic) BOOL isShowFlipCameraButton; +@property (nonatomic) BOOL isShowTorchButton; +@property (nonatomic) BOOL isFlipped; +@property (nonatomic) BOOL isTransitionAnimated; +@property (nonatomic) BOOL isSuccessBeepEnabled; + + +- (id)initWithPlugin:(CDVBarcodeScanner*)plugin callback:(NSString*)callback parentViewController:(UIViewController*)parentViewController alterateOverlayXib:(NSString *)alternateXib; +- (void)scanBarcode; +- (void)barcodeScanSucceeded:(NSString*)text format:(NSString*)format; +- (void)barcodeScanFailed:(NSString*)message; +- (void)barcodeScanCancelled; +- (void)openDialog; +- (NSString*)setUpCaptureSession; +- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection; +@end + +//------------------------------------------------------------------------------ +// Qr encoder processor +//------------------------------------------------------------------------------ +@interface CDVqrProcessor: NSObject +@property (nonatomic, retain) CDVBarcodeScanner* plugin; +@property (nonatomic, retain) NSString* callback; +@property (nonatomic, retain) NSString* stringToEncode; +@property NSInteger size; + +- (id)initWithPlugin:(CDVBarcodeScanner*)plugin callback:(NSString*)callback stringToEncode:(NSString*)stringToEncode; +- (void)generateImage; +@end + +//------------------------------------------------------------------------------ +// view controller for the ui +//------------------------------------------------------------------------------ +@interface CDVbcsViewController : UIViewController {} +@property (nonatomic, retain) CDVbcsProcessor* processor; +@property (nonatomic, retain) NSString* alternateXib; +@property (nonatomic) BOOL shutterPressed; +@property (nonatomic, retain) IBOutlet UIView* overlayView; +@property (nonatomic, retain) UIToolbar * toolbar; +@property (nonatomic, retain) UIView * reticleView; +// unsafe_unretained is equivalent to assign - used to prevent retain cycles in the property below +@property (nonatomic, unsafe_unretained) id orientationDelegate; + +- (id)initWithProcessor:(CDVbcsProcessor*)processor alternateOverlay:(NSString *)alternateXib; +- (void)startCapturing; +- (UIView*)buildOverlayView; +- (UIImage*)buildReticleImage; +- (void)shutterButtonPressed; +- (IBAction)cancelButtonPressed:(id)sender; +- (IBAction)flipCameraButtonPressed:(id)sender; +- (IBAction)torchButtonPressed:(id)sender; + +@end + +//------------------------------------------------------------------------------ +// plugin class +//------------------------------------------------------------------------------ +@implementation CDVBarcodeScanner + +//-------------------------------------------------------------------------- +- (NSString*)isScanNotPossible { + NSString* result = nil; + + Class aClass = NSClassFromString(@"AVCaptureSession"); + if (aClass == nil) { + return @"AVFoundation Framework not available"; + } + + return result; +} + +-(BOOL)notHasPermission +{ + AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; + return (authStatus == AVAuthorizationStatusDenied || + authStatus == AVAuthorizationStatusRestricted); +} + +-(BOOL)isUsageDescriptionSet +{ + NSDictionary * plist = [[NSBundle mainBundle] infoDictionary]; + if ([plist objectForKey:@"NSCameraUsageDescription" ]) { + return YES; + } + return NO; +} + + + +//-------------------------------------------------------------------------- +- (void)scan:(CDVInvokedUrlCommand*)command { + CDVbcsProcessor* processor; + NSString* callback; + NSString* capabilityError; + + callback = command.callbackId; + + NSDictionary* options; + if (command.arguments.count == 0) { + options = [NSDictionary dictionary]; + } else { + options = command.arguments[0]; + } + + BOOL preferFrontCamera = [options[@"preferFrontCamera"] boolValue]; + BOOL showFlipCameraButton = [options[@"showFlipCameraButton"] boolValue]; + BOOL showTorchButton = [options[@"showTorchButton"] boolValue]; + BOOL disableAnimations = [options[@"disableAnimations"] boolValue]; + BOOL disableSuccessBeep = [options[@"disableSuccessBeep"] boolValue]; + + // We allow the user to define an alternate xib file for loading the overlay. + NSString *overlayXib = options[@"overlayXib"]; + + capabilityError = [self isScanNotPossible]; + if (capabilityError) { + [self returnError:capabilityError callback:callback]; + return; + } else if ([self notHasPermission]) { + NSString * error = NSLocalizedString(@"Access to the camera has been prohibited; please enable it in the Settings app to continue.",nil); + [self returnError:error callback:callback]; + return; + } else if (![self isUsageDescriptionSet]) { + NSString * error = NSLocalizedString(@"NSCameraUsageDescription is not set in the info.plist", nil); + [self returnError:error callback:callback]; + return; + } + + processor = [[CDVbcsProcessor alloc] + initWithPlugin:self + callback:callback + parentViewController:self.viewController + alterateOverlayXib:overlayXib + ]; + // queue [processor scanBarcode] to run on the event loop + + if (preferFrontCamera) { + processor.isFrontCamera = true; + } + + if (showFlipCameraButton) { + processor.isShowFlipCameraButton = true; + } + + if (showTorchButton) { + processor.isShowTorchButton = true; + } + + processor.isSuccessBeepEnabled = !disableSuccessBeep; + + processor.isTransitionAnimated = !disableAnimations; + + processor.formats = options[@"formats"]; + + [processor performSelector:@selector(scanBarcode) withObject:nil afterDelay:0]; +} + +//-------------------------------------------------------------------------- +- (void)encode:(CDVInvokedUrlCommand*)command { + if([command.arguments count] < 1) + [self returnError:@"Too few arguments!" callback:command.callbackId]; + + CDVqrProcessor* processor; + NSString* callback; + callback = command.callbackId; + + processor = [[CDVqrProcessor alloc] + initWithPlugin:self + callback:callback + stringToEncode: command.arguments[0][@"data"] + ]; + // queue [processor generateImage] to run on the event loop + [processor performSelector:@selector(generateImage) withObject:nil afterDelay:0]; +} + +- (void)returnImage:(NSString*)filePath format:(NSString*)format callback:(NSString*)callback{ + NSMutableDictionary* resultDict = [[NSMutableDictionary alloc] init]; + resultDict[@"format"] = format; + resultDict[@"file"] = filePath; + + CDVPluginResult* result = [CDVPluginResult + resultWithStatus: CDVCommandStatus_OK + messageAsDictionary:resultDict + ]; + + [[self commandDelegate] sendPluginResult:result callbackId:callback]; +} + +//-------------------------------------------------------------------------- +- (void)returnSuccess:(NSString*)scannedText format:(NSString*)format cancelled:(BOOL)cancelled flipped:(BOOL)flipped callback:(NSString*)callback{ + NSNumber* cancelledNumber = @(cancelled ? 1 : 0); + + NSMutableDictionary* resultDict = [NSMutableDictionary new]; + resultDict[@"text"] = scannedText; + resultDict[@"format"] = format; + resultDict[@"cancelled"] = cancelledNumber; + + CDVPluginResult* result = [CDVPluginResult + resultWithStatus: CDVCommandStatus_OK + messageAsDictionary: resultDict + ]; + [self.commandDelegate sendPluginResult:result callbackId:callback]; +} + +//-------------------------------------------------------------------------- +- (void)returnError:(NSString*)message callback:(NSString*)callback { + CDVPluginResult* result = [CDVPluginResult + resultWithStatus: CDVCommandStatus_ERROR + messageAsString: message + ]; + + [self.commandDelegate sendPluginResult:result callbackId:callback]; +} + +@end + +//------------------------------------------------------------------------------ +// class that does the grunt work +//------------------------------------------------------------------------------ +@implementation CDVbcsProcessor + +@synthesize plugin = _plugin; +@synthesize callback = _callback; +@synthesize parentViewController = _parentViewController; +@synthesize viewController = _viewController; +@synthesize captureSession = _captureSession; +@synthesize previewLayer = _previewLayer; +@synthesize alternateXib = _alternateXib; +@synthesize is1D = _is1D; +@synthesize is2D = _is2D; +@synthesize capturing = _capturing; +@synthesize results = _results; + +SystemSoundID _soundFileObject; + +//-------------------------------------------------------------------------- +- (id)initWithPlugin:(CDVBarcodeScanner*)plugin + callback:(NSString*)callback +parentViewController:(UIViewController*)parentViewController + alterateOverlayXib:(NSString *)alternateXib { + self = [super init]; + if (!self) return self; + + self.plugin = plugin; + self.callback = callback; + self.parentViewController = parentViewController; + self.alternateXib = alternateXib; + + self.is1D = YES; + self.is2D = YES; + self.capturing = NO; + self.results = [NSMutableArray new]; + + CFURLRef soundFileURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("CDVBarcodeScanner.bundle/beep"), CFSTR ("caf"), NULL); + AudioServicesCreateSystemSoundID(soundFileURLRef, &_soundFileObject); + + return self; +} + +//-------------------------------------------------------------------------- +- (void)dealloc { + self.plugin = nil; + self.callback = nil; + self.parentViewController = nil; + self.viewController = nil; + self.captureSession = nil; + self.previewLayer = nil; + self.alternateXib = nil; + self.results = nil; + + self.capturing = NO; + + AudioServicesRemoveSystemSoundCompletion(_soundFileObject); + AudioServicesDisposeSystemSoundID(_soundFileObject); +} + +//-------------------------------------------------------------------------- +- (void)scanBarcode { + +// self.captureSession = nil; +// self.previewLayer = nil; + NSString* errorMessage = [self setUpCaptureSession]; + if (errorMessage) { + [self barcodeScanFailed:errorMessage]; + return; + } + + self.viewController = [[CDVbcsViewController alloc] initWithProcessor: self alternateOverlay:self.alternateXib]; + // here we set the orientation delegate to the MainViewController of the app (orientation controlled in the Project Settings) + self.viewController.orientationDelegate = self.plugin.viewController; + + // delayed [self openDialog]; + [self performSelector:@selector(openDialog) withObject:nil afterDelay:1]; +} + +//-------------------------------------------------------------------------- +- (void)openDialog { + [self.parentViewController + presentViewController:self.viewController + animated:self.isTransitionAnimated completion:nil + ]; +} + +//-------------------------------------------------------------------------- +- (void)barcodeScanDone:(void (^)(void))callbackBlock { + self.capturing = NO; + [self.captureSession stopRunning]; + [self.parentViewController dismissViewControllerAnimated:self.isTransitionAnimated completion:callbackBlock]; + + + AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + [device lockForConfiguration:nil]; + if([device isAutoFocusRangeRestrictionSupported]) { + [device setAutoFocusRangeRestriction:AVCaptureAutoFocusRangeRestrictionNone]; + } + [device unlockForConfiguration]; + + // viewcontroller holding onto a reference to us, release them so they + // will release us + self.viewController = nil; +} + +//-------------------------------------------------------------------------- +- (BOOL)checkResult:(NSString *)result { + [self.results addObject:result]; + + NSInteger treshold = 7; + + if (self.results.count > treshold) { + [self.results removeObjectAtIndex:0]; + } + + if (self.results.count < treshold) + { + return NO; + } + + BOOL allEqual = YES; + NSString *compareString = self.results[0]; + + for (NSString *aResult in self.results) + { + if (![compareString isEqualToString:aResult]) + { + allEqual = NO; + //NSLog(@"Did not fit: %@",self.results); + break; + } + } + + return allEqual; +} + +//-------------------------------------------------------------------------- +- (void)barcodeScanSucceeded:(NSString*)text format:(NSString*)format { + dispatch_sync(dispatch_get_main_queue(), ^{ + if (self.isSuccessBeepEnabled) { + AudioServicesPlaySystemSound(_soundFileObject); + } + [self barcodeScanDone:^{ + [self.plugin returnSuccess:text format:format cancelled:FALSE flipped:FALSE callback:self.callback]; + }]; + }); +} + +//-------------------------------------------------------------------------- +- (void)barcodeScanFailed:(NSString*)message { + dispatch_sync(dispatch_get_main_queue(), ^{ + [self barcodeScanDone:^{ + [self.plugin returnError:message callback:self.callback]; + }]; + }); +} + +//-------------------------------------------------------------------------- +- (void)barcodeScanCancelled { + [self barcodeScanDone:^{ + [self.plugin returnSuccess:@"" format:@"" cancelled:TRUE flipped:self.isFlipped callback:self.callback]; + }]; + if (self.isFlipped) { + self.isFlipped = NO; + } +} + +- (void)flipCamera { + self.isFlipped = YES; + self.isFrontCamera = !self.isFrontCamera; + [self barcodeScanDone:^{ + if (self.isFlipped) { + self.isFlipped = NO; + } + [self performSelector:@selector(scanBarcode) withObject:nil afterDelay:0.1]; + }]; +} + +- (void)toggleTorch { + AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + [device lockForConfiguration:nil]; + if (device.flashActive) { + [device setTorchMode:AVCaptureTorchModeOff]; + [device setFlashMode:AVCaptureFlashModeOff]; + } else { + [device setTorchModeOnWithLevel:AVCaptureMaxAvailableTorchLevel error:nil]; + [device setFlashMode:AVCaptureFlashModeOn]; + } + [device unlockForConfiguration]; +} + +//-------------------------------------------------------------------------- +- (NSString*)setUpCaptureSession { + NSError* error = nil; + + AVCaptureSession* captureSession = [[AVCaptureSession alloc] init]; + self.captureSession = captureSession; + + AVCaptureDevice* __block device = nil; + if (self.isFrontCamera) { + + NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; + [devices enumerateObjectsUsingBlock:^(AVCaptureDevice *obj, NSUInteger idx, BOOL *stop) { + if (obj.position == AVCaptureDevicePositionFront) { + device = obj; + } + }]; + } else { + device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + if (!device) return @"unable to obtain video capture device"; + + } + + // set focus params if available to improve focusing + [device lockForConfiguration:&error]; + if (error == nil) { + if([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) { + [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; + } + if([device isAutoFocusRangeRestrictionSupported]) { + [device setAutoFocusRangeRestriction:AVCaptureAutoFocusRangeRestrictionNear]; + } + } + [device unlockForConfiguration]; + + AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; + if (!input) return @"unable to obtain video capture device input"; + + AVCaptureMetadataOutput* output = [[AVCaptureMetadataOutput alloc] init]; + if (!output) return @"unable to obtain video capture output"; + + [output setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)]; + + if ([captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) { + captureSession.sessionPreset = AVCaptureSessionPresetHigh; + } else if ([captureSession canSetSessionPreset:AVCaptureSessionPresetMedium]) { + captureSession.sessionPreset = AVCaptureSessionPresetMedium; + } else { + return @"unable to preset high nor medium quality video capture"; + } + + if ([captureSession canAddInput:input]) { + [captureSession addInput:input]; + } + else { + return @"unable to add video capture device input to session"; + } + + if ([captureSession canAddOutput:output]) { + [captureSession addOutput:output]; + } + else { + return @"unable to add video capture output to session"; + } + + [output setMetadataObjectTypes:[self formatObjectTypes]]; + + // setup capture preview layer + self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession]; + self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; + + // run on next event loop pass [captureSession startRunning] + [captureSession performSelector:@selector(startRunning) withObject:nil afterDelay:0]; + + return nil; +} + +//-------------------------------------------------------------------------- +// this method gets sent the captured frames +//-------------------------------------------------------------------------- +- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection*)connection { + + if (!self.capturing) return; + +#if USE_SHUTTER + if (!self.viewController.shutterPressed) return; + self.viewController.shutterPressed = NO; + + UIView* flashView = [[UIView alloc] initWithFrame:self.viewController.view.frame]; + [flashView setBackgroundColor:[UIColor whiteColor]]; + [self.viewController.view.window addSubview:flashView]; + + [UIView + animateWithDuration:.4f + animations:^{ + [flashView setAlpha:0.f]; + } + completion:^(BOOL finished){ + [flashView removeFromSuperview]; + } + ]; +#endif + + + try { + // This will bring in multiple entities if there are multiple 2D codes in frame. + for (AVMetadataObject *metaData in metadataObjects) { + AVMetadataMachineReadableCodeObject* code = (AVMetadataMachineReadableCodeObject*)[self.previewLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject*)metaData]; + + if ([self checkResult:code.stringValue]) { + [self barcodeScanSucceeded:code.stringValue format:[self formatStringFromMetadata:code]]; + } + } + } + catch (...) { + // NSLog(@"decoding: unknown exception"); + // [self barcodeScanFailed:@"unknown exception decoding barcode"]; + } + + // NSTimeInterval timeElapsed = [NSDate timeIntervalSinceReferenceDate] - timeStart; + // NSLog(@"decoding completed in %dms", (int) (timeElapsed * 1000)); + +} + +//-------------------------------------------------------------------------- +// convert metadata object information to barcode format string +//-------------------------------------------------------------------------- +- (NSString*)formatStringFromMetadata:(AVMetadataMachineReadableCodeObject*)format { + if (format.type == AVMetadataObjectTypeQRCode) return @"QR_CODE"; + if (format.type == AVMetadataObjectTypeAztecCode) return @"AZTEC"; + if (format.type == AVMetadataObjectTypeDataMatrixCode) return @"DATA_MATRIX"; + if (format.type == AVMetadataObjectTypeUPCECode) return @"UPC_E"; + // According to Apple documentation, UPC_A is EAN13 with a leading 0. + if (format.type == AVMetadataObjectTypeEAN13Code && [format.stringValue characterAtIndex:0] == '0') return @"UPC_A"; + if (format.type == AVMetadataObjectTypeEAN8Code) return @"EAN_8"; + if (format.type == AVMetadataObjectTypeEAN13Code) return @"EAN_13"; + if (format.type == AVMetadataObjectTypeCode128Code) return @"CODE_128"; + if (format.type == AVMetadataObjectTypeCode93Code) return @"CODE_93"; + if (format.type == AVMetadataObjectTypeCode39Code) return @"CODE_39"; + if (format.type == AVMetadataObjectTypeInterleaved2of5Code) return @"ITF"; + if (format.type == AVMetadataObjectTypeITF14Code) return @"ITF_14"; + + if (format.type == AVMetadataObjectTypePDF417Code) return @"PDF_417"; + return @"???"; +} + +//-------------------------------------------------------------------------- +// convert string formats to metadata objects +//-------------------------------------------------------------------------- +- (NSArray*) formatObjectTypes { + NSArray *supportedFormats = nil; + if (self.formats != nil) { + supportedFormats = [self.formats componentsSeparatedByString:@","]; + } + + NSMutableArray * formatObjectTypes = [NSMutableArray array]; + + if (self.formats == nil || [supportedFormats containsObject:@"QR_CODE"]) [formatObjectTypes addObject:AVMetadataObjectTypeQRCode]; + if (self.formats == nil || [supportedFormats containsObject:@"AZTEC"]) [formatObjectTypes addObject:AVMetadataObjectTypeAztecCode]; + if (self.formats == nil || [supportedFormats containsObject:@"DATA_MATRIX"]) [formatObjectTypes addObject:AVMetadataObjectTypeDataMatrixCode]; + if (self.formats == nil || [supportedFormats containsObject:@"UPC_E"]) [formatObjectTypes addObject:AVMetadataObjectTypeUPCECode]; + if (self.formats == nil || [supportedFormats containsObject:@"EAN_8"]) [formatObjectTypes addObject:AVMetadataObjectTypeEAN8Code]; + if (self.formats == nil || [supportedFormats containsObject:@"EAN_13"]) [formatObjectTypes addObject:AVMetadataObjectTypeEAN13Code]; + if (self.formats == nil || [supportedFormats containsObject:@"CODE_128"]) [formatObjectTypes addObject:AVMetadataObjectTypeCode128Code]; + if (self.formats == nil || [supportedFormats containsObject:@"CODE_93"]) [formatObjectTypes addObject:AVMetadataObjectTypeCode93Code]; + if (self.formats == nil || [supportedFormats containsObject:@"CODE_39"]) [formatObjectTypes addObject:AVMetadataObjectTypeCode39Code]; + if (self.formats == nil || [supportedFormats containsObject:@"ITF"]) [formatObjectTypes addObject:AVMetadataObjectTypeInterleaved2of5Code]; + if (self.formats == nil || [supportedFormats containsObject:@"ITF_14"]) [formatObjectTypes addObject:AVMetadataObjectTypeITF14Code]; + if (self.formats == nil || [supportedFormats containsObject:@"PDF_417"]) [formatObjectTypes addObject:AVMetadataObjectTypePDF417Code]; + + return formatObjectTypes; +} + +@end + +//------------------------------------------------------------------------------ +// qr encoder processor +//------------------------------------------------------------------------------ +@implementation CDVqrProcessor +@synthesize plugin = _plugin; +@synthesize callback = _callback; +@synthesize stringToEncode = _stringToEncode; +@synthesize size = _size; + +- (id)initWithPlugin:(CDVBarcodeScanner*)plugin callback:(NSString*)callback stringToEncode:(NSString*)stringToEncode{ + self = [super init]; + if (!self) return self; + + self.plugin = plugin; + self.callback = callback; + self.stringToEncode = stringToEncode; + self.size = 300; + + return self; +} + +//-------------------------------------------------------------------------- +- (void)dealloc { + self.plugin = nil; + self.callback = nil; + self.stringToEncode = nil; +} +//-------------------------------------------------------------------------- +- (void)generateImage{ + /* setup qr filter */ + CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; + [filter setDefaults]; + + /* set filter's input message + * the encoding string has to be convert to a UTF-8 encoded NSData object */ + [filter setValue:[self.stringToEncode dataUsingEncoding:NSUTF8StringEncoding] + forKey:@"inputMessage"]; + + /* on ios >= 7.0 set low image error correction level */ + if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_7_0) + [filter setValue:@"L" forKey:@"inputCorrectionLevel"]; + + /* prepare cgImage */ + CIImage *outputImage = [filter outputImage]; + CIContext *context = [CIContext contextWithOptions:nil]; + CGImageRef cgImage = [context createCGImage:outputImage + fromRect:[outputImage extent]]; + + /* returned qr code image */ + UIImage *qrImage = [UIImage imageWithCGImage:cgImage + scale:1. + orientation:UIImageOrientationUp]; + /* resize generated image */ + CGFloat width = _size; + CGFloat height = _size; + + UIGraphicsBeginImageContext(CGSizeMake(width, height)); + + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGContextSetInterpolationQuality(ctx, kCGInterpolationNone); + [qrImage drawInRect:CGRectMake(0, 0, width, height)]; + qrImage = UIGraphicsGetImageFromCurrentImageContext(); + + /* clean up */ + UIGraphicsEndImageContext(); + CGImageRelease(cgImage); + + /* save image to file */ + NSString* fileName = [[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingString:@".jpg"]; + NSString* filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName]; + [UIImageJPEGRepresentation(qrImage, 1.0) writeToFile:filePath atomically:YES]; + + /* return file path back to cordova */ + [self.plugin returnImage:filePath format:@"QR_CODE" callback: self.callback]; +} +@end + +//------------------------------------------------------------------------------ +// view controller for the ui +//------------------------------------------------------------------------------ +@implementation CDVbcsViewController +@synthesize processor = _processor; +@synthesize shutterPressed = _shutterPressed; +@synthesize alternateXib = _alternateXib; +@synthesize overlayView = _overlayView; + +//-------------------------------------------------------------------------- +- (id)initWithProcessor:(CDVbcsProcessor*)processor alternateOverlay:(NSString *)alternateXib { + self = [super init]; + if (!self) return self; + + self.processor = processor; + self.shutterPressed = NO; + self.alternateXib = alternateXib; + self.overlayView = nil; + return self; +} + +//-------------------------------------------------------------------------- +- (void)dealloc { + self.view = nil; + self.processor = nil; + self.shutterPressed = NO; + self.alternateXib = nil; + self.overlayView = nil; +} + +//-------------------------------------------------------------------------- +- (void)loadView { + self.view = [[UIView alloc] initWithFrame: self.processor.parentViewController.view.frame]; +} + +//-------------------------------------------------------------------------- +- (void)viewWillAppear:(BOOL)animated { + + // set video orientation to what the camera sees + self.processor.previewLayer.connection.videoOrientation = (AVCaptureVideoOrientation) [[UIApplication sharedApplication] statusBarOrientation]; + + // this fixes the bug when the statusbar is landscape, and the preview layer + // starts up in portrait (not filling the whole view) + self.processor.previewLayer.frame = self.view.bounds; +} + +//-------------------------------------------------------------------------- +- (void)viewDidAppear:(BOOL)animated { + // setup capture preview layer + AVCaptureVideoPreviewLayer* previewLayer = self.processor.previewLayer; + previewLayer.frame = self.view.bounds; + previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; + + if ([previewLayer.connection isVideoOrientationSupported]) { + [previewLayer.connection setVideoOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; + } + + [self.view.layer insertSublayer:previewLayer below:[[self.view.layer sublayers] objectAtIndex:0]]; + + [self.view addSubview:[self buildOverlayView]]; + [self startCapturing]; + + [super viewDidAppear:animated]; +} + +//-------------------------------------------------------------------------- +- (void)startCapturing { + self.processor.capturing = YES; +} + +//-------------------------------------------------------------------------- +- (IBAction)shutterButtonPressed { + self.shutterPressed = YES; +} + +//-------------------------------------------------------------------------- +- (IBAction)cancelButtonPressed:(id)sender { + [self.processor performSelector:@selector(barcodeScanCancelled) withObject:nil afterDelay:0]; +} + +- (IBAction)flipCameraButtonPressed:(id)sender +{ + [self.processor performSelector:@selector(flipCamera) withObject:nil afterDelay:0]; +} + +- (IBAction)torchButtonPressed:(id)sender +{ + [self.processor performSelector:@selector(toggleTorch) withObject:nil afterDelay:0]; +} + +//-------------------------------------------------------------------------- +- (UIView *)buildOverlayViewFromXib +{ + [[NSBundle mainBundle] loadNibNamed:self.alternateXib owner:self options:NULL]; + + if ( self.overlayView == nil ) + { + NSLog(@"%@", @"An error occurred loading the overlay xib. It appears that the overlayView outlet is not set."); + return nil; + } + + self.overlayView.autoresizesSubviews = YES; + self.overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.overlayView.opaque = NO; + + CGRect bounds = self.view.bounds; + bounds = CGRectMake(0, 0, bounds.size.width, bounds.size.height); + + [self.overlayView setFrame:bounds]; + + return self.overlayView; +} + +//-------------------------------------------------------------------------- +- (UIView*)buildOverlayView { + + if ( nil != self.alternateXib ) + { + return [self buildOverlayViewFromXib]; + } + CGRect bounds = self.view.frame; + bounds = CGRectMake(0, 0, bounds.size.width, bounds.size.height); + + UIView* overlayView = [[UIView alloc] initWithFrame:bounds]; + overlayView.autoresizesSubviews = YES; + overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + overlayView.opaque = NO; + + self.toolbar = [[UIToolbar alloc] init]; + self.toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth; + + id cancelButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:(id)self + action:@selector(cancelButtonPressed:) + ]; + + + id flexSpace = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace + target:nil + action:nil + ]; + + id flipCamera = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemCamera + target:(id)self + action:@selector(flipCameraButtonPressed:) + ]; + + NSMutableArray *items; + +#if USE_SHUTTER + id shutterButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemCamera + target:(id)self + action:@selector(shutterButtonPressed) + ]; + + if (_processor.isShowFlipCameraButton) { + items = [NSMutableArray arrayWithObjects:flexSpace, cancelButton, flexSpace, flipCamera, shutterButton, nil]; + } else { + items = [NSMutableArray arrayWithObjects:flexSpace, cancelButton, flexSpace, shutterButton, nil]; + } +#else + if (_processor.isShowFlipCameraButton) { + items = [@[flexSpace, cancelButton, flexSpace, flipCamera] mutableCopy]; + } else { + items = [@[flexSpace, cancelButton, flexSpace] mutableCopy]; + } +#endif + + if (_processor.isShowTorchButton && !_processor.isFrontCamera) { + AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + if ([device hasTorch] && [device hasFlash]) { + NSURL *bundleURL = [[NSBundle mainBundle] URLForResource:@"CDVBarcodeScanner" withExtension:@"bundle"]; + NSBundle *bundle = [NSBundle bundleWithURL:bundleURL]; + NSString *imagePath = [bundle pathForResource:@"torch" ofType:@"png"]; + UIImage *image = [UIImage imageWithContentsOfFile:imagePath]; + + id torchButton = [[UIBarButtonItem alloc] + initWithImage:image + style:UIBarButtonItemStylePlain + target:(id)self + action:@selector(torchButtonPressed:) + ]; + + [items insertObject:torchButton atIndex:0]; + } + } + self.toolbar.items = items; + [overlayView addSubview: self.toolbar]; + + UIImage* reticleImage = [self buildReticleImage]; + self.reticleView = [[UIImageView alloc] initWithImage:reticleImage]; + + self.reticleView.opaque = NO; + self.reticleView.contentMode = UIViewContentModeScaleAspectFit; + self.reticleView.autoresizingMask = (UIViewAutoresizing) (0 + | UIViewAutoresizingFlexibleLeftMargin + | UIViewAutoresizingFlexibleRightMargin + | UIViewAutoresizingFlexibleTopMargin + | UIViewAutoresizingFlexibleBottomMargin) + ; + + [overlayView addSubview: self.reticleView]; + [self resizeElements]; + return overlayView; +} + +//-------------------------------------------------------------------------- + +#define RETICLE_SIZE 500.0f +#define RETICLE_WIDTH 10.0f +#define RETICLE_OFFSET 60.0f +#define RETICLE_ALPHA 0.4f + +//------------------------------------------------------------------------- +// builds the green box and red line +//------------------------------------------------------------------------- +- (UIImage*)buildReticleImage { + UIImage* result; + UIGraphicsBeginImageContext(CGSizeMake(RETICLE_SIZE, RETICLE_SIZE)); + CGContextRef context = UIGraphicsGetCurrentContext(); + + if (self.processor.is1D) { + UIColor* color = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:RETICLE_ALPHA]; + CGContextSetStrokeColorWithColor(context, color.CGColor); + CGContextSetLineWidth(context, RETICLE_WIDTH); + CGContextBeginPath(context); + CGFloat lineOffset = (CGFloat) (RETICLE_OFFSET+(0.5*RETICLE_WIDTH)); + CGContextMoveToPoint(context, lineOffset, RETICLE_SIZE/2); + CGContextAddLineToPoint(context, RETICLE_SIZE-lineOffset, (CGFloat) (0.5*RETICLE_SIZE)); + CGContextStrokePath(context); + } + + if (self.processor.is2D) { + UIColor* color = [UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:RETICLE_ALPHA]; + CGContextSetStrokeColorWithColor(context, color.CGColor); + CGContextSetLineWidth(context, RETICLE_WIDTH); + CGContextStrokeRect(context, + CGRectMake( + RETICLE_OFFSET, + RETICLE_OFFSET, + RETICLE_SIZE-2*RETICLE_OFFSET, + RETICLE_SIZE-2*RETICLE_OFFSET + ) + ); + } + + result = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return result; +} + +#pragma mark CDVBarcodeScannerOrientationDelegate + +- (BOOL)shouldAutorotate +{ + return YES; +} + +- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation +{ + return [[UIApplication sharedApplication] statusBarOrientation]; +} + +- (NSUInteger)supportedInterfaceOrientations +{ + return UIInterfaceOrientationMaskAll; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) { + return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation]; + } + + return YES; +} + +- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration +{ + [UIView setAnimationsEnabled:NO]; + AVCaptureVideoPreviewLayer* previewLayer = self.processor.previewLayer; + previewLayer.frame = self.view.bounds; + + if (orientation == UIInterfaceOrientationLandscapeLeft) { + [previewLayer setOrientation:AVCaptureVideoOrientationLandscapeLeft]; + } else if (orientation == UIInterfaceOrientationLandscapeRight) { + [previewLayer setOrientation:AVCaptureVideoOrientationLandscapeRight]; + } else if (orientation == UIInterfaceOrientationPortrait) { + [previewLayer setOrientation:AVCaptureVideoOrientationPortrait]; + } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { + [previewLayer setOrientation:AVCaptureVideoOrientationPortraitUpsideDown]; + } + + previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; + + [self resizeElements]; + [UIView setAnimationsEnabled:YES]; +} + +-(void) resizeElements { + CGRect bounds = self.view.bounds; + if (@available(iOS 11.0, *)) { + bounds = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, self.view.safeAreaLayoutGuide.layoutFrame.size.height+self.view.safeAreaLayoutGuide.layoutFrame.origin.y); + } + + [self.toolbar sizeToFit]; + CGFloat toolbarHeight = [self.toolbar frame].size.height; + CGFloat rootViewHeight = CGRectGetHeight(bounds); + CGFloat rootViewWidth = CGRectGetWidth(bounds); + CGRect rectArea = CGRectMake(0, rootViewHeight - toolbarHeight, rootViewWidth, toolbarHeight); + [self.toolbar setFrame:rectArea]; + + CGFloat minAxis = MIN(rootViewHeight, rootViewWidth); + + rectArea = CGRectMake( + (CGFloat) (0.5 * (rootViewWidth - minAxis)), + (CGFloat) (0.5 * (rootViewHeight - minAxis)), + minAxis, + minAxis + ); + + [self.reticleView setFrame:rectArea]; + self.reticleView.center = CGPointMake(self.view.center.x, self.view.center.y-self.toolbar.frame.size.height/2); +} + +@end diff --git a/src/ios/scannerOverlay.xib b/src/ios/scannerOverlay.xib new file mode 100644 index 0000000..765f2a8 --- /dev/null +++ b/src/ios/scannerOverlay.xib @@ -0,0 +1,185 @@ + + + + 1280 + 11C74 + 1938 + 1138.23 + 567.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 933 + + + IBUINavigationItem + IBUIBarButtonItem + IBUIView + IBUINavigationBar + IBProxyObject + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + + + 290 + {320, 44} + + + + _NS:260 + IBCocoaTouchFramework + 1 + + + + Barcode Scanner + + Cancel + IBCocoaTouchFramework + 1 + + + IBCocoaTouchFramework + + + + + {320, 460} + + + + + 3 + MSAwAA + + 2 + + + IBCocoaTouchFramework + + + + + + + overlayView + + + + 9 + + + + + + 0 + + + + + + 1 + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 3 + + + + + + + + 4 + + + + + + + + 10 + + + + + + + PGbcsViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 11 + + + + + PGbcsViewController + UIViewController + + overlayView + UIView + + + overlayView + + overlayView + UIView + + + + IBProjectSource + ./Classes/PGbcsViewController.h + + + + + 0 + IBCocoaTouchFramework + YES + 3 + 933 + + diff --git a/src/windows/BarcodeScannerProxy.js b/src/windows/BarcodeScannerProxy.js new file mode 100644 index 0000000..cea16d9 --- /dev/null +++ b/src/windows/BarcodeScannerProxy.js @@ -0,0 +1,738 @@ +/* + * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. + * + * 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. + */ + +var urlutil = require('cordova/urlutil'); + +var CAMERA_STREAM_STATE_CHECK_RETRY_TIMEOUT = 200; // milliseconds +var OPERATION_IS_IN_PROGRESS = -2147024567; +var REGDB_E_CLASSNOTREG = -2147221164; +var INITIAL_FOCUS_DELAY = 200; // milliseconds +var CHECK_PLAYING_TIMEOUT = 100; // milliseconds + +/** + * List of supported barcode formats from ZXing library. Used to return format + * name instead of number code as per plugin spec. + * + * @enum {String} + */ +var BARCODE_FORMAT = { + 1: 'AZTEC', + 2: 'CODABAR', + 4: 'CODE_39', + 8: 'CODE_93', + 16: 'CODE_128', + 32: 'DATA_MATRIX', + 64: 'EAN_8', + 128: 'EAN_13', + 256: 'ITF', + 512: 'MAXICODE', + 1024: 'PDF_417', + 2048: 'QR_CODE', + 4096: 'RSS_14', + 8192: 'RSS_EXPANDED', + 16384: 'UPC_A', + 32768: 'UPC_E', + 61918: 'All_1D', + 65536: 'UPC_EAN_EXTENSION', + 131072: 'MSI', + 262144: 'PLESSEY' +}; + +/** + * Detects the first appropriate camera located at the back panel of device. If + * there is no back cameras, returns the first available. + * + * @returns {Promise} Camera id + */ +function findCamera() { + var Devices = Windows.Devices.Enumeration; + + // Enumerate cameras and add them to the list + return Devices.DeviceInformation.findAllAsync(Devices.DeviceClass.videoCapture) + .then(function (cameras) { + + if (!cameras || cameras.length === 0) { + throw new Error("No cameras found"); + } + + var backCameras = cameras.filter(function (camera) { + return camera.enclosureLocation && camera.enclosureLocation.panel === Devices.Panel.back; + }); + + // If there is back cameras, return the id of the first, + // otherwise take the first available device's id + return (backCameras[0] || cameras[0]).id; + }); +} + +/** + * @param {Windows.Graphics.Display.DisplayOrientations} displayOrientation + * @return {Number} + */ +function videoPreviewRotationLookup(displayOrientation, isMirrored) { + var degreesToRotate; + + switch (displayOrientation) { + case Windows.Graphics.Display.DisplayOrientations.landscape: + degreesToRotate = 0; + break; + case Windows.Graphics.Display.DisplayOrientations.portrait: + if (isMirrored) { + degreesToRotate = 270; + } else { + degreesToRotate = 90; + } + break; + case Windows.Graphics.Display.DisplayOrientations.landscapeFlipped: + degreesToRotate = 180; + break; + case Windows.Graphics.Display.DisplayOrientations.portraitFlipped: + if (isMirrored) { + degreesToRotate = 90; + } else { + degreesToRotate = 270; + } + break; + default: + degreesToRotate = 0; + break; + } + + return degreesToRotate; +} + +/** + * The pure JS implementation of barcode reader from WinRTBarcodeReader.winmd. + * Works only on Windows 10 devices and more efficient than original one. + * + * @class {BarcodeReader} + */ +function BarcodeReader () { + this._promise = null; + this._cancelled = false; +} + +/** + * Returns an instance of Barcode reader, depending on capabilities of Media + * Capture API + * + * @static + * @constructs {BarcodeReader} + * + * @param {MediaCapture} mediaCaptureInstance Instance of + * Windows.Media.Capture.MediaCapture class + * + * @return {BarcodeReader} BarcodeReader instance that could be used for + * scanning + */ +BarcodeReader.get = function (mediaCaptureInstance) { + if (mediaCaptureInstance.getPreviewFrameAsync && ZXing.BarcodeReader) { + return new BarcodeReader(); + } + + // If there is no corresponding API (Win8/8.1/Phone8.1) use old approach with WinMD library + return new WinRTBarcodeReader.Reader(); + +}; + +/** + * Initializes instance of reader. + * + * @param {MediaCapture} capture Instance of + * Windows.Media.Capture.MediaCapture class, used for acquiring images/ video + * stream for barcode scanner. + * @param {Number} width Video/image frame width + * @param {Number} height Video/image frame height + */ +BarcodeReader.prototype.init = function (capture, width, height) { + this._capture = capture; + this._width = width; + this._height = height; + this._zxingReader = new ZXing.BarcodeReader(); + this._zxingReader.tryHarder = true; + + var formatsList = BarcodeReader.scanCallArgs.args.length > 0 && BarcodeReader.scanCallArgs.args[0].formats; + if (formatsList) { + var possibleFormats = formatsList + .split(",") + .map(format => { + for (var index in BARCODE_FORMAT) { + if (BARCODE_FORMAT[index] === format) { + return index; + } + } + }); + + this._zxingReader.possibleFormats = possibleFormats; + } +}; + +/** + * Starts barcode search routines asyncronously. + * + * @return {Promise} barcode scan result or null if search + * cancelled. + */ +BarcodeReader.prototype.readCode = function () { + + /** + * Grabs a frame from preview stream uning Win10-only API and tries to + * get a barcode using zxing reader provided. If there is no barcode + * found, returns null. + */ + function scanBarcodeAsync(mediaCapture, zxingReader, frameWidth, frameHeight) { + // Shortcuts for namespaces + var Imaging = Windows.Graphics.Imaging; + var Streams = Windows.Storage.Streams; + + var frame = new Windows.Media.VideoFrame(Imaging.BitmapPixelFormat.bgra8, frameWidth, frameHeight); + return mediaCapture.getPreviewFrameAsync(frame) + .then(function (capturedFrame) { + + // Copy captured frame to buffer for further deserialization + var bitmap = capturedFrame.softwareBitmap; + var rawBuffer = new Streams.Buffer(bitmap.pixelWidth * bitmap.pixelHeight * 4); + capturedFrame.softwareBitmap.copyToBuffer(rawBuffer); + capturedFrame.close(); + + // Get raw pixel data from buffer + var data = new Uint8Array(rawBuffer.length); + var dataReader = Streams.DataReader.fromBuffer(rawBuffer); + dataReader.readBytes(data); + dataReader.close(); + + return zxingReader.decode(data, frameWidth, frameHeight, ZXing.BitmapFormat.bgra32); + }); + } + + var self = this; + return scanBarcodeAsync(this._capture, this._zxingReader, this._width, this._height) + .then(function (result) { + if (self._cancelled) + return null; + + return result || (self._promise = self.readCode()); + }); +}; + +/** + * Stops barcode search + */ +BarcodeReader.prototype.stop = function () { + this._cancelled = true; +}; + +function degreesToRotation(degrees) { + switch (degrees) { + // portrait + case 90: + return Windows.Media.Capture.VideoRotation.clockwise90Degrees; + // landscape + case 0: + return Windows.Media.Capture.VideoRotation.none; + // portrait-flipped + case 270: + return Windows.Media.Capture.VideoRotation.clockwise270Degrees; + // landscape-flipped + case 180: + return Windows.Media.Capture.VideoRotation.clockwise180Degrees; + default: + // Falling back to portrait default + return Windows.Media.Capture.VideoRotation.clockwise90Degrees; + } +} + +module.exports = { + + /** + * Scans image via device camera and retieves barcode from it. + * @param {function} success Success callback + * @param {function} fail Error callback + * @param {array} args Arguments array + */ + scan: function (success, fail, args) { + var capturePreview, + capturePreviewAlignmentMark, + captureCancelButton, + navigationButtonsDiv, + previewMirroring, + closeButton, + capture, + reader; + + // Save call state for suspend/resume + BarcodeReader.scanCallArgs = { + success: success, + fail: fail, + args: args + }; + + function updatePreviewForRotation(evt) { + if (!capture) { + return; + } + + var displayInformation = (evt && evt.target) || Windows.Graphics.Display.DisplayInformation.getForCurrentView(); + var currentOrientation = displayInformation.currentOrientation; + + previewMirroring = capture.getPreviewMirroring(); + + // Lookup up the rotation degrees. + var rotDegree = videoPreviewRotationLookup(currentOrientation, previewMirroring); + + capture.setPreviewRotation(degreesToRotation(rotDegree)); + return WinJS.Promise.as(); + } + + /** + * Creates a preview frame and necessary objects + */ + function createPreview() { + + // Create fullscreen preview + var capturePreviewFrameStyle = document.createElement('link'); + capturePreviewFrameStyle.rel = "stylesheet"; + capturePreviewFrameStyle.type = "text/css"; + capturePreviewFrameStyle.href = urlutil.makeAbsolute("/www/css/plugin-barcodeScanner.css"); + + document.head.appendChild(capturePreviewFrameStyle); + + capturePreviewFrame = document.createElement('div'); + capturePreviewFrame.className = "barcode-scanner-wrap"; + + capturePreview = document.createElement("video"); + capturePreview.className = "barcode-scanner-preview"; + capturePreview.addEventListener('click', function () { + focus(); + }); + + capturePreviewAlignmentMark = document.createElement('div'); + capturePreviewAlignmentMark.className = "barcode-scanner-mark"; + + navigationButtonsDiv = document.createElement("div"); + navigationButtonsDiv.className = "barcode-scanner-app-bar"; + navigationButtonsDiv.onclick = function (e) { + e.cancelBubble = true; + }; + + closeButton = document.createElement("div"); + closeButton.innerText = "close"; + closeButton.className = "app-bar-action action-close"; + navigationButtonsDiv.appendChild(closeButton); + + BarcodeReader.scanCancelled = false; + closeButton.addEventListener("click", cancelPreview, false); + document.addEventListener('backbutton', cancelPreview, false); + + [capturePreview, capturePreviewAlignmentMark, navigationButtonsDiv].forEach(function (element) { + capturePreviewFrame.appendChild(element); + }); + } + + function focus(controller) { + + var result = WinJS.Promise.wrap(); + + if (!capturePreview || capturePreview.paused) { + // If the preview is not yet playing, there is no sense in running focus + return result; + } + + if (!controller) { + try { + controller = capture && capture.videoDeviceController; + } catch (err) { + console.log('Failed to access focus control for current camera: ' + err); + return result; + } + } + + if (!controller.focusControl || !controller.focusControl.supported) { + console.log('Focus control for current camera is not supported'); + return result; + } + + // Multiple calls to focusAsync leads to internal focusing hang on some Windows Phone 8.1 devices + // Also need to wrap in try/catch to avoid crash on Surface 3 - looks like focusState property + // somehow is not accessible there. See https://github.com/phonegap/phonegap-plugin-barcodescanner/issues/288 + try { + if (controller.focusControl.focusState === Windows.Media.Devices.MediaCaptureFocusState.searching) { + return result; + } + } catch (e) { + // Nothing to do - just continue w/ focusing + } + + // The delay prevents focus hang on slow devices + return WinJS.Promise.timeout(INITIAL_FOCUS_DELAY) + .then(function () { + try { + return controller.focusControl.focusAsync().then(function () { + return result; + }, function (e) { + // This happens on mutliple taps + if (e.number !== OPERATION_IS_IN_PROGRESS) { + console.error('focusAsync failed: ' + e); + return WinJS.Promise.wrapError(e); + } + return result; + }); + } catch (e) { + // This happens on mutliple taps + if (e.number !== OPERATION_IS_IN_PROGRESS) { + console.error('focusAsync failed: ' + e); + return WinJS.Promise.wrapError(e); + } + return result; + } + }); + } + + function setupFocus(focusControl) { + + function supportsFocusMode(mode) { + return focusControl.supportedFocusModes.indexOf(mode).returnValue; + } + + if (!focusControl || !focusControl.supported || !focusControl.configure) { + return WinJS.Promise.wrap(); + } + + var FocusMode = Windows.Media.Devices.FocusMode; + var focusConfig = new Windows.Media.Devices.FocusSettings(); + focusConfig.autoFocusRange = Windows.Media.Devices.AutoFocusRange.normal; + + // Determine a focus position if the focus search fails: + focusConfig.disableDriverFallback = false; + + if (supportsFocusMode(FocusMode.continuous)) { + console.log("Device supports continuous focus mode"); + focusConfig.mode = FocusMode.continuous; + } else if (supportsFocusMode(FocusMode.auto)) { + console.log("Device doesn\'t support continuous focus mode, switching to autofocus mode"); + focusConfig.mode = FocusMode.auto; + } + + focusControl.configure(focusConfig); + + // Continuous focus should start only after preview has started. See 'Remarks' at + // https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.devices.focuscontrol.configure.aspx + function waitForIsPlaying() { + var isPlaying = !capturePreview.paused && !capturePreview.ended && capturePreview.readyState > 2; + + if (!isPlaying) { + return WinJS.Promise.timeout(CHECK_PLAYING_TIMEOUT) + .then(function () { + return waitForIsPlaying(); + }); + } + + return focus(); + } + + return waitForIsPlaying(); + } + + function disableZoomAndScroll() { + document.body.classList.add('no-zoom'); + document.body.classList.add('no-scroll'); + } + + function enableZoomAndScroll() { + document.body.classList.remove('no-zoom'); + document.body.classList.remove('no-scroll'); + } + + /** + * Starts stream transmission to preview frame and then run barcode search + */ + function startPreview() { + return findCamera() + .then(function (id) { + var captureSettings; + + try { + captureSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings(); + } catch (e) { + if (e.number === REGDB_E_CLASSNOTREG) { + throw new Error('Ensure that you have Windows Media Player and Media Feature pack installed.'); + } + + throw e; + } + + captureSettings.streamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.video; + captureSettings.photoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.videoPreview; + captureSettings.videoDeviceId = id; + + capture = new Windows.Media.Capture.MediaCapture(); + return capture.initializeAsync(captureSettings); + }) + .then(function () { + + var controller = capture.videoDeviceController; + var deviceProps = controller.getAvailableMediaStreamProperties(Windows.Media.Capture.MediaStreamType.videoPreview); + + deviceProps = Array.prototype.slice.call(deviceProps); + deviceProps = deviceProps.filter(function (prop) { + // filter out streams with "unknown" subtype - causes errors on some devices + return prop.subtype !== "Unknown"; + }).sort(function (propA, propB) { + // sort properties by resolution + return propB.width - propA.width; + }); + + var preferredProps = deviceProps.filter(function(prop){ + // Filter out props where frame size is between 640*480 and 1280*720 + return prop.width >= 640 && prop.height >= 480 && prop.width <= 1280 && prop.height <= 720; + }); + + // prefer video frame size between between 640*480 and 1280*720 + // use maximum resolution otherwise + var maxResProps = preferredProps[0] || deviceProps[0]; + return controller.setMediaStreamPropertiesAsync(Windows.Media.Capture.MediaStreamType.videoPreview, maxResProps) + .then(function () { + return { + capture: capture, + width: maxResProps.width, + height: maxResProps.height + }; + }); + }) + .then(function (captureSettings) { + + capturePreview.msZoom = true; + capturePreview.src = URL.createObjectURL(capture); + capturePreview.play(); + + // Insert preview frame and controls into page + document.body.appendChild(capturePreviewFrame); + + disableZoomAndScroll(); + + return setupFocus(captureSettings.capture.videoDeviceController.focusControl) + .then(function () { + Windows.Graphics.Display.DisplayInformation.getForCurrentView().addEventListener("orientationchanged", updatePreviewForRotation, false); + return updatePreviewForRotation(); + }) + .then(function () { + + if (!Windows.Media.Devices.CameraStreamState) { + // CameraStreamState is available starting with Windows 10 so skip this check for 8.1 + // https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.devices.camerastreamstate + return WinJS.Promise.as(); + } + + function checkCameraStreamState() { + if (capture.cameraStreamState !== Windows.Media.Devices.CameraStreamState.streaming) { + + // Using loop as MediaCapture.CameraStreamStateChanged does not fire with CameraStreamState.streaming state. + return WinJS.Promise.timeout(CAMERA_STREAM_STATE_CHECK_RETRY_TIMEOUT) + .then(function () { + return checkCameraStreamState(); + }); + } + + return WinJS.Promise.as(); + } + + // Ensure CameraStreamState is Streaming + return checkCameraStreamState(); + }) + .then(function () { + return captureSettings; + }); + }); + } + + /** + * Removes preview frame and corresponding objects from window + */ + function destroyPreview() { + var promise = WinJS.Promise.as(); + + Windows.Graphics.Display.DisplayInformation.getForCurrentView().removeEventListener("orientationchanged", updatePreviewForRotation, false); + document.removeEventListener('backbutton', cancelPreview); + + if (capturePreview) { + var isPlaying = !capturePreview.paused && !capturePreview.ended && capturePreview.readyState > 2; + if (isPlaying) { + capturePreview.pause(); + } + + // http://stackoverflow.com/a/28060352/4177762 + capturePreview.src = ""; + if (capturePreview.load) { + capturePreview.load(); + } + } + + if (capturePreviewFrame) { + try { + document.body.removeChild(capturePreviewFrame); + } catch (e) { + // Catching NotFoundError + console.error(e); + } + } + capturePreviewFrame = null; + + reader && reader.stop(); + reader = null; + + if (capture) { + try { + promise = capture.stopRecordAsync(); + } catch (e) { + // Catching NotFoundError + console.error(e); + } + } + capture = null; + + enableZoomAndScroll(); + + return promise; + } + + /** + * Stops preview and then call success callback with cancelled=true + * See https://github.com/phonegap-build/BarcodeScanner#using-the-plugin + */ + function cancelPreview() { + BarcodeReader.scanCancelled = true; + reader && reader.stop(); + } + + function checkCancelled() { + if (BarcodeReader.scanCancelled || BarcodeReader.suspended) { + throw new Error('Canceled'); + } + } + + // Timeout is needed so that the .done finalizer below can be attached to the promise. + BarcodeReader.scanPromise = WinJS.Promise.timeout() + .then(function() { + createPreview(); + checkCancelled(); + return startPreview(); + }) + .then(function (captureSettings) { + checkCancelled(); + reader = BarcodeReader.get(captureSettings.capture); + reader.init(captureSettings.capture, captureSettings.width, captureSettings.height); + + // Add a small timeout before capturing first frame otherwise + // we would get an 'Invalid state' error from 'getPreviewFrameAsync' + return WinJS.Promise.timeout(200) + .then(function () { + checkCancelled(); + return reader.readCode(); + }); + }) + .then(function (result) { + // Suppress null result (cancel) on suspending + if (BarcodeReader.suspended) { + return; + } + + destroyPreview(); + success({ + text: result && result.text, + format: result && BARCODE_FORMAT[result.barcodeFormat], + cancelled: !result + }); + }); + + // Catching any errors here + BarcodeReader.scanPromise.done(function () { }, function (error) { + // Suppress null result (cancel) on suspending + if (BarcodeReader.suspended) { + return; + } + + destroyPreview(); + if (error.message == 'Canceled') { + success({ + cancelled: true + }); + } else { + fail(error); + } + }); + + BarcodeReader.videoPreviewIsVisible = function () { + return capturePreviewFrame !== null; + } + + BarcodeReader.destroyPreview = destroyPreview; + }, + + /** + * Encodes specified data into barcode + * @param {function} success Success callback + * @param {function} fail Error callback + * @param {array} args Arguments array + */ + encode: function (success, fail, args) { + fail("Not implemented yet"); + } +}; + +var app = WinJS.Application; + +function waitForScanEnd() { + return BarcodeReader.scanPromise || WinJS.Promise.as(); +} + +function suspend(args) { + BarcodeReader.suspended = true; + if (args) { + args.setPromise(BarcodeReader.destroyPreview() + .then(waitForScanEnd, waitForScanEnd)); + } else { + BarcodeReader.destroyPreview(); + } +} + +function resume() { + BarcodeReader.suspended = false; + module.exports.scan(BarcodeReader.scanCallArgs.success, BarcodeReader.scanCallArgs.fail, BarcodeReader.scanCallArgs.args); +} + +function onVisibilityChanged() { + if (document.visibilityState === 'hidden' + && BarcodeReader.videoPreviewIsVisible && BarcodeReader.videoPreviewIsVisible() && BarcodeReader.destroyPreview) { + suspend(); + } else if (BarcodeReader.suspended) { + resume(); + } +} + +// Windows 8.1 projects +document.addEventListener('msvisibilitychange', onVisibilityChanged); +// Windows 10 projects +document.addEventListener('visibilitychange', onVisibilityChanged); + +// About to be suspended +app.addEventListener('checkpoint', function (args) { + if (BarcodeReader.videoPreviewIsVisible && BarcodeReader.videoPreviewIsVisible() && BarcodeReader.destroyPreview) { + suspend(args); + } +}); + +// Resuming from a user suspension +Windows.UI.WebUI.WebUIApplication.addEventListener("resuming", function () { + if (BarcodeReader.suspended) { + resume(); + } +}, false); + +require("cordova/exec/proxy").add("BarcodeScanner", module.exports); diff --git a/src/windows/assets/plugin-barcodeScanner.css b/src/windows/assets/plugin-barcodeScanner.css new file mode 100644 index 0000000..e990703 --- /dev/null +++ b/src/windows/assets/plugin-barcodeScanner.css @@ -0,0 +1,89 @@ +.barcode-scanner-wrap { + margin: 0; + padding: 0; + outline: 0; + font-size: 100%; + vertical-align: baseline; + background: 0 0 black; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 9999999; + -ms-user-select: none; +} + +.barcode-scanner-preview { + width: auto; + height: calc(100% - 70px); + position: absolute; + top: calc(50% - 35px); + left: 50%; + transform: translateX(-50%) translateY(-50%); +} + +.barcode-scanner-mark { + position: absolute; + left: 0; + top: 50%; + width: 100%; + height: 3px; + background: red; + z-index: 9999999; +} + +.barcode-scanner-app-bar { + height: 70px; + width: 100%; + padding-top: 10px; + z-index: 9999999; + text-align: center; + user-select: none; + position: absolute; + bottom: 0px; +} + +.app-bar-action { + width: 40px; + height: 40px; + margin: 0 auto; + font-family: "Segoe UI Symbol"; + color: white; + font-size: 12px; + text-transform: lowercase; + text-align: center; + cursor: default; +} + +@media all and (orientation: landscape) { + .app-bar-action { + float: right; + margin-right: 20px; + } +} + +.app-bar-action::before { + font-size: 28px; + display: block; + height: 36px; +} + +.action-close::before { + content: "\E0C7"; + /* close icon is larger so we re-size it to fit other icons */ + font-size: 20px; + line-height: 40px; +} + +.action-close:hover::before { + content: "\E0CA"; +} + +.no-zoom { + -ms-content-zooming: none; +} + +.no-scroll { + overflow: hidden; +} diff --git a/src/windows/lib.UW/ANY/ZXing.winmd b/src/windows/lib.UW/ANY/ZXing.winmd new file mode 100644 index 0000000..f8d3a68 Binary files /dev/null and b/src/windows/lib.UW/ANY/ZXing.winmd differ diff --git a/src/windows/lib.UW/ARM/ZXing.winmd b/src/windows/lib.UW/ARM/ZXing.winmd new file mode 100644 index 0000000..173b0cc Binary files /dev/null and b/src/windows/lib.UW/ARM/ZXing.winmd differ diff --git a/src/windows/lib.UW/x64/ZXing.winmd b/src/windows/lib.UW/x64/ZXing.winmd new file mode 100644 index 0000000..1f4cca0 Binary files /dev/null and b/src/windows/lib.UW/x64/ZXing.winmd differ diff --git a/src/windows/lib.UW/x86/ZXing.winmd b/src/windows/lib.UW/x86/ZXing.winmd new file mode 100644 index 0000000..e785f95 Binary files /dev/null and b/src/windows/lib.UW/x86/ZXing.winmd differ diff --git a/src/windows/lib/Properties/AssemblyInfo.cs b/src/windows/lib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4ee65dd --- /dev/null +++ b/src/windows/lib/Properties/AssemblyInfo.cs @@ -0,0 +1,39 @@ +/* + * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. + * + * 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. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WinRTBarcodeReader")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WinRTBarcodeReader")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/src/windows/lib/Reader.cs b/src/windows/lib/Reader.cs new file mode 100644 index 0000000..4a11938 --- /dev/null +++ b/src/windows/lib/Reader.cs @@ -0,0 +1,173 @@ +/* + * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. + * + * 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. + */ + +namespace WinRTBarcodeReader +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + using Windows.Foundation; + using Windows.Graphics.Imaging; + using Windows.Media.Capture; + using Windows.Media.MediaProperties; + using Windows.Storage.Streams; + + using ZXing; + + /// + /// Defines the Reader type, that perform barcode search asynchronously. + /// + public sealed class Reader + { + #region Private fields + + /// + /// Data reader, used to create bitmap array. + /// + private BarcodeReader barcodeReader; + + /// + /// The cancel search flag. + /// + private CancellationTokenSource cancelSearch; + + /// + /// MediaCapture instance, used for barcode search. + /// + private MediaCapture capture; + + /// + /// Encoding properties for mediaCapture object. + /// + private ImageEncodingProperties encodingProps; + + /// + /// Flag that indicates successful barcode search. + /// + private bool barcodeFoundOrCancelled; + + /// + /// Image stream for MediaCapture content. + /// + private InMemoryRandomAccessStream imageStream; + + #endregion + + #region Constructor + + /// + /// Initializes a new instance of the class. + /// + /// MediaCapture instance. + /// Capture frame width. + /// Capture frame height. + public void Init(MediaCapture capture, uint width, uint height) + { + this.capture = capture; + encodingProps = ImageEncodingProperties.CreateJpeg(); + encodingProps.Width = width; + encodingProps.Height = height; + + barcodeReader = new BarcodeReader {Options = {TryHarder = true}}; + cancelSearch = new CancellationTokenSource(); + } + + #endregion + + #region Public methods + + /// + /// Perform async MediaCapture analysis and searches for barcode. + /// + /// IAsyncOperation object + public IAsyncOperation ReadCode() + { + return this.Read().AsAsyncOperation(); + } + + /// + /// Send signal to stop barcode search. + /// + public void Stop() + { + this.cancelSearch.Cancel(); + } + + #endregion + + #region Private methods + + /// + /// Perform async MediaCapture analysis and searches for barcode. + /// + /// Task object + private async Task Read() + { + Result result = null; + try + { + while (result == null) + { + result = await GetCameraImage(cancelSearch.Token); + } + } + catch (OperationCanceledException) { } + + return result; + } + + /// + /// Perform image capture from mediaCapture object + /// + /// + /// The cancel Token. + /// + /// + /// Decoded barcode string. + /// + private async Task GetCameraImage(CancellationToken cancelToken) + { + if (cancelToken.IsCancellationRequested) + { + throw new OperationCanceledException(cancelToken); + } + + imageStream = new InMemoryRandomAccessStream(); + + await capture.CapturePhotoToStreamAsync(encodingProps, imageStream); + await imageStream.FlushAsync(); + + var decoder = await BitmapDecoder.CreateAsync(imageStream); + + byte[] pixels = + (await + decoder.GetPixelDataAsync(BitmapPixelFormat.Rgba8, + BitmapAlphaMode.Ignore, + new BitmapTransform(), + ExifOrientationMode.IgnoreExifOrientation, + ColorManagementMode.DoNotColorManage)).DetachPixelData(); + + const BitmapFormat format = BitmapFormat.RGB32; + + imageStream.Dispose(); + + var result = + await + Task.Run( + () => barcodeReader.Decode(pixels, (int) decoder.PixelWidth, (int) decoder.PixelHeight, format), + cancelToken); + + return result; + } + + #endregion + } +} diff --git a/src/windows/lib/WinRTBarcodeReader.csproj b/src/windows/lib/WinRTBarcodeReader.csproj new file mode 100644 index 0000000..7d3c2b3 --- /dev/null +++ b/src/windows/lib/WinRTBarcodeReader.csproj @@ -0,0 +1,137 @@ + + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + WinRTBarcodeReader + {01412F36-3781-4AF0-903C-ACEA7552C99C} + winmdobj + Properties + WinRTBarcodeReader + WinRTBarcodeReader + en-US + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 8.1 + 12 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE + prompt + 4 + + + false + None + true + bin\Release\ + TRACE;NETFX_CORE + prompt + 4 + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE + true + ;2008 + false + None + ARM + false + prompt + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;NETFX_CORE + true + ;2008 + false + None + x64 + false + prompt + true + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE + true + ;2008 + false + None + x86 + false + prompt + true + + + + + + + + ZXing.winmd + + + + 12.0 + + + + \ No newline at end of file diff --git a/src/windows/lib/ZXing.winmd b/src/windows/lib/ZXing.winmd new file mode 100644 index 0000000..ea21bd7 Binary files /dev/null and b/src/windows/lib/ZXing.winmd differ diff --git a/www/barcodescanner.js b/www/barcodescanner.js new file mode 100644 index 0000000..f9bba2b --- /dev/null +++ b/www/barcodescanner.js @@ -0,0 +1,156 @@ +/** + * cordova is available under the MIT License (2008). + * See http://opensource.org/licenses/alphabetical for full text. + * + * Copyright (c) Matt Kane 2010 + * Copyright (c) 2011, IBM Corporation + * Copyright (c) 2012-2017, Adobe Systems + */ + + + var exec = cordova.require("cordova/exec"); + + var scanInProgress = false; + + /** + * Constructor. + * + * @returns {BarcodeScanner} + */ + function BarcodeScanner() { + + /** + * Encoding constants. + * + * @type Object + */ + this.Encode = { + TEXT_TYPE: "TEXT_TYPE", + EMAIL_TYPE: "EMAIL_TYPE", + PHONE_TYPE: "PHONE_TYPE", + SMS_TYPE: "SMS_TYPE" + // CONTACT_TYPE: "CONTACT_TYPE", // TODO: not implemented, requires passing a Bundle class from Javascript to Java + // LOCATION_TYPE: "LOCATION_TYPE" // TODO: not implemented, requires passing a Bundle class from Javascript to Java + }; + + /** + * Barcode format constants, defined in ZXing library. + * + * @type Object + */ + this.format = { + "all_1D": 61918, + "aztec": 1, + "codabar": 2, + "code_128": 16, + "code_39": 4, + "code_93": 8, + "data_MATRIX": 32, + "ean_13": 128, + "ean_8": 64, + "itf": 256, + "maxicode": 512, + "msi": 131072, + "pdf_417": 1024, + "plessey": 262144, + "qr_CODE": 2048, + "rss_14": 4096, + "rss_EXPANDED": 8192, + "upc_A": 16384, + "upc_E": 32768, + "upc_EAN_EXTENSION": 65536 + }; + } + +/** + * Read code from scanner. + * + * @param {Function} successCallback This function will recieve a result object: { + * text : '12345-mock', // The code that was scanned. + * format : 'FORMAT_NAME', // Code format. + * cancelled : true/false, // Was canceled. + * } + * @param {Function} errorCallback + * @param config + */ +BarcodeScanner.prototype.scan = function (successCallback, errorCallback, config) { + + if (config instanceof Array) { + // do nothing + } else { + if (typeof(config) === 'object') { + // string spaces between formats, ZXing does not like that + if (config.formats) { + config.formats = config.formats.replace(/\s+/g, ''); + } + config = [ config ]; + } else { + config = []; + } + } + + if (errorCallback == null) { + errorCallback = function () { + }; + } + + if (typeof errorCallback != "function") { + console.log("BarcodeScanner.scan failure: failure parameter not a function"); + return; + } + + if (typeof successCallback != "function") { + console.log("BarcodeScanner.scan failure: success callback parameter must be a function"); + return; + } + + if (scanInProgress) { + errorCallback('Scan is already in progress'); + return; + } + + scanInProgress = true; + + exec( + function(result) { + scanInProgress = false; + // work around bug in ZXing library + if (result.format === 'UPC_A' && result.text.length === 13) { + result.text = result.text.substring(1); + } + successCallback(result); + }, + function(error) { + scanInProgress = false; + errorCallback(error); + }, + 'BarcodeScanner', + 'scan', + config + ); + }; + + //------------------------------------------------------------------- + BarcodeScanner.prototype.encode = function (type, data, successCallback, errorCallback, options) { + if (errorCallback == null) { + errorCallback = function () { + }; + } + + if (typeof errorCallback != "function") { + console.log("BarcodeScanner.encode failure: failure parameter not a function"); + return; + } + + if (typeof successCallback != "function") { + console.log("BarcodeScanner.encode failure: success callback parameter must be a function"); + return; + } + + exec(successCallback, errorCallback, 'BarcodeScanner', 'encode', [ + {"type": type, "data": data, "options": options} + ]); + }; + + var barcodeScanner = new BarcodeScanner(); + module.exports = barcodeScanner;