Sunday, September 27, 2020

D365 CE Mobile Tips: Capturing image using D365 Mobile

 Microsoft provides a set of client APIs which can use to implement device-specific functionalities in D365 Mobile. Those client APIs provide device-specific functionalities like Capture Audio, Capture Image, Capture Video, Scanning Barcodes, Get Geo Position, and Upload Media File. Since D365 Mobile available on almost all major mobile platforms accessing device-specific functions may require native mobile programming. However, if developers use Microsoft provided client APIs then they can get rid of device-specific programming and implement device specific functionalities in Unified Interface with help of Microsoft XRM Client. For more details about XRM.Device APIs please refer to MSDN article.

 https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/xrm-device

 In this blog post will discuss how to use “Xrm.Device.captureImage” APIto capture images from the mobile devices and attached them as an annotation.

There are few image options that can set before capturing an image.

  • allowEdit– If this flag set to yes then the user can edit the image before confirming it. We experienced some issues in Android and will mention them below                
  • height– This will allow users to crop the image after its taken                
  • width –same as the height, the user can crop the captured image.
  • preferFrontCamera– if this flag set to yes then the system will switch to the front camera to capture image                
  • quality– this is a percentage that controls the quality of the image. Value should between0 to 100.

Following code will trigger as a result of button click in custom HTML file added as web resource in Unified Interface form.

function CaptureImage(event) {
    var parentRecordId = event.currentTarget.id;
    var fileName = parentRecordId + ":" + new Date().toLocaleString();
    var Client = globalContext.client.getClient();
    if (Client.toLocaleLowerCase() == "mobile") {
        var imgOptions = {};
        imgOptions.allowEdit = false;
        imgOptions.height = ImageHeight;
        imgOptions.width = ImageWidth;
        imgOptions.quality = ImageQuality;

        Xrm.Device.captureImage(imgOptions).then(
            function (imgData) {
                if (imgData != null && imgData != undefined && imgData.fileContent != null && imgData.fileContent != undefined && imgData.fileContent != "") {
                    var dataUri = imgData.fileContent;                    
                    var annotation = {};
                    annotation.documentbody = dataUri.replace("data:image/png;base64,", "");    
                    annotation.mimetype = "image/png";    
                    annotation["objectid_new_picture@odata.bind"] = "/new_pictures(" + parentRecordId + ")";
                    annotation.subject = "Attached Image : " + new Date().toLocaleString();
                    annotation.filename = fileName;
                    
                    //Create annotation using XRM
                }
            },
            function (error) {
                if (error != null && error != undefined && error != "" && error.message != null && error.message != undefined && error.message != "") {
                    Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: error.message });                    
                } else {
                    Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: error });
                }
            });
    }
}


As mentioned earlier, we end up with permission issue in Android when we set height, width, and allow edit image options (please refer below screenshot). Even we allow access camera, storage, and relevant components D365 client still popping up the same error. Once we removed image options it starts working without any issue. 



Once you remove image options from code then code will looks like following

function CaptureImage(event) {
    var parentRecordId = event.currentTarget.id;
    var fileName = parentRecordId + ":" + new Date().toLocaleString();
    var Client = globalContext.client.getClient();
    if (Client.toLocaleLowerCase() == "mobile") {
        Xrm.Device.captureImage().then(
            function (imgData) {
                if (imgData != null && imgData != undefined && imgData.fileContent != null && imgData.fileContent != undefined && imgData.fileContent != "") {
                    var dataUri = imgData.fileContent;                   
                    var annotation = {};
                    annotation.documentbody = dataUri.replace("data:image/png;base64,", "");   
                    annotation.mimetype = "image/png";   
                    annotation["objectid_new_picture@odata.bind"] = "/new_pictures(" + parentRecordId + ")";
                    annotation.subject = "Attached Image : " + new Date().toLocaleString();
                    annotation.filename = fileName;
                   
                    //Create annotation using XRM
                }
            },
            function (error) {
                if (error != null && error != undefined && error != "" && error.message != null && error.message != undefined && error.message != "") {
                    Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: error.message });                   
                } else {
                    Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: error });
                }
            });
    }
}


This work in both online and offline modes also both Android and iOS.