bitpay / cordova-plugin-qrscanner

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

iOS 15.4 camera preview not showed #371

Open fabioz23 opened 2 years ago

fabioz23 commented 2 years ago

Hi all,

i'm experiencing a problem, on iOS 15.4 the camera preview is not showing, black screen and green dot on status bar. So the camera is used and QR recognition works. The same code on iOS 15.3.1 work fine (and also on Android devices).

I've tried also @v1934 version: https://github.com/v1934/cordova-plugin-qrscanner-11 experiencing the same problem.

What are the changes on Safari Webkit that doesn't allow to make transparent the web content and show the live camera feed?

v1934 commented 2 years ago

Weird, I have tested it on a device with iOS 15.4 and it works fine, also on 15.2. Are you using the wkwebview plugin? If yes then maybe that's the cause for different behaviour.

Try executing QRScanner.show() and QRscanner.hide() manually in safari debugging when camera is turned on. On Android 10+ these two methods were reversed because of some change in Android

fabioz23 commented 2 years ago

Schermata 2022-03-22 alle 16 54 43

this is what i see on screen: Schermata 2022-03-22 alle 16 55 30

I've tried to downgrade from 15.4 to 15.3.1 and the same app (capacitor 2.5, ionic 5, angular 11) works as normal.

fabioz23 commented 2 years ago

this is the func using the qrscanner-11 plugin:

qrCodeFromCamera() {
            this.platform.ready().then(() => {
                this.qrScanner.prepare()
                    .then((status: QRScannerStatus) => {
                        if (status.authorized) {
                            const ionApp = document.getElementsByTagName('ion-app')[0] as HTMLElement;
                            ionApp.style.display = 'none';

                            const scanSub = this.qrScanner.scan().subscribe(async (text: string) => {

                                ionApp.style.display = 'block';

                                scanSub.unsubscribe(); // stop scanning
                                await this.qrScanner.hide();
                                this.qrScanner.destroy().then();

                            });

                            this.qrScanner.resumePreview();

                            this.qrScanner.show()
                                .then(async (data: QRScannerStatus) => {}, 
            err => {
                                        console.log('err= ', err);
                                });

                        } else if (status.denied) {
                            console.log('denied = ', status.denied);
                            this.qrScanner.openSettings();
                        } else {
                                console.log('err = ', status);
                        }
                    })
                    .catch((e: any) => {
                            console.log('Error is', e);
                    }).finally(() => {
                        console.log('qrscanner onFinally');
                });
            });

    }
v1934 commented 2 years ago

Did calling show() and hide() change anything or it was still black? On android 10+ hide() actually showed the camera. But iOS was not affected. What you could also try is to useFrontCamera() and see if it changes anything.

Are you sure that html and body elements have background-color: transparent? In my app i force the color to transparent when showing QRScanner, although I'm not using Ionic. It probably does it by default, but in my case without changing the color I'd also get only black/white screen.

Are you using the wkwebview plugin or anything like this? WKWebViewOnly flag or similar? There may be differences between webview implementations.

Update: I can see that WKWebView is now used by default in cordova-ios for some time already, so I guess that's not the problem

fabioz23 commented 2 years ago

is not the same problem seen on android devices and 2.6.0 plugin version.

my problem is different, the code above works on android 8.x to 12 and from iOS 12 to 15.3.1.

The problem is isolated only on iOS 15.4. (both plugins, this repo and your @v1934 repo)

With 2.6.0 plugin version (this repo) i've also the Android 11-12 problem related to .hide() .show() inversion.

fabioz23 commented 2 years ago

Did calling show() and hide() change anything or it was still black? On android 10+ hide() actually showed the camera. But iOS was not affected. What you could also try is to useFrontCamera() and see if it changes anything.

i'll try but i expect the same result.

Are you sure that html and body elements have background-color: transparent? In my app i force the color to transparent when showing QRScanner, although I'm not using Ionic. It probably does it by default, but in my case without changing the color I'd also get only black/white screen.

yes, the background is transparent.

Are you using the wkwebview plugin or anything like this? WKWebViewOnly flag or similar? There may be differences between webview implementations.

Update: I can see that WKWebView is now used by default in cordova-ios for some time already, so I guess that's not the problem

yep

phausero commented 2 years ago

We do have the same problem. Any news on how to fix this?

fabioz23 commented 2 years ago

We do have the same problem. Any news on how to fix this?

i'm investigating on it.

i ask also support from plugin maintaners @majochoc , @matiu and @v1934 as they know this plugin better than me

v1934 commented 2 years ago

Well, I'm actually just an user of this plugin just like you, I just fixed the previous android bug because it was affecting my app. I'd like to test it too but somehow on my physical 15.4 device I don't reproduce this problem, and I somehow don't have any 15.4 simulator available to download (only 15.2). My app is not based on Ionic though, maybe here lies the problem?

phausero commented 2 years ago

I think i found a solution. You have to also set the background of the webviews scrollview to transparent too now. Will create a PR.

fabioz23 commented 2 years ago

I think i found a solution. You have to also set the background of the webviews scrollview to transparent too now. Will create a PR.

can you give more details on your solution?

i've already tried to make transparent and/or not display some elements in the dom stack with no success.

                        const body = document.getElementsByTagName('body')[0] as HTMLElement;
                        body.style.background = 'transparent';
                        body.style.display = 'none';

                        const appRoot = document.getElementsByTagName('app-root')[0] as HTMLElement;
                        appRoot.style.background = 'transparent';
                        appRoot.style.display = 'none';

                        const ionApp = document.getElementsByTagName('ion-app')[0] as HTMLElement;
                        ionApp.style.background = 'transparent';
                        ionApp.style.display = 'none';

                        const ionContent = document.getElementsByTagName('ion-content')[0] as HTMLElement;
                        ionContent.style.background = 'transparent';
                        ionContent.style.display = 'none';
v1934 commented 2 years ago

@fabioz23 I guess @phausero referes to the UIScrollView element that is a child of WKWebView, therefore it cannot be fixed from HTML. Does the same error happen if your HTML content/body is not scrollable? This repo is abandoned for years already, so if @phausero submits a PR I'll also move the changes to my fork with android fix

fabioz23 commented 2 years ago

ok found and fixed.

@v1934 i've done a PR to your repo for this fix

fabioz23 commented 2 years ago

@phausero if you agree and test goes fine we can mark as solved this issue.

v1934 commented 2 years ago

I have accepted the PR and pushed an update, you can check it out by adding cordova-plugin-qrscanner-11@3.0.3 to your cordova plugins. I have so far tested it on physical Android 10, iOS 15.2 and 15.4 devices, all working fine. Let me know if the issue is resolved for you as well.

rolinger commented 1 year ago

@v1934 - the latest fork you have for qrscanner-11 (3.0.4) is breaking in Cordova 11 (cordova-android 11). Failing to compile the dependency:

1: Task failed with an exception.

I also checked out the zxing-android-embedded scanner toolset, its now up to 4.3.0 - not certain if that helps anything here though.

rolinger commented 1 year ago

@v1934 - any chance you are making a whole new plugin since the orig authors are no longer maintaining this one. I know @jacobg has been maintaining a bunch of fixes in his too; maybe merge the efforts together.

rolinger commented 1 year ago

@v1934 - the latest fork you have for qrscanner-11 (3.0.4) is breaking in Cordova 11 (cordova-android 11). Failing to compile the dependency:

1: Task failed with an exception.

  • Where: Script 'C:\Users\rolin\dev\MyApp\platforms\android\cordova-plugin-qrscanner-11\myApp-qrscanner.gradle' line: 6
  • What went wrong: A problem occurred evaluating script.

Could not find method compile() for arguments [com.journeyapps:zxing-android-embedded:3.3.0] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

I also checked out the zxing-android-embedded scanner toolset, its now up to 4.3.0 - not certain if that helps anything here though.

I got this resolved fixing the gradle script. In gradle 7.0 and higher certain methods have been replaced. Note that the compile, runtime, testCompile, and testRuntime configurations introduced by the Java plugin have been deprecated since Gradle 4.10 (Aug 27, 2018), and were finally removed in Gradle 7.0 (Apr 9, 2021).

The aforementioned configurations should be replaced by implementation, runtimeOnly, testImplementation, and testRuntimeOnly, respectively.

Thus changing the plugin src/android/qrscanner.gradle file fixed the install for me. So far, the plugin has loaded and seems to work fine now on Cordova11 (cordova-android11). Haven't tested iOS yet. Thats next after I rebuild my project for Cordova 11 on the Mac.

dependencies {
    compile 'com.journeyapps:zxing-android-embedded:3.3.0'
    compile 'com.android.support:appcompat-v7:23.1.0'
    //compile 'com.journeyapps:zxing-android-embedded:3.3.0'
    //compile 'com.android.support:appcompat-v7:23.1.0'
    implementation 'com.journeyapps:zxing-android-embedded:3.3.0'
    implementation 'com.android.support:appcompat-v7:23.1.0'
}
v1934 commented 1 year ago

Please try using the new version of my fork: cordova-plugin-qrscanner-11@3.0.5

rolinger commented 1 year ago

@fabioz23 @phausero - I have noticed that on different phones hiding the app layer to reveal the live camera screen beneath the app is not consistent. I have watched users on the same version of my app click the scan now button and the camera is revealed showing an overlay transparent png with red target brackets (IE: [ - ] ) and sometimes its not, its a white screen showing the red brackets - but the camera is on and working and will scan a qr code in front of it. The red target brackets are visual only, giving the user something to aim/focus/center the image with while the scanner does its work in the background.

IE: ionApp.style.display = 'none'

This is telling me that some phones or some versions of iOS need another layer removed to reveal the live camera screen beneath it. However, when it has happened, I have not been able to successful capture what the device is or what additional layer needs to be hidden. I suspect the same is happening to you on certain devices.

I do recall getting it all to work. Then on another test device saw this issue happening and had to hide a different layer...not just another layer, but a different layer altogether. My next version I plan on tracking it down and will try to determine if there any conditions I can add that will always hide the correct layer(s).

lankymart commented 1 year ago

Can anyone advise how I use cordova-plugin-qrscanner-11@3.0.5 in a capacitor 4 project to replace @ionic-native/qr-scanner/ngx which is https://github.com/bitpay/cordova-plugin-qrscanner but wrapped in an @ionic-native npm package?

Tried adding it as an import to replace

import { QRScanner, QRScannerStatus } from "@ionic-native/qr-scanner/ngx";

with

import { QRScanner, QRScannerStatus } from "cordova-plugin-qrscanner-11";

but this just fails as

Could not find a declaration file for module 'cordova-plugin-qrscanner-11'. '/Users/admin/Documents/Task-6181-Upgrade-Capacitor/node_modules/cordova-plugin-qrscanner-11/dist/cordova-plugin-qrscanner-lib.min.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/cordova-plugin-qrscanner-11` if it exists or add a new declaration (.d.ts) file containing `declare module 'cordova-plugin-qrscanner-11';`ts(7016)