When the user is prompted for a permission on Safari, the video element is shown as a black rectangle with a strikethrough play button. How do I change this element's styling? Does it have a specific ID / class / tag?
I'm using Quagga JS as a barcode scanner. AFAIK Quagga creates a video element, then asks for camera permission. The optimal result would be to hide the element using display:none;, but I can't think of any way to accomplish this. I need the element to display the camera feed once the scanner has its permission, but before that it should either paint the screen black or be hidden.
I've fixed it by hiding it via JavaScript and showing it once the Quagga Feedback has finished. Note that a pure CSS solution would be much prettier.
// Hide the preview before it's fully initialised.
$('#videoBoundingBox').hide();
Quagga.init({
inputStream: {
name: "Live",
type: "LiveStream",
target: document.querySelector('#videoBoundingBox')
},
decoder: {
readers: [
"code_128_reader",
"ean_reader"
]
}
}, function (err) {
if (err) {
console.log(err);
setResult(err);
err = err.toString();
if (err.search("NotFoundError")) {
// No camera found. The user is probably in an office environment.
// Redirect to previous orders or show a background image of sorts.
} else if (err.search("NotAllowedError")) {
// The user has blocked the permission request.
// We should ask them again just to be sure or redirect them.
} else {
// Some other error.
}
return;
}
// Hide the preview before it's fully initialised.
$('#videoBoundingBox').show();
setResult("Initialization finished. Ready to start");
console.log("Initialization finished. Ready to start");
Quagga.start();
initializeQuaggaFeedback();
});
Related
What is the right way to access the the front or back camera.
Currently I'm only able to access the "user" camera ( front ).
I can't switch to back camera using any constraints.
Using a specific device id is also not working:
var constraints = {
video: {
facingMode: "environment",
deviceId: "E858F78F6026428D45DD669617B4A881409AA4DA"
}
};
navigator.mediaDevices.getUserMedia(constraints).
Cany somebody please help me?
It is always accessing the front camera.
Following your question I think you already have successfully called getUserMedia() to get the user's permission to access the camera (otherwise you won't have get the front camera to work). This is needed because the label values in the following JSON will only be filled when the user has already granted access.
On iOS you now have to call navigator.mediaDevices.enumerateDevices() and will get a "response JSON" like that:
[
{
"deviceId":"<firstID>",
"kind":"audioinput",
"label":"iPhone Microphone",
"groupId":""
},
{
"deviceId":"<secondID>",
"kind":"videoinput",
"label":"Back Camera",
"groupId":""
},
{
"deviceId":"<thirdID>",
"kind":"videoinput",
"label":"Front Camera",
"groupId":""
}
]
using the deviceId of the device you want or let the user choose it using a basic UI will give you access to the back camera.
Caution: The deviceId values will change on each invocation of enumerateDevices()!
You can also pass this in as an argument when you are calling getUserMedia.
video: {
facingMode: {
exact: 'environment'
}
}
This will return the back camera's video:
navigator.mediaDevices.getUserMedia({
video: {
facingMode: {
exact: 'environment'
}
}
})
I run a simple demo to use cordova-plugin-qrscanner, it can scan qrcode but no camera preview.
qrscannerDemo on Github
Related code blow:
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { AndroidPermissions } from '#ionic-native/android-permissions';
import { QRScanner, QRScannerStatus } from '#ionic-native/qr-scanner';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController,
public androidPermissions: AndroidPermissions,
public qrScanner: QRScanner) {
}
qrscanner() {
// Optionally request the permission early
this.qrScanner.prepare()
.then((status: QRScannerStatus) => {
if (status.authorized) {
// camera permission was granted
alert('authorized');
// start scanning
let scanSub = this.qrScanner.scan().subscribe((text: string) => {
console.log('Scanned something', text);
alert(text);
this.qrScanner.hide(); // hide camera preview
scanSub.unsubscribe(); // stop scanning
});
this.qrScanner.resumePreview();
// show camera preview
this.qrScanner.show();
// wait for user to scan something, then the observable callback will be called
} else if (status.denied) {
alert('denied');
// camera permission was permanently denied
// you must use QRScanner.openSettings() method to guide the user to the settings page
// then they can grant the permission from there
} else {
// permission was denied, but not permanently. You can ask for permission again at a later time.
alert('else');
}
})
.catch((e: any) => {
alert('Error is' + e);
});
}
}
<ion-header>
<ion-navbar transparent>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding style="background: none transparent;">
<button ion-button (click)="qrscanner()">qrscanner</button>
</ion-content>
I run the ionic project on android then click the button but nothing happened and no camera preview show.
I test the project again and find it can scan qrcode and get the result test, but no camera preview.
I search the problem, someone says should to set the body and any elements transparent. I try but does not work.
Android. Nothing appears on screen. #35
AnyOne help?
In top level index.html:
<ion-app style="background: none transparent;"></ion-app>
In camera display page html file:
<ion-content style="background: none transparent;">
After some research even i found the answer and surely this works fantastic for all ,but #nokeieng answer helped me too..
1) First, make a new component for qrscanner. In ionic there is a lifecycle in ionic so go according to that after entering the component this event trigger ionViewDidEnter().In this event the camera opens and let you scan.
ionViewDidEnter(){
this.qrScanner.prepare()
.then((status: QRScannerStatus) => {
if (status.authorized) {
// camera permission was granted
var camtoast = this.toastCtrl.create({
message: 'camera permission granted',
duration: 1000
});
camtoast.present();
// start scanning
this.qrScanner.show()
window.document.querySelector('ion-app').classList.add('cameraView');
let scanSub = this.qrScanner.scan().subscribe((text: string) => {
console.log('Scanned something', text);
window.document.querySelector('ion-app').classList.remove('cameraView');
this.qrScanner.hide(); // hide camera preview
const toast = this.toastCtrl.create({
message: 'You scanned text is this :'+text,
duration: 6000
});
toast.present();
scanSub.unsubscribe(); // stop scanning
});
} else if (status.denied) {
const toast = this.toastCtrl.create({
message: 'camera permission was denied',
duration: 3000
});
toast.present();
// camera permission was permanently denied
// you must use QRScanner.openSettings() method to guide the user to the settings page
// then they can grant the permission from there
} else {
const toast = this.toastCtrl.create({
message: 'You can ask for permission again at a later time.',
duration: 3000
});
toast.present();
// permission was denied, but not permanently. You can ask for permission again at a later time.
}
})
.catch((e: any) => console.log('Error is', e));
}
2) After this remove the camera class when back button is pressed for that add this code.
ionViewWillLeave() will triggers when component is destroyed or left.
ionViewWillLeave(){
window.document.querySelector('ion-app').classList.remove('cameraView');
}
3) We are done with .ts file. Now we have to make the component and the main element i.e ion-app transparent so that we can see the camera for that we add this css inside theme/variables.scss
ion-app.cameraView ion-nav{opacity:0}
and
ion-app.cameraView,ion-app.cameraView ion-content,ion-app.cameraView .nav-decor,{
background: transparent url("../../assets/imgs/camera_overlay.png") !important;
background-size: 100% 100% !important;}
4) As you can see I have given a background image so that we get a camera overlay preview
and you are done with the code just run this command in terminal to see live changes in ionic
ionic cordova run android --livereload
You just need to toggle the ion-app display between "none" and "block" if the status is authorized.
const ionApp = <HTMLElement>document.getElementsByTagName("ion-app")[0];
// start scanning
const scanSub = this.qrScanner.scan().subscribe((link: string) => {
ionApp.style.display = "block";
this.qrScanner.hide(); // hide camera preview
scanSub.unsubscribe(); // stop scanning
});
ionApp.style.display = "none";
this.qrScanner.show();
There is a div, with class=“nav-decor”, which has a black background, this needs to be changed to transparent.
I changed 3 things to transparent for the camera to show: ion-app, ion-content and .nav-decor
My solution was to have a “cameraView” class, which would set the ion-app, ion-content and .nav-decor to have a transparent background.
I used this CSS
ion-app.cameraView, ion-app.cameraView ion-content, ion-app.cameraView .nav-decor {
background: transparent none !important;
}
And then these functions to show the camera after qrScanner.show() and hide it after I’m finished scanning
showCamera() {
(window.document.querySelector('ion-app') as HTMLElement).classList.add('cameraView');
}
hideCamera() {
(window.document.querySelector('ion-app') as HTMLElement).classList.remove('cameraView');
}
I've work around following many answers,
Here is my solution combined all of the answer I've read.
In my scss file named page-scan.scss
page-scan {}
ion-app.cameraView,
ion-app.cameraView ion-content,
ion-app.cameraView .nav-decor,
ion-header,
ion-navbar,
ion-title {
background: transparent none !important;
}
ion-app.cameraView {
background-size: 100% 100% !important;
/* To show image border */
background-image: url([YOU CAN USE BASE64 image here!!]) !important;
}
Note: image border like this one
Here is the sample image:
file scan.html
<ion-header>
<ion-navbar color="primary_dark">
<ion-title>scan</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
</ion-content>
file scan.ts. add these functions to show and hide camera preview
private showCamera() {
((<any>window).document.querySelector('ion-app') as HTMLElement).classList.add('cameraView');
}
private hideCamera() {
((<any>window).document.querySelector('ion-app') as HTMLElement).classList.remove('cameraView');
}
And finally, call show, scan and preview camera like code below
this.showCamera();
this.qrScanner.show()
this.subScan = this.qrScanner.scan()
See issue on github here
Update your cordova-android.
I fixed this when updated to cordova android 10.1.0
cordova platform remove android
cordova platform add android#10.1.0
.ion-page{display:none important!}
Please help me with Notification in my Firefox add-on.
var notifications = require("sdk/notifications");
function showNotifcation(title, text) {
notifications.notify({
iconURL: data.url("img/icon.png"),
title: title,
text: text
});
setTimeout(notifications.close(), 1000);
}
Not work.
Without more information from you it is not possible to be sure as to what your problem/issue is.
However, a brief look at the sdk/notifications documentation, and source code, indicates that you are attempting to use a non-existent method: notifications.close(). There is no such method in sdk/notifications.
One possible reason for your attempt to use this method is that you are conflating the Web Notification API, more detail, with the Add-on SDK sdk/notifications.
The Add-on SDK, sdk/notifications, has no way for you to programmatically close the notification from your code. Thus, there is no way for you to set a timeout for the notification using this interface. However, in some operating systems/windowing systems there is already a default timeout for these notifications.
You will need to either display a panel on your own, or use the chrome interfaces described in User Notifications and Alerts.
In addition, it would be unusual for you to be able to just call setTimeout(). That will, under most contexts, not be defined. You would normally need to use sdk/timers with:
var { setTimeout } = require("sdk/timers");
In some contexts, you might be able to use window.setTimeout(), when window is appropriately defined (which you will probably have to set yourself).
Modifying the code from my answer to Prevent XUL notificationBox from closing when button is hit (if you want buttons, that answer will show you how to do it), and other answers of mine: Something along the lines of what I believe you desire would be (code for the timeout is at the bottom):
function showNotificationBox(text) {
//Create some common variables if they do not exist.
if (window === null || typeof window !== "object") {
// Add/remove a "/" to comment/un-comment the code appropriate for your add-on:
//* Add-on SDK:
var window = require('sdk/window/utils').getMostRecentBrowserWindow();
//*/
/* Overlay and bootstrap (from almost any context/scope):
var window=Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
//*/
}
if (typeof gBrowser === "undefined") {
var gBrowser = window.gBrowser;
}
let notifyBox = gBrowser.getNotificationBox();
//appendNotification( label , value , image (URL) , priority , buttons, eventCallback )
let theNotification = notifyBox.appendNotification(text, "Test notification unique ID",
"chrome://browser/content/aboutRobots-icon.png",
notifyBox.PRIORITY_INFO_HIGH, [], null);
//* Add-on SDK:
var { setTimeout } = require("sdk/timers");
setTimeout(theNotification.close(), 10000);
//*/
/* Overlay and bootstrap:
let timerCallback = {
notify:function notify() {theNotification.close(); }
}
let closeNotificationTimer = Components.classes["#mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
closeNotificationTimer.initWithCallback(timerCallback,10000,
Components.interfaces.nsITimer.TYPE_ONE_SHOT);
//*/
}
Note: I changed the timeout to 10 seconds from the 1 second which is in the code in your question. One second is a unreasonable amount of time to expect to show anything which you actually desire the user to see and understand.
The above implements the user notification in a notificationBox. As such it shows up within the Firefox window:
It is also possible to use the nsIAlertsService which is what sdk/notifications uses. This will normally display an alert box in the bottom right of the screen, potentially outside of the Firefox window (see image on nsIAlertsService for example). The notification may show up elsewhere depending on how you have your windowing system set up (this is OS dependent). However, the documentation did not have a method to clear the notification, or set a timeout. However, the interface definition does show that a closeAlert() method does exist. The source code for the sdk/notifications does not expose this to the Add-on SDK. Thus, you would need to use the chrome interfaces. I have updated the documentation to show closeAlert().
Such as (some code taken and modified from nsIAlertsService):
//* Add-on SDK:
var {Cc, Ci} = require("chrome");
//*/
/* Overlay and bootstrap:
const Cc = Components.classes;
const Ci = Components.interfaces;
//*/
function showNotifcation(title, text) {
var alertsService = Cc["#mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
try {
//The second use of title is the alert name.
alertsService.showAlertNotification(icon, title, text, false, "", null, title);
} catch (e) {
// This can fail on Mac OS X
}
//* Add-on SDK:
var { setTimeout } = require("sdk/timers");
setTimeout(alertsService.closeAlert(title), 10000);
//*/
/* Overlay and bootstrap:
let alertTimerCallback = {
notify:function notify() {alertsService.closeAlert(title); }
}
let closeAlertTimer = Cc["#mozilla.org/timer;1"].createInstance(Components.interfaces
.nsITimer);
closeAlertTimer.initWithCallback(alertTimerCallback,10000,Ci.nsITimer.TYPE_ONE_SHOT);
//*/
}
I have only tested the above code with a bootstrapped/restartless Firefox add-on. Thus, the Add-on SDK code may be slightly off.
I'm facing a problem using this 2 PhoneGap plugins: "BarcodeScanner" & "ChildBrowser" (inside an iOS app, with XCode 4 & PhoneGap 2.0).
I've a button "Scan" on my app UI. When the user clic on this button, the barcode scanner is launched.
So, in the Success function of the barcode scanner callback, I need to open the recovered URL from the scan in a new Childbrowser window (inner the app).
But the new Childbrowser window is never been opened, while the console displays "Opening Url : http://fr.wikipedia.org/" (for example).
Here is my JS part of code:
$("#btnStartScan").click(function() {
var scanBarcode = window.plugins.barcodeScanner.scan(
function(result) {
if (!result.cancelled){
openUrl(result.text);
}
},
function(error) {
navigator.notification.alert("scanning failed: " + error);
});
});
function openUrl(url)
{
try {
var root = this;
var cb = window.plugins.childBrowser;
if(cb != null) {
cb.showWebPage(url);
}
else{
alert("childbrowser is null");
}
}
catch (err) {
alert(err);
}
}
And all works fine if I call my openURL() function inside a Confirm alert callback for example, like this:
if (!result.cancelled){
navigator.notification.confirm("Confirm?",
function (b) {
if (b === 1) {
openUrl(result.text);
}
},
'Test',
'Yes, No');
}
But I need to launch the ChildBrowser window directly after a scan, without any confirm alert etc.
Does anybody know how to solve this please?
I also have this same problem.
Solve it by set timeout.
var scanBarcode = window.plugins.barcodeScanner.scan(
function(result) {
if (!result.cancelled){
setTimeout(function(){ openUrl(result.text); },500);
}
},
function(error) {
navigator.notification.alert("scanning failed: " + error);
});
I'm running into the exact same problem.
My application also has another mechanism to show a webpage besides the barcode reader and when I do that action I can see that the barcode-related page HAD loaded, but it never was shown.
In ChildBrowserViewController.m, I'm looking at the last line of loadURL() which is webView.hidden = NO; and I'm thinking that the child browser is set visible after we barcode but something about the barcode reader window caused the child browser to get set to the wrong z-order, but I'm not familiar enough with the sdk to know how to test that or try to bring it to the front.
Hope this helps target a potential area.
I have an application that requires a page refresh whenever the orientation changes (ipad/iphone). Within this application, HTML5 videos also gets presented at certain times in UX. Whenever a user is viewing a video in full screen mode, their first inclination is to rotate the device to landscape orientation if it was not already in that mode. When they do this, however, it triggers the nasty page reload, effectively ending their viewing session. By tapping into webkit full screen API I was able to write logic to control this behavior, which works perfectly on Safari desktop as well as with the iPad/iPhone user agent selected in developer tools, but it DOES NOT work on the native iphone/ipad.
document.webkitIsFullScreen returns false/true correctly in console in Safari, but comes up as undefined on iphone/ipad. Can anyone tell me how to accomplish this on ipad/iphone, since these are the only devices that require this functionality anyway? Or is there a much simpler solution that I am overlooking? Any help is greatly appreciated!
$(document).ready( function () {
var video = document.getElementById('video');
var canrefresh = true;
video.addEventListener("webkitfullscreenchange",function(){
// Detects if video is in full screen mode and toggles canrefresh variable
// canrefresh = false when webkitfullscreenchange event is heard
// canrefresh = true after exiting full screen
if (canrefresh == true) {
canrefresh = false;
} else {
canrefresh = true;
}
console.log(document.webkitIsFullScreen+' | '+canrefresh);
}, false);
$(window).resize(function() {
// Look to make sure not in full screen, and canrefresh variable is true before refreshing page
if((document.webkitIsFullScreen == false) && (canrefresh == true)){
window.location = window.location.href+'?v='+Math.floor(Math.random()*1000);
}
});
console.log(document.webkitIsFullScreen+' | '+canrefresh);
$('body .test').text(document.webkitIsFullScreen+' | '+canrefresh); // document.webkitIsFullScreen is returning 'false' in Safari (correct), but 'undefined' on native iphone/ipad device
});
The equivalent property which is compatible with Mobile Safari is the webkitDisplayingFullscreen property on the HTMLVideoElement DOM object.