PWA mobile camera access - ionic-framework

My requirement is to access the mobile camera in iOS and android using the mobile browser.
Using Ionic PWA app can I access mobile camera in iOS and android device browsers? Looking for PWA solution using Cordova (not native solution).

While working on a PWA. I came across the need to access a mobile device's camera/images.(a native app was out of the question). After doing some research I came across this little nugget.
<input type="file" accept="image/*" capture="camera" />
By adding the accept and capture attributes I was able to access my phone's camera and images. I should also point out that you don't need to do anything special with your Server side (Node or PHP). It acts just like a standard file upload input in a browser.

You can open video devices in the web browser...
<video id="cameraPlayer"></video>
// find the video devices (font/back cameras etc)
navigator.mediaDevices.enumerateDevices().then(function (devices) {
// https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices
devices.forEach(function (device) {
if (device.kind === 'videoinput') {
cameraDeviceIds.push(device.deviceId)
}
})
})
// attach camera output to video tag
navigator.mediaDevices.getUserMedia({
video: { deviceId: { exact: cameraDeviceIds[currentCameraIndex] } }
}).then(function (stream) {
document.getElementById("cameraPlayer").srcObject = stream
})
If you just want an image you can use an input
<input type="file" accept="image/*" id="inputPhoto" class="hidden" capture="environment" />
// trigger capture
document.getElementById('inputPhoto').click()
// event handler for change
function onInputPhotoChange() {
if (document.getElementById('inputPhoto').files.length === 0) {
return
}
var reader = new window.FileReader()
reader.onloadend = function (event) {
event.target.result
// image data
// note you may need to rotate using EXIF data on a canvas
}
// Read the file into memory as dataurl
var blob = document.getElementById('inputPhoto').files[0]
reader.readAsDataURL(blob)
}

If you want to use the camera in an Ionic PWA app, you can use Capacitor:
https://capacitor.ionicframework.com/docs/apis/camera
I implemented the camera feature and it works 100%:

In addition to the above answers, you will have to add this in your index.html file, for the camera to work on PWA
<script nomodule="" src="https://unpkg.com/#ionic/pwa-elements#1.3.0/dist/ionicpwaelements/ionicpwaelements.js"></script>

The solution given above only make selection of file resticted to i
mages category only. But we want to access camera or audio device here
of browser.
So, to rescue this challege here come api from browser("browsers are
powerfull now yeah").
getUserMedia(:true/false)
Here <media_type> is type of media you want to access like
audio,video
You can set it as {audio: true/false} and {video:true/false}.
But error "NotFoundError" will be returned if media not found.
Here is eg; :>
if('mediaDevices' in navigator && 'getUserMedia' in
navigator.mediaDevices){ const stream = await
navigator.mediaDevices.getUserMedia({video: true}) }

It will run on Android and Ios platform with PWA and on a browser
home.page.ts file
import { Component } from '#angular/core';
import { Plugins, CameraResultType, Capacitor, FilesystemDirectory,
CameraPhoto, CameraSource } from '#capacitor/core';
const { Camera, Filesystem, Storage } = Plugins;
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
constructor() {}
async capturedImage(){
const image = await Camera.getPhoto({
resultType: CameraResultType.DataUrl,
source: CameraSource.Camera,
quality: 90
});
console.log('image',image)
}
}
home.page.html
<ion-button expand="full" (click)="capturedImage()"> Captured Image</ion-button>

Accessing the camera via Cordova (and more specifically ionic since you tagged the ionic-framework in your question) is a matter of installing the plugin, whether you're using ionic or not. There are several camera plugins but the one recommended by ionic can be found here:
https://github.com/apache/cordova-plugin-camera
For example to add the plugin to your ionic project, simply run:
ionic Cordova plugin add cordova-plugin-camera
You would use it like this in your component's .ts file (for example):
import { Camera, CameraOptions } from '#ionic-native/camera';
constructor(private camera: Camera) { }
...
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
this.camera.getPicture(options).then((imageData) => {
// imageData is either a base64 encoded string or a file URI
// If it's base64:
let base64Image = 'data:image/jpeg;base64,' + imageData;
}, (err) => {
// Handle error
});
The above implementation was taken from here, where more details can also be found:
https://ionicframework.com/docs/native/camera/

Related

Unable to open PDF files in app view in Capacitor Ionic

import { Plugins } from '#capacitor/core';
const { Browser } = Plugins;
Browser.open({ url: 'http://www.africau.edu/images/default/sample.pdf', windowName:'_self' });
When the url is specified as a link to a website, it works fine but doesnt when specified a PDF. Could someone please suggest if any changes required ? Do i need to specify the rel ? If yes how ? There is no such key to be passed in open call. Response received is 'NO enabled plugin supports this MIME type'.
The Browser plugin from Capacitor should work fine for this. Try without specifying windowName.
// Capacitor v2
import { Plugins } from '#capacitor/core';
const { Browser } = Plugins;
Browser.open({ url: 'http://www.africau.edu/images/default/sample.pdf'});
// or for Capacitor v3
import { Browser } from '#capacitor/browser';
Browser.open({ url: 'http://www.africau.edu/images/default/sample.pdf'});
InAppBrowser will not pdf files. you will have to use it in some other way,
first you can simply add a href this will open user default browser.. like for android it will open this link in android and for ios it will use safari.
open pdf
Second way is to use a plugin for document viewer .. i have added its link below
constructor(private document: DocumentViewer) { }
const options: DocumentViewerOptions = {
title: 'My PDF'
}
this.document.viewDocument('http://www.africau.edu/images/default/sample.pdf', 'application/pdf', options)
https://ionicframework.com/docs/native/document-viewer

Youtube iframe on ionic app generate play icon background

I'm developing an app, using Ionic 3, thats reproduce a youtube video. As I want an embedded video I use an iframe where the src is the video's url.
When I test on an Android device, i get this before the video starts playing.
Is there a way to avoid that background? or make it personalized?
Testing it using "ionic serve" makes the background completely black, so it only happens running on an android device.
Why not use a temporary <img>, as soon as the user clicks on the img, the <iframe> tag is toggled on, with Autoplay = true.
I recommend using angular youtube-player. You can detect when the video is ready to play. If the video is not ready yet, just display an image or a spinner.
Here is an example:
HTML:
<img class="video-loading-cover" src="assets/images/home/ytcover.png" height="550" width="1400" [hidden]="isVideoLoaded" alt="">
<youtube-player #youTubePlayer (ready)="playVideo($event)" (stateChange)="onPlayerStateChange($event)" (error)="hideVideo()"
width="100%" height="540px" [playerVars]="playerVars" [videoId]="videoId"></youtube-player>
TS:
#ViewChild('youTubePlayer') youTubePlayer: YT.Player;
isVideoLoaded: boolean;
videoId = 'your video id';
// optional
playerVars: YT.PlayerVars = {
autoplay: AutoPlay.AutoPlay,
loop: Loop.Loop,
playlist: 'yourPlaylist',
controls: Controls.Hide,
enablejsapi: JsApi.Enable,
origin: window.location.origin,
rel: RelatedVideos.Hide,
iv_load_policy: IvLoadPolicy.Hide,
autohide: AutoHide.HideAllControls,
showinfo: ShowInfo.Hide
};
ngOnInit() {
const tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
document.body.appendChild(tag);
}
onPlayerStateChange(el) {
this.youTubePlayer.mute();
switch (el.data) {
case -1:
case 2:
this.youTubePlayer.playVideo();
break;
case 1:
this.isVideoLoaded = true;
break;
}
}
hideVideo(): void {
this.isVideoLoaded = false;
}
playVideo(event): void {
this.youTubePlayer.mute();
setTimeout(() => {
this.youTubePlayer.playVideo();
}, 10);
}
Note that in my example when the youtube video is loading it will call the (error)="hideVideo()" function and an image will be displayed. When it is available it will automatically hide the image and play the video.

FILE_URI path for Camera not working on IONIC 4

When using the Cameara to take a picture with destinationType: this.camera.DestinationType.FILE_URI, the resulting URL will not work to display the image. For example, when attempting to take a photo like this:
this.camera.getPicture(options).then((url) => {
// Load Image
this.imagePath = url;
}, (err) => {
console.log(err);
});
Attempting to display it as <img [src]="imagePath" > will result in an error (file not found).
The problem here is that the URL is in the file:///storage... path instead of the correct one based on localhost.
In previous versions of Ionic, this would be solved by using normalizeURL. This will not work on Ionic 4 (or at least I could not make it work).
To solve this issue, you will need to use convertFileSrc():
import {WebView} from '#ionic-native/ionic-webview/ngx';
...
this.camera.getPicture(options).then((url) => {
// Load Image
this.imagePath = this.webview.convertFileSrc(url);
}, (err) => {
console.log(err);
});
Now the image URL will be in the appropriate http://localhost:8080/_file_/storage... format and will load correctly.
See WKWebView - Ionic Docs for more information.
In my case, the following code works with me
const downloadFileURL = 'file:///...';
// Convert a `file://` URL to a URL that is compatible with the local web server in the Web View plugin.
const displayedImg = (<any>window).Ionic.WebView.convertFileSrc(downloadFileURL);
In case some gots here looking for the answer on ionic4, check this out
"Not allowed to load local resource" for Local image from Remote page in PhoneGap Build
and look for the answer from #Alok Singh that's how I got it working on ionic4 and even works with livereload
UPDATE december 2021:
You have to install the new Ionic Webview
RUN:
ionic cordova plugin add cordova-plugin-ionic-webview
npm install #awesome-cordova-plugins/ionic-webview
Import it in app.module and your page where you wanna use it:
import { WebView } from '#awesome-cordova-plugins/ionic-webview/ngx';
image = "";
constructor(private webview: WebView){}
Then this will work:
this.camera.getPicture(options).then((imageData) => {
this.image = this.webview.convertFileSrc(imageData)
}, (err) => {
// Handle error
});
And show it in the HTML page:
<img [src]="image" alt="">

Ionic Photo Viewer doesn't work on ios

I'm using Ionic Photo Viewer to show images in full screen. My HTML is:-
<ion-slides>
<ion-slide col-12 *ngFor="let image of businessImages | async">
<div class="main-slider-image" [defaultImage]="'assets/imgs/default_image_slider.png'" [lazyLoad]="image.thumb400Url" [offset]="100" (click)="openImage(image.originalUrl)">
</div>
</ion-slide>
</ion-slides>
On TypeScript:-
openImage(url) {
this.photoViewer.show(url, "", { share: false });
}
On Android is working like this:-
Click here to see Android version
On the other hand, on the iPhone is working like this:-
Click here to see iPhone version
On the iPhone, the photo viewer doesn't open the photo. I've tried:-
openImage(url) {
this.photoViewer.show(url);
}
But this also didn't work. If you've any idea how to solve this issue please share. Thank you
This issue is really crazy and had to spend lots of time to figure out the solutions. The solutions is all the parameters in the 'options' variable are required.
Follow this:
const options = {
share: true, // default is false
closeButton: true, // default is true
copyToReference: true, // default is false
headers: "", // If it is not provided, it will trigger an exception
piccasoOptions: { } // If it is not provided, it will trigger an exception
};
this.photoViewer.show(url, "", options);
At least I had to revert to 1.1.11 (found from NPM) to show IOS properly. For Android, latest version seemed to work.
Share did not seem to work for IOS in 1.1.11. In Android latest photo-viewer plugin it seemed to work. So now I have:
private viewPhoto(url: string): void {
if (url && url != 'assets/images/profile.png') {
this.photoViewer.show(url, '', { share: this.platform.is('android') });
}
}
And.. I think the correct place to discuss these is https://github.com/sarriaroman/photoviewer/issues.
And another thing, I'm considering to use another plugin, https://github.com/Riron/ionic-img-viewer. Some of the photoviewer issues had a link to this but haven't tried it yet.
I have the same error, and im solve with this
ionic cordova plugin rm com-sarriaroman-photoviewer
ionic cordova plugin add com-sarriaroman-photoviewer#1.1.18
npm install --save #ionic-native/photo-viewer
on your function, if device using ios, decodeURIComponent was the answer
showImage(url,title) {
var options = {
share: true, // default is false
closeButton: true, // iOS only: default is true
copyToReference: true // iOS only: default is false
};
if (this.platform.is("ios")) {
url = decodeURIComponent(url);
}
this.photoViewer.show(url, title, options);
}

cordova-plugin-camera not working in IOS

I am developing an hybrid app for Android and for IOS using ionic.
While opening the Camera from Android is working perfectly, but I am not able to open an camera from IOS device.
I install respective plugin for that
cordova plugin add cordova-plugin-camera.
next I added the ng-cordova.js into index.html before the cordova.js line.
Also in app.js i include angular.module('starter', ['ionic', 'ngCordova']
In the Controller.js added $cordovaCamera
my code as
navigator.camera.getPicture(onSuccess,onFail, {
quality:90
destinationType:Camera.DestinationType.DATA_URL,
sourceType:Camera.PictureSourceType.CAMERA,
allowEdit:false,
encodingType:Camera.EncodingType.JPEG,
popoverOptions:CameraPopoverOptions,
saveToPhotoAlbum:true,
correctOrientation:true
})
function onSuccess(imageURI){
$rootScope.$broadcast("ShowAttachmentModal",imageURI);
}
function onSuccess(message){
alert('Failed'+message);
}
This code work perfectly in Android but not working in IOS while to open camera.
#MartinP, instead of ngCordova, which is being deprecated, see if you can use the replacement library Ionic-Natve (http://ionicframework.com/docs/v2/native/camera/).
Then try this code instead.
function takePicture() {
var opts = {
quality: 90,
encodingType: $cordovaCamera.EncodingType.JPEG,
destinationType: $cordovaCamera.DestinationType.DATA_URL,
correctOrientation: true,
allowEdit: true,
targetWidth: 300,
targetHeight: 300
};
$cordovaCamera.getPicture(opts).then(function (imageData) {
$rootScope.$broadcast("ShowAttachmentModal",imageData);;
}, function (err) {
$log.error(err);
});
}
The Cordova plugin is the same. You'll need to inject $cordovaCamera into your controller. Once it works, then you can play around with the options. As you may be aware, the DATA_URL option returns a Base64-encoded string. So to set it as an image's source, you'll need to prepend imageData with 'data:image/jpeg;base64,'.