+ Start a Discussion
Jai ChaturvediJai Chaturvedi 

Salesforce1: Unable to access mobile camera

I have written code to access camera from VF page. It is working fine in laptop browser and mobile browser. But when I am trying the same VF page in Salesforce1 app it is not accessing camera.I am using Andriod OS.

I tried 2 approaches, both are not working.

Approach 1: Using <apex:inputFile accept="image/*;capture=camera" />
Page:​
<apex:page controller="CameraAccess2" standardStylesheets="false" showHeader="false" docType="html-5.0">
    <apex:form >
        Enter File Description
        <p>
            <apex:inputText value="{!AttachmentName}" />
            <apex:inputFile value="{!attachmentObj.Body}"  accept="image/*;capture=camera" />
        </p>
        <p>
            <apex:commandButton  action="{!saveFile}" value="Save File" />
        </p>
    </apex:form>
</apex:page>
 
public class CameraAccess{
    public Attachment attachmentObj {get;set;}
    public String AttachmentName {get;set;}
    public CameraAccess() {
        attachmentObj = new Attachment();
    }     

    public PageReference saveFile()
    {
        attachmentObj.ParentId = '003J000000wGwBR';
        attachmentObj.Name = AttachmentName +'.jpg';
        insert attachmentObj;
        return new PageReference('/003J000000wGwBR');
    }
}

Approach 2: Using Javascript WebCam api
 
<apex:page sidebar="false" showHeader="false" standardStylesheets="false">
<apex:includeScript value="{!URLFOR($Resource.jQueryPackageReport, 'package/media/js/jquery-1.11.1.min.js')}"/>

<title>Webcam</title>
<div  style="background-color:#FFF">
    <div  style="padding-top: 2%;padding-bottom: 1%;">
        <div class="col-md-2 col-md-offset-3" >
            <button class="btn btn-primary" style="margin-top:10px" id="snap" >Capture</button>
            <button class="btn btn-primary" style="margin-top:10px;display:none" id="new">Retake</button>    
            <button class="btn btn-primary" style="margin-top:10px;display:none" id="upload">Upload</button>
        </div>


        <div >
            <select class="form-control" style="margin-top:10px" id="videoSource"></select>
        </div>

    </div>
    <div style="padding-top: 2%;padding-bottom: 1%;" >
        <div align="center">
            <canvas id="canvas" style="display:none;border-radius: 15px;" width="240" height="200"></canvas>
            <video class="myvideo" id="video" autoplay="autoplay" style="border-radius: 15px;"></video> 
        </div>
    </div> 

    <div id="el_loading" style="display:none;position: fixed;top:0;background-color: #fbfbfb; height:100%;opacity:0.65;width:100%;">
        <div  style="top: 50%; width: 91px;  margin: 20% 47%;"> 
            <img  src="/img/loading.gif" title="Please Wait..."/>
            <span>Saving...</span>
        </div>
    </div>  
</div>

<div  id="myModal1">
    <div style="padding-top: 5%">  
        <div style="background-color: #2AD67B;color: white;border-radius: 7%;">
            <div  style="background-color: #2AD67B;color: white;border-radius: 7%;">
                <button class="close" onclick="hideTheBoxComponent();" style="color:white" type="button">&times;</button>
                <p style="margin-left: 39%;font-size: large;margin-top: 4%;">
                     Image Saved
                </p>
            </div>
        </div>
    </div>
</div>



<script>   
    function hideTheBoxComponent(){
        $("#myModal1").modal('hide'); 
    }

    function showDialogComponent(){
        $("#myModal1").modal({
          "backdrop"  : "static",
          "keyboard"  : true,
          "show"      : true 
        });
    }

    // Put event listeners into place
    window.addEventListener("DOMContentLoaded", function() {

        // Grab elements, create settings, etc.
        var canvas = document.getElementById("canvas"),
            context = canvas.getContext("2d"),
            video = document.getElementById("video"),
            videoObj = { "video": true },
            errBack = function(error) {
                console.log("Video capture error: ", error.code); 
            };

        // Capture Snap Photo
        document.getElementById("snap").addEventListener("click", function() {
            context.drawImage(video, 0, 0, 250, 200);
            // Littel effects
            $('#video').hide();
            $('#canvas').show();
            $('#snap').hide();
            $('#new').show();
            $('#upload').show();
        });

        // Capture New Photo
        document.getElementById("new").addEventListener("click", function() {
            $('#video').show();
            $('#canvas').hide();
            $('#snap').show();
            $('#new').hide();
            $('#upload').hide();
        });



    }, false);

    'use strict';

    var videoElement = document.querySelector('video');    
    var videoSelect = document.querySelector('select#videoSource');
    navigator.getUserMedia = navigator.getUserMedia ||
      navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

    function gotSources(sourceInfos) {
      for (var i = 0; i !== sourceInfos.length; ++i) {
        var sourceInfo = sourceInfos[i];
        var option = document.createElement('option');
        option.value = sourceInfo.id;
        if (sourceInfo.kind === 'video') {
          option.text = sourceInfo.label || 'camera ' + (videoSelect.length + 1);
          videoSelect.appendChild(option);
        } else {
          console.log('Some other kind of source: ', sourceInfo);
        }
      }
    }

    if (typeof MediaStreamTrack === 'undefined'){
      alert('This browser does not support MediaStreamTrack.\n\nTry Chrome Canary.');
    } else {
      MediaStreamTrack.getSources(gotSources);
    }

    function successCallback(stream) {
      window.stream = stream; // make stream available to console
      videoElement.src = window.URL.createObjectURL(stream);
      videoElement.play();
    }

    function errorCallback(error){
      console.log('navigator.getUserMedia error: ', error);
    }

    function start(){
      if (!!window.stream) {
        videoElement.src = null;
        window.stream.stop();
      }
      var videoSource = videoSelect.value;
      var constraints = {

        video: {
          optional: [{sourceId: videoSource}]
        }
      };
      navigator.getUserMedia(constraints, successCallback, errorCallback);
    }
    videoSelect.onchange = start;
    start();
</script>
</apex:page>

Both are not wokring. Please help. If there is any other way then please share.

I want user to take snapshot from camera and save it on object.
bob_buzzardbob_buzzard
One of the APIs for the file input for Android via cordova (which Salesforce1 is built on) was removed in Android 4.4 as it wasn't intended for use as public API : https://issues.apache.org/jira/browse/CB-5294. This broke the camera access and a couple of other items I believe. There's another issue item that says the behaviour is fixed for Android 5.0, but I don't know whether this is in the version of cordova that Salesforce1 is built on. Unfortunately all we can really do is wait.
Jai ChaturvediJai Chaturvedi
Thans Bob.

I am using Android 5.0 only but I think still issue is not resolved.