Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Added an intermediate page for accessing camera in V2 extensions #20

Closed
wants to merge 3 commits into from

Conversation

defr0std
Copy link

@defr0std defr0std commented Oct 20, 2017

A request is made to use camera feature in V2 extensions.
microsoft/AL#215

The problem is that Camera API requires .NET variable which can be used only on pages. Therefore the proposed solution is to add an intermediate page which would access the camera and provide the taken picture back to the caller as a BLOB.

This solution requires the same number of clicks for the picture to be taken, but shows an intermediate form in the process. On one hand, this form could be a bit distracting, but on the other hand, this form will also report an error message if the camera is not available, so there is no need to check for that in every use case of the camera API and hide the buttons.

The form can also be customized by the extension to provide more instructions to the user.

This is how a picture could be taken using V2 code:

pageextension 50108 CustomerListExt extends "Customer Card"
{
    actions
    {
        addafter(Approval)
        {
            action(ChangePicture)
            {
                ApplicationArea = All;

                trigger OnAction();
                var CameraPage : Page "Camera Interaction";
                    PictureStream : InStream;
                begin
                    CameraPage.AllowEdit(true);
                    CameraPage.Quality(100);
                    CameraPage.EncodingType('PNG');

                    CameraPage.RunModal();

                    if (CameraPage.GetPicture(PictureStream)) then begin
                        Image.ImportStream(PictureStream, CameraPage.GetPictureName());
                    end;
                end;
            }
        }
    }
}

P.S. This is a bit non-standard request - no tests are added since it's all integration API, no codeunits either :)

PageType=StandardDialog;
SourceTableTemporary=Yes;
OnOpenPage=BEGIN
CameraAvailable := CameraProvider.IsAvailable();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a codeunit is also needed to expose IsAvailable method.

@JesperSchulz
Copy link
Contributor

This is a fine little functionality, but it needs some refactoring. We should not have this much code on a page. We will take a closer look and do a little refactoring and re-design.

@defr0std
Copy link
Author

@JesperSchulz Thanks. Also got some UX feedback that it would be nice to have only one OK button on the intermediate page instead of OK/Cancel. Could you please also have a look that while refactoring?

CameraOptions.Quality := Quality;
CameraOptions.AllowEdit := AllowEdit;

CASE EncodingType OF
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try using Evaluate to get the string value of the enumeration.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved properties to the page itself, removed options.

OnOpenPage=BEGIN
CameraAvailable := CameraProvider.IsAvailable();

IF CameraAvailable THEN BEGIN
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better do
IF NOT CameraAvailable THEN
EXIT;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

InStream@1003 : InStream;
OutStream@1004 : OutStream;
BEGIN
File.OPEN(PictureFilePath);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use blob.Import(filename)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

{ 3 ; ;EncodingType ;Option ;OptionString=JPEG,PNG }
{ 4 ; ;MediaType ;Option ;OptionString=Picture,Video,AllMedia }
{ 5 ; ;SourceType ;Option ;OptionString=Camera,PhotoLibrary }
{ 6 ; ;TakenPicture ;BLOB }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just Call them Picture and PictureName

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not relevant anymore.

}
KEYS
{
{ ;Quality ;Clustered=Yes }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you end up saving this you should have a better key. A GUID will do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Table removed

CameraProvider.RequestPictureAsync(CameraOptions);
END;
END;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Us QueryClose to return the LookUpOK if you got a picture.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not possible, as discussed. Instead added GetPicture(stream: InStream): boolean, as agreed.

@MarcHansenMicrosoft
Copy link
Contributor

Please make sure to update the usage sample to reflect the changed code.

JesperSchulz added a commit that referenced this pull request Dec 5, 2017
Create "Camera Interaction" page 1910. This pull request addresses #20.
@JesperSchulz
Copy link
Contributor

Addressed through pull request #44. Case closed.

@DmitryKatson
Copy link

@JesperSchulz i've just tested this in wave 2 with iPhone and found that
if (CameraPage.GetPicture(PictureStream))
shows the import screen to take the picture once again.

So CameraPage.RunModal()
gives me this screen
image

and then I see
image

That's because CameraPage.GetPicture have FileManagement.BlobImport() inside
image

And FileManagement.BlobImport() has UploadIntoStream
image

which opens this new step in the iPhone.
I found this interesting "remark" in the documentation https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/methods-auto/file/file-uploadintostream-method

image

But i think it's not longer true...

So, you need to change "Camera iteraction".GetPicture business logic.

@JesperSchulz
Copy link
Contributor

@dkatson, thanks for letting me know! I'll see what i can do ;-)

@srkkoneti
Copy link

@JesperSchulz, We have tested the camera feature in Wave2 the same issue occurring, After uploading screen, showing blank import screen and if we cancel the import screen, we are getting following error
Media

@JesperSchulz
Copy link
Contributor

We've actually not been able to get around to this issue yet. There are currently quite a few more pressing tasks we need to attend to, I'm afraid. But I've created a bug for this and we should be able to get to it soon. If you'd like to suggest a fix, please go right ahead :-) That might just speed up things! Otherwise please have a little more patience.

@DmitryKatson
Copy link

Well, that was my workaround.

local procedure TakePicture(var TempPurchLine: Record "Purchase Line" temporary);
var
    //CameraInteraction: Page "Camera Interaction";
    PictureStream: InStream;
    FileManagement: Codeunit "File Management";
    TempBlob: Codeunit "Temp Blob";
    FileName: Text;
begin
    //CameraInteraction.AllowEdit(true);
    //CameraInteraction.Quality(100);
    //CameraInteraction.EncodingType('PNG');
    //CameraInteraction.RunModal();
    //if (CameraInteraction.GetPicture(PictureStream)) then begin
    //    TempPurchLine."AIR Item Photo".ImportStream(PictureStream, CameraInteraction.GetPictureName());
    //end;

    FileManagement.BLOBImport(TempBlob, FileName);
    TempBlob.CreateInStream(PictureStream);
    TempPurchLine."Item Photo".ImportStream(PictureStream, FileName);
end;

@DmitryKatson
Copy link

So, just completely ignore Page "Camera Interaction". It works, but not so sexy as with "Camera Interaction" :)

@JesperSchulz
Copy link
Contributor

@srkkoneti
Copy link

@JesperSchulz , Could you please let us know in which build it was included

@JesperSchulz
Copy link
Contributor

The code went in just before Christmas on the 22nd of December. If you take the latest preview build of version 16, you should get it. The code was also backported to 15, but release usually takes a little while. Expect the change to be released by EOM.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants