bitpay / cordova-plugin-qrscanner

A fast, energy efficient, highly-configurable QR code scanner for Cordova apps and the browser.
MIT License
568 stars 772 forks source link

Add android platform #9

Closed rocketman-21 closed 7 years ago

tobiasviehweger commented 7 years ago

@willhay Very interested in this, just started working on this today. I'm quite new to Cordova plugins, but willing to read up on stuff, in case you need some help :)

rocketman-21 commented 7 years ago

@tobiasviehweger Great to hear! Just committed the rest of my changes. Most of the methods should now be working besides the scan methods. Currently, QRScanner.java uses the old android.Camera API and it works on old and new devices very well. I think the next step will be to use the camera2 API for newer devices as well as add the scan methods.

tobiasviehweger commented 7 years ago

So I just looked into the best way to read QR codes, and it seems the xzing lib is the way to go. The official phonegap-barcode-scanner is just a wrapper around it as well.

The question is though, if it might make sense to just use https://github.com/journeyapps/zxing-android-embedded, also for the CameraPreview (using BarcodeView) class. By default they support SurfaceView and TextureView, according to this page might be a better option on newer versions.

I'll play around with this a little...

tobiasviehweger commented 7 years ago

This is how I'd imagine it: https://github.com/tobiasviehweger/cordova-plugin-qrscanner/commit/afb730a7dd4271b2caa2bfe0bafa05455eb64bd1

I'm just setting up some test project now to see if everything works..

rocketman-21 commented 7 years ago

Looks great, testing it out now as well.

tobiasviehweger commented 7 years ago

So there was something small missing (starting the actual preview), I've just added that. //Edit nevermind, it works when you set the background-color to transparent in HTML

@bitjson Btw. I have nothing to test the iOS version on, but how exactly is the behavior there? Is the camera shown full screen, with a semitransparent webview? Would it be an option to specify a rect in the future, so that you could render it non-fullscreen?

rocketman-21 commented 7 years ago

image1 @tobiasviehweger

tobiasviehweger commented 7 years ago

Ah thanks. So the image preview is already working for me. I'll check on a real device tomorrow if the QR code is also recognized. clipboard01

rocketman-21 commented 7 years ago

@tobiasviehweger Just fixed a few things. Trying to get the scan function working now. I'm getting a "java.lang.IllegalStateException: Must be called from the main thread." error on mBarcodeView.decodeSingle(this) (line 448). Same error I was getting for pause/resumePreview. Looking into it now. //Edit - fixed

rocketman-21 commented 7 years ago

@tobiasviehweger Everything seems to be working except the scan() (pause, vibrate). It will pause but there is no vibration. This might be a problem with cordova-plugin-vibration, not sure yet. (Line 169 on tests.js has the vibrate function). Testing on a nexus 6P right now and everything looks good besides that. About to test on samsung S3 and S4. //Edit - S4 worked fine. On the S3 (Android Version 4.1.2), most of the methods don't work. Prepared returns status.prepared = false. Show and Hide work. Scan, light, and resume/pause don't work since the camera preview won't start. Looking into this now.

bitjson commented 7 years ago

Hey @tobiasviehweger – thanks for your help! This is looking great.

@bitjson Btw. I have nothing to test the iOS version on, but how exactly is the behavior there? Is the camera shown full screen, with a semitransparent webview?

Yep – the iOS platform renders the camera preview behind the webview, and then makes the webview's background transparent. So it's possible to see the whole camera view by making the webview contents transparent, or to obscure parts and add controls/buttons over the view with HTML/CSS. You can try the browser platform for a good idea of the iOS implementation.

Would it be an option to specify a rect in the future, so that you could render it non-fullscreen?

A configurable rect is certainly something we could reconsider. I'd looked at doing that before, but I concluded that it would complicate the API and implementation significantly, without providing much additional functionality.

Particularly for mobile devices, attached cameras are well designed (and optimized) to take and display video on the device's entire screen.

Other rect sizes/ratios would require clipping or distorting the video in order to display the whole image. I don't think we ever want to distort video, and in cases where we want to clip/mask parts of it, we still want to be searching for QR codes across the entire video input. So it makes sense to "crop" the video at the webview layer (by covering it with HTML/CSS interface elements) rather than via an additional native interface.

Does that make sense? Is there another use case you'd like to accommodate with it?

tobiasviehweger commented 7 years ago

@willhay Thanks for testing and fixing so thoroughly! The only device available to me currently is the Huawei P8 Lite (running 5.0.1). The current version really worked great on that device! The QR code was almost recognized instantly and the preview image was smooth :) I'll see if I can organize some more phones to test on, that might take a while though.

I'll see if I can find some time to look into the vibration thing next week, in case you haven't been successful already ;)

@bitjson Makes sense. I understood now how everything works and it's a good option for me - I had feared that the content of the web view might be somewhat transparent as well, but as they aren't, this solution is working quite nicely - the less code used, the less can go wrong ;)

tobiasviehweger commented 7 years ago

@willhay Just found this issue, maybe it's just the permission missing? https://github.com/journeyapps/zxing-android-embedded/issues/182

rocketman-21 commented 7 years ago

@tobiasviehweger Looks like the plugin (cordova plugin vibration) is automatically adding the permission to AndroidManifest.xml so I don't think permissions is the problem. I tried making my own vibrate function which worked fine, not sure what's up. I checked out the readme for the cordova plugin vibration and couldn't find anything either. //Edit - Scanning area seems small. I have to put the qrcode at least a foot from the camera for it to scan. This talks about scaling the scanning area. Looking into it now.

tobiasviehweger commented 7 years ago

Hm interesting. When I tested it on the Huawei I didn't experience that. I guess the QR filled at least 2/3 of the screen and worked quite well. Maybe it's really a scaling thing. Does this happen on all your devices?

rocketman-21 commented 7 years ago

Edit// Seems to be working fine now if I tilt the camera at a slight angle towards the QR Code. Android version is marginally slower than the iOS version when scanning.

Strange. At this distance it works great: screenshot_20160729-135152

But when you get as close as this it doesn't ever work, just says scanning... forever: screenshot_20160729-135353

Happens on both the Nexus 6P and Galaxy S4.

tobiasviehweger commented 7 years ago

@willhay Thanks for the continued dev. I tested on a Samsung Galaxy A3 today, also worked quite well, though I noticed as well that it does not work if the QR code fills the whole screen. I don't think that's an issue, because having a rect like this in the app is quite common, and it worked even larger than that for me.

rocketman-21 commented 7 years ago

@tobiasviehweger No problem, thanks for testing on more devices. I also don't think its a big issue but I'm still looking into whether or not I can/should change the size of the scanning area.

rocketman-21 commented 7 years ago

The prepare function isn't working on a Galaxy S3 (Android 4.1.2). Looking into it now

rocketman-21 commented 7 years ago

@tobiasviehweger If you restart the test app and click the scan() button in Manual Tests, it won't detect the qrcode or return the data. Click scan() again and it scans and returns fine. If you click prepare() first, then scan(), it detects the qr-code as well. So if you call scan() as your first method call it will not scan. Not sure why this happens. Edit// think I fixed it

rocketman-21 commented 7 years ago

Plugin working on Galaxy S3 now. I think it wasn't working before because the hasCamera() method used hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)). It uses hasSystemFeature(PackageManager.FEATURE_CAMERA)) now and it prepares the camera preview and scans just fine.

tobiasviehweger commented 7 years ago

@willhay Awesome! Could you remove this line, I think it got committed by accident: import com.google.android.gms.games.quest.QuestRef;

Thanks =)

rocketman-21 commented 7 years ago

Fixed a lot of stuff. Only issue I can see right now is the scan with pause and vibrate won't vibrate. Trying to fix it now, any ideas whats up? @tobiasviehweger Edit// Phone I was testing on was on Do Not Disturb so it wasn't vibrating... Don't think it's an issue anymore

tobiasviehweger commented 7 years ago

@willhay Great to hear that, sorry for coming back late. Unfortunately I'll be on vacation for the next two weeks, so no testing from my side. But my latest tests still look very promising..

@bitjson What would be the next steps for getting this one merged?

bitjson commented 7 years ago

This is looking great, awesome work guys. @willhay and I just went through some of the final work that needs to be done before this is ready for release. We just need to solve a few more bugs, then a little housekeeping before it's merged. We'll squash out commits labeled fix which are not bug fixes for problems with released code, and add breaking change information to the commits that cause the breaks.

Since this has breaking API changes, it will be released as v3.0.0, hopefully tomorrow morning.

rocketman-21 commented 7 years ago

@tobiasviehweger The scanner only detects the QR Code if it's in the middle of the screen. For example, if you position the camera so that the QRCode is in the upper right corner of the BarcodeView preview, the QR Code will not be detected. Once you move the camera so the QR Code is in the middle, it detects it instantly. Do you have any idea how we can change the scanning area to take up as much of the camera preview as possible?

rocketman-21 commented 7 years ago

Closing in favor of https://github.com/bitpay/cordova-plugin-qrscanner/pull/16