vue-qrcode-reader: Camera not working in PWA after app returns from background in iOS
Describe the bug The camera stops working after the PWA returns form background on my 12 mini. The camera also doesn’t work at all on an iPhone 13 (see videos below). App works perfectly fine in Safari. PWA also works fine on Android devices.
To Reproduce Implement this Demo as PWA: https://gruhn.github.io/vue-qrcode-reader/demos/DecodeAll.html#decode-continuously
<template>
<div class="scanner">
<p class="error">{{ error }}</p>
<p class="decode-result">Last result: <b>{{ error }}</b></p>
<qrcode-stream @decode="onDecode" @init="onInit" />
</div>
</template>
<script>
import { QrcodeStream } from 'vue-qrcode-reader'
export default {
components: { QrcodeStream },
data () {
return {
result: '',
error: ''
}
},
methods: {
onDecode (result) {
this.result = result
},
async onInit (promise) {
try {
await promise
} catch (error) {
if (error.name === 'NotAllowedError') {
this.error = "ERROR: you need to grant camera access permission"
} else if (error.name === 'NotFoundError') {
this.error = "ERROR: no camera on this device"
} else if (error.name === 'NotSupportedError') {
this.error = "ERROR: secure context required (HTTPS, localhost)"
} else if (error.name === 'NotReadableError') {
this.error = "ERROR: is the camera already in use?"
} else if (error.name === 'OverconstrainedError') {
this.error = "ERROR: installed cameras are not suitable"
} else if (error.name === 'StreamApiNotSupportedError') {
this.error = "ERROR: Stream API is not supported in this browser"
} else if (error.name === 'InsecureContextError') {
this.error = 'ERROR: Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.';
} else {
this.error = `ERROR: Camera error (${error.name})`;
}
}
}
}
}
</script>
<style scoped>
.error {
font-weight: bold;
color: red;
}
.scanner {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
left: 0;
top: 0;
}
</style>
Screenshots iPhone 12 mini behaviour
iPhone 13 behaviour
Smartphone:
- Devices: iPhone 12 mini, iPhone 13
- OS: iOS 15.4.1
- Browser: PWA
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 3
- Comments: 22 (4 by maintainers)
Commits related to this issue
- fix(QrcodeStream): iOS PWA background stream kill Apparently, when QrcodeStream is used in an iOS PWA and goes into the background, the stream on the video element is stopped. When the user returns, ... — committed to gruhn/vue-qrcode-reader by gruhn a year ago
- fix(QrcodeStream): iOS PWA background stream kill Apparently, when QrcodeStream is used in an iOS PWA and goes into the background, the stream on the video element is stopped. When the user returns, ... — committed to gruhn/vue-qrcode-reader by gruhn a year ago
- fix(QrcodeStream): iOS PWA background stream kill Apparently, when QrcodeStream is used in an iOS PWA and goes into the background, the stream on the video element is stopped. When the user returns, ... — committed to gruhn/vue-qrcode-reader by gruhn a year ago
- feat(QrcodeStream): throw timeout error when camera won't load On iOS devices in PWA mode, QrcodeStream works initially, but after killing and restarting the PWA, all video elements fail to display c... — committed to gruhn/vue-qrcode-reader by gruhn a year ago
- feat(QrcodeStream): throw timeout error when camera won't load On iOS devices in PWA mode, QrcodeStream works initially, but after killing and restarting the PWA, all video elements fail to display c... — committed to gruhn/vue-qrcode-reader by gruhn a year ago
- feat(QrcodeStream): throw timeout error when camera won't load On iOS devices in PWA mode, QrcodeStream works initially, but after killing and restarting the PWA, all video elements fail to display c... — committed to gruhn/vue-qrcode-reader by gruhn a year ago
- feat(QrcodeStream): throw timeout error when camera won't load On iOS devices in PWA mode, QrcodeStream works initially, but after killing and restarting the PWA, all video elements fail to display c... — committed to gruhn/vue-qrcode-reader by gruhn a year ago
I have tested my PWA on iOS 17.2 and everything works. I hope it will be live soon.
Since today the scanner exits with the StreamLoadTimeoutError everytime - also when newly started and not activating from the background. I have not changed anything - neither on the web nor on my phone. Same issue on 3 client’s phones. The PWA askes for camera permission every time.
I then updated from 16.4.1 to 16.4.2 - when I started the PWA again for the first time on the new system, the camera access worked. But this was the only time it worked - later tests did not work any more. When switching off/on the device it works for one single time again.
I also found out that the PWA camera access works when the camera app has just been put to background.
Yes, I doubt so. But iOS 17 will be released in a few weeks already and if you cannot wait, there are some pretty stable public betas available.
In IOS 17 Beta Public Beta 2 the issue seems to be resolved. I have tried it multiple times with several PWAs and could not reproduce the issue. In IOS 17 Beta 1 the issue was still present for me. The only thing I noticed was that the camera image is small for some milliseconds and then gets the full size. Only on first load of the PWA. This is since Beta 1… // edit: I just got the issue again but I stressed the PWA with closing and reopening very often.
Ok, so until someone finds a workaround, I implemented what they suggested in the WebKit issue thread: throw an error when the problem occurs, so at least the application can respond to it. You should be able to do something like this in v5.1.0:
Also, check out the corresponding demo.
Posting to keep the issue open - same issue on iPhone 14. Same issue exactly as Jannis033.
On an iPhone 12 I was testing on, the PWA app would get in a state where the video element of the reader would refuse to start at all after going into the background and coming back. My eventual workaround had two parts:
In
mounted()
of the component showing the qr-reader, find the video element of the qr-reader (usinggetElementsByTagName
or whatever), subscribe to theended
event of the video - which seems to fire when the badness happens. Use$router.back()
to close the component whenever this fires (this may or may not be appropriate depending on your implementation of the reader!)Additionally, in the
beforeDestroy
hook (Vue 2) of the component with the reader, find the video element and do this:I was starting to wonder about brushing off my Swift skills, such as they are, and going native at about this point (which presumably is exactly what Apple wants me to do!)
I doubt that it is the reason. The devices are online the whole time. It just occurs when moving the app into background and back forward. It also behaves differently on different iOS devices (with same iOS-Version), so i would exclude the internet connection and therefore also the cdn as the reason for this.
@0tsu0i0ihajime the error is still not resolved and also the reason has not be found yet.