Capturing camera photos in a UI5 application without containers
Hi there.
Allow me to show you how you can add picture-taking functionality to an UI5 application, in a super easy way. No need to wrap the application in any container. All your users need is a modern browser.
As a developer, you need one npm module to be installed and adding a UI5 control to some view. Couldn’t be simpler…
What makes this possible is the HTML5 media API. This is an API browsers provide so that web apps can access media devices (e.g. camera, microphones). Here’s a good post about it.
The API is not particularly hard to use but it is lower level than what we’d like for a UI5 app. So I’ve decided to take it a step further and wrap it in a nice, easy to use UI5 Camera control.
The control, once inserted in a UI5 view, renders a live preview of the camera and upon user click captures the image from the camera and triggers an event called snapshot
. By listening to this event on your controller you can grab the picture.
The control deals with the boilerplate needed to ask the browser (and user) for Camera access and rendering a live preview of the video stream.
Here’s a live demo of it. Try it with an up-to-date Chrome version and allow the camera when the browser asks. Don’t worry, the pictures never leave your browser.
Sounds good enough? Read below to know how you can add this to your application.
Step 1:
At the root of your UI5 application, check if you have a file called package.json
. If you do go to Step 2, if not do an npm init
and follow the prompt. npm init
creates the package.json
which allows you to install modules locally.
Step 2:
Execute npm install openui5-camera
This installs the library mentioned above which I’ve open sourced and published to the node package manager. The installed files are saved under folder node_modules
.
Step 3:
Copy file node_modules\openui5-camera\dist\openui5\camera\library-preload.js
into thirdparty\openui5\camera\library-preload.js
(create folders as necessary).
(bonus points if you can automate this step)
Step 4:
In your manifest, declare a resource path by adding the following inside sap.ui5
:
"resourceRoots": {
"openui5.camera": "./thirdparty/openui5/camera/"
}
Step 5:
In the view you wish to render the camera preview, insert the following:
<cam:Camera
id="idCamera"
width="800"
height="600"
snapshot=".onSnapshot" />
at the top of that view, declare the xml namespace cam
pointing to the openui5.camera
custom control:
xmlns:cam="openui5.camera"
Step 6:
Implement the snapshot event handler in the corresponding controller. Example below:
onSnapshot: function (oEvent) {
// The image is inside oEvent, on the image parameter,
// let's grab it.
var sSnapshot = oEvent.getParameter("image")});
// Do something with it!
// As you see in the demo, you can attach it directly to a src of an Image.
// Because it is already a text string it is also easy to POST to a server inside a json message.
},
The picture is inside the event in png
format encoded in base64, so it is essentially a string allowing you to POST it easily.
If you’re having trouble making it work, check the demo app’s code here
Caveats
The control is still in early development stages. Exposing little details about the underlying camera device. If you make it better please contribute back. Source code here.
Also, note the license. This control comes without any warranty, use at your own risk.
Do you like the control? Show some love with github stars 🙂 If you’re using it, show what you’re building (if you can) in the comments!
All the best
Hi Tiago, great work !
Thanks!
Hi Tiago,
I am trying to invoke a camera probably a DSLR/phone camera from the UI5 application and capture the live feed image on click of a button.
Can you suggest me some library through which I can connect to a camera other than webcam and do this?
Is this control is working in Tablet Device??
Yes. It works on a tablet if it runs a modern browser.
Hello! Great work, thanks. But this is didn`t works at Fiori Application on Android and iOS.
I tried to fix it (on Android Fiori), camera works with polyfill library adapter.js. But that not decide all problems. With adapter.js on Adnroid your camera control launch front camera (faceMode setting in constraint doesn`t help in that problem). I tried many different options for faceMode, but without result. We have that problem, because when devices initializated on camera launch, they with empty labels (on Desktop labels are not empty). I think, this hapend because Fiori App don`t ask permissions for camera (that fixed by application settings in maing Android settings), because I saw that behaviour on Desktop when you don`t send permissions to page. But if you fix permissions on Fiori App, launches front camera. You can fix it by send deviceId to constraint to launch camera what you need. But it`s not easy made for all devices. I think, on my Android launches front camera because it was first in devices array.
Anyway, I try to use cordova on Fiori App and it was easelly: cordova can launch native camera on device, and in native camera you can change cameras, setting, etc.
Thank you so much for you work, this great to use in browsers.
Best regards,
Pavel Mazharov.
Hi Pavel,
Thanks for trying it out and sharing the experience with the Fiori App. As far as I know Fiori App on Android will use the WebView component, which depending on the android version may be lacking in functionality. This is definitely an area I'd like to have a look in the future for this library.
Thanks
Hi Tiago Almeida (or should I say "ola" as a Portuguese speaker as well 🙂 )
Great work, providing a useful and simple to use component at the same time!
I managed to make it work, but I had to copy the .js components (Camera, CameraRenderer and library ) into the folder, otherwise it wouldn't work. Seems like the library-preload didn't work properly for me, not registering the modules. It's a minor, but do you have any idea what could be wrong? I've followed all steps, including the resource in manifest. I'm working with SAP UI5 1.38. It's not a big issue, but I always like to understand the reasons, concept behind and solve it.
Thanks
Luis
Olá Luis!
Sorry for the delay in the reply.
What you mention is interesting. Did you have the preload options disabled app-wide?
The demo app is working by loading only the -preload file but it could be an incompatibility with 1.38, demo is using the latest and greatest. I'll look at that and update here If i find anything.
Thanks for the comment!
Hi Tiago Almeida, is it possible to record a video in sapui5 ?
Hi Samuel,
The library does not support video recording at the moment. Only capturing still images. However, it is theoretically possible to do that. There are 3 javascript APIs for capturing/recording video from the media stream: MediaStream Recording API (a.k.a. Media recording API), HTML Media Capture and webRTC (sending the video as it comes from the device). It would be an interesting project to get that support in ?
Hi Tiago Almeida .
Does the work on IOS Fiori client app ?...For me its not working.
However its working perfectly on android Fiori Client app.
Hello Tiago,
Thanks a lot for your effort, actually I am using the lib working properly in my application. I just have a topic to bring to you:
Thanks a lot in advance.
Hi Domenico,
Thanks for the comment 🙂
I’ve always had numerous issues with the device toolbar in Google Chrome (assuming this is what you are referring to!). Have you tried changing first the device to emulate and then opening the application?
At the moment there is no control of the resolution of the image, only the viewport size width and height which are exposed as properties of the control. Feel free to add that functionality in and make a pull request! The control code is actually quite small at the moment.
Regards,
Tiago
Hi Tiago,
Thank you for your post. I was exploring this capability ... now I have a question for you.
Does your plugin or other can take real pictures from the native camera (photo) or only from the video stream.
I have a surface capable of taking 8MP pixel... Do you know ways to bypass this 1080p limitation ?
Thank you
Quentin
Hi Quentin,
You're welcome. The plugin takes pictures from the live native camera, using a javascript api for doing so.
On devices with 2 cameras (like a phone which typically has front and back), it defaults to selecting the back camera. You can try your device with the demo page and see if it works for you: https://tiagobalmeida.github.io/openui5-camera/test/demo/index.html
(Need to allow access to the camera)
Resolution of the picture can be controlled on the <Camera> element via width/height properties.
Please note: While I'd love for this to work everywhere, it comes without any guarantee of any kind 🙂 You may have to adapt the code to make it work better for your use case.
Cheers