Thursday, May 7, 2015

Oracle MAF : Upload an image from camera or library

This blog is to share my experience in implementing a very common requirement - attach a photo by integrating with device camera or photo library and then passing the photo  as Base64-encoded string.

STEP 1: Enable camera plugin in your maf-application.xml






STEP 2: Using getPicture method to integreate with device camera and photo library


a. Create a Java class say PhotoUtility.
b. MAF provides method getPicture  to integrate with camera and photo library

getPicture method 

@Params


quality – Quality of saved image. Range is [0, 100]. Higher the quality higher will be the image size. So, 30-50 is good value for quality. For iOS set quality below 50 to avoid memory error on some devices. It might give memory errors when quality is more than 50.

destinationType – Choose the format of the return value.
DeviceManager.DESTINATIONTYPE_FILE_URI  (1) => The file is saved in application`s temporary directory and it Returns image as a filename URI.
DeviceManager.CAMERA_DESTINATIONTYPE_DATA_URL (0) => Returns image as Base64-encoded String which can be passed in a webservice.

sourceType – Source of the image
DeviceManager.SOURCETYPE_PHOTOLIBRARY (0) => photo library
DeviceManager.SOURCETYPE_CAMERA (1) => Camera

allowEdit – Allow simple editing of image before selection. It is ignored in android device.

encodingType – Choose the encoding of the returned image file.
DeviceManager.ENCODING_TYPE_PNG (1) => PNG image is returned
DeviceManager.CAMERA_ENCODINGTYPE_JPEG (0) => jped image is returned

targetWidth  – Width in pixels to scale image. Aspect ratio is maintained. A negative or zero value indicates that the original dimensions of the
image will be used.

targetHeight  – Height in pixels to scale image. Aspect ratio is maintained. A negative or zero value indicates that the original dimensions of the
image will be used.

@Return
a String representing either base64-encoded image data or a file URI, depending on the value of destinationType.


Add the below code in java class which in turn uses getPicture method
     private String photo = "";

    public void setPhoto(String photo) {
        String oldPhoto = this.photo;
        this.photo = photo;
        propertyChangeSupport.firePropertyChange("photo", oldPhoto, photo);
    }


    public void getPhotoFromCamera() {
        String photo1 =
            DeviceManagerFactory.getDeviceManager().getPicture(40, DeviceManager.CAMERA_DESTINATIONTYPE_DATA_URL,
                                                               DeviceManager.CAMERA_SOURCETYPE_CAMERA, false,
                                                               DeviceManager.CAMERA_ENCODINGTYPE_JPEG, 1000, 1000);
        photo1 = "data:image/gif;base64," + photo1;
        setPhoto(photo1);
    }
-------------------------------------------------------------------------------------------------------------------------
    public void getPhotoFromLibrary() {
        String photo1 =
            DeviceManagerFactory.getDeviceManager().getPicture(40, DeviceManager.CAMERA_DESTINATIONTYPE_DATA_URL,
                                                               DeviceManager.CAMERA_SOURCETYPE_PHOTOLIBRARY, false,
                                                               DeviceManager.CAMERA_ENCODINGTYPE_JPEG, 1000, 1000);
        photo1 = "data:image/jpeg;base64," + photo1;
        setPhoto(photo1);
    }


In the above code data:image/jpeg;base64, is the data URL scheme header. This is required to show an image using base64-encoded string.

Right click your java class and create Java and Create Data Control.

STEP 3: Using DC methods in AMX page

Drag drop photo attribute from Data Control paletter to create a MAF input text. This is just to create the bindings. Now delete the input text from the source. Don`t delete it from Data Struture. Just delete it from the editor. And add the below code for image:
<amx:image  inlineStyle="width:60%;max-width:100%;margin-top:10px" id="i1"
                   source="#{bindings.photo.inputValue}"/>


You can change the inlineStyle based on your need.

Now one by one drag and drop getPhotoFromCamera() and getPhotoFromLibrary() methods from Data Control palette to create a MAF button or link.
It will look like this:
      <amx:commandButton actionListener="#{bindings.getPhotoFromCamera.execute}" text="Take New Photo"
                       id="cb3"
                       />
    <amx:commandButton actionListener="#{bindings.getPhotoFromLibrary.execute}" text="Chose Existing Photo"
                        id="cb4"
                       />


You can use a panel group layout vertical to give a better look and feel:
    <amx:panelGroupLayout id="pgl1" layout="vertical" halign="center">
    <amx:image  inlineStyle="width:60%;max-width:100%;margin-top:10px" id="i1"
                   source="#{bindings.photo.inputValue}"/>
      <amx:spacer id="s1" height="20" width="20"/>
      <amx:commandButton actionListener="#{bindings.getPhotoFromCamera.execute}" text="Take New Photo"
                       id="cb3"
                       />
    <amx:commandButton actionListener="#{bindings.getPhotoFromLibrary.execute}" text="Chose Existing Photo"
                        id="cb4"
                        />
    </amx:panelGroupLayout>



Here is how your page will look like
(Note : I have applied some style class to buttons)




STEP 4 : Passing Base64-encoded String to REST service

Now photo attribute contains the image along with Data URI scheme header(data:image/jpeg;base64,). When sending through REST service we need to remove it and call REST service using REST Service Adapter.

I hope it is helpful.


Following the above principle and with some java coding we can even build a page where user can add multiple attachments.

Something like below:







Cheers,
Deepak



8 comments:

  1. Great .. but How Can I Capturing Image from ADF Web Based Application ?

    ReplyDelete
  2. Thanks for this tutorial, but
    How can i save this image on my mobile device
    Plzzzzzzzzz Help

    ReplyDelete
    Replies
    1. Hi Ujjwal,

      Sorry for late reply.

      Either you can save Base64-encoded string or you can save the image with in the application as well.

      I hope you would have completed this requirement till now.

      Regards,
      Deepak

      Delete
    2. Hi deepak,
      now i can see the image in my gallery, but when i click the pic on the same time when i check gallery i am not able to find the image in my phone after 5 to 30 min i ca see that image. why this so please help me

      Delete
    3. i would like to save this image in my database using Rest. what should be the type of image in my database (either Blob or String). Since the type of photo is String

      Delete
  3. Hello Sir,

    I have created a table in oracle database which support utf-8(Hindi) format. Now i want to retrieve these utf-8 value in my Oracle MAF application

    As i am new to Oracle MAF i don't have any idea how to achieve this

    please help me.....

    Thanks & Regard
    Ujjawal Srivastava

    ReplyDelete
  4. how to upload multiple images at a time

    ReplyDelete
  5. I'm hitting following exception -

    07-07 19:49:26.358: D/CordovaInterfaceImpl(14708): Sending activity result to plugin
    07-07 19:49:26.382: D/CameraLauncher(14708): File locaton is: /storage/emulated/0/Download/Pizigani_1367_Chart_10MB.jpg
    07-07 19:49:27.105: I/ExifInterface_JNI(14708): Raw image not detected
    07-07 19:49:27.112: I/ExifInterface_JNI(14708): Raw image not detected
    07-07 19:49:27.138: D/JVM(14708): AttachmentBean: getPhotoFromGallery: Caught IOException: java.nio.file.NoSuchFileException: /storage/emulated/0/Android/data/com.oraclecorp.vertical.cg.RetailExecution/cache/Pizigani_1367_Chart_10MB.jpg?1499482167122


    Do you know how i can resolve this ? This i'm trying to open a image from photo album

    ReplyDelete