Kirungi
Kirungi

Reputation: 57

Camera snapshot in J2ME Null Pointer Exception

I've spent long on this but no success yet. In my application to capture image and send to the server, I get NullPointerException below;

java.lang.NullPointerException:   0

at Files.CameraMIDlet.snap(CameraMIDlet.java:120)
at Files.CameraForm.commandAction(CameraForm.java:116)
at javax.microedition.lcdui.Display$ChameleonTunnel.callScreenListener(), bci=46
at com.sun.midp.chameleon.layers.SoftButtonLayer.processCommand(), bci=74
at com.sun.midp.chameleon.layers.SoftButtonLayer.soft2(), bci=173
at com.sun.midp.chameleon.layers.SoftButtonLayer.keyInput(), bci=78
at com.sun.midp.chameleon.CWindow.keyInput(), bci=38
at javax.microedition.lcdui.Display$DisplayEventConsumerImpl.handleKeyEvent(), bci=17
at com.sun.midp.lcdui.DisplayEventListener.process(), bci=277
at com.sun.midp.events.EventQueue.run(), bci=179
at java.lang.Thread.run(Thread.java:722)

The errors happen at byte[] image = videoControl.getSnapshot("encoding = jpeg"); in the CameraMIDlet and also at midlet.snap(); in the CameraForm, in the code below.

The code for CameraForm is here:

package Files;

import javax.microedition.media.*;

import javax.microedition.lcdui.*;

import javax.microedition.media.control.*;

import java.io.IOException;

class CameraForm extends Form implements CommandListener {

private final CameraMIDlet midlet;

private final Command exitCommand;

private Command captureCommand = null;

private Command showImageCommand = null;


private Player player = null;

private static VideoControl videoControl = null;

private boolean active = false;

private StringItem messageItem;

public CameraForm(CameraMIDlet midlet) {
    super("Camera");
    this.midlet = midlet;
    messageItem = new StringItem("Message", "start");
    append(messageItem);
    exitCommand = new Command("EXIT", Command.EXIT, 1);
    addCommand(exitCommand);
    setCommandListener(this);
    try {
        //creates a new player and set it to realize
        player = Manager.createPlayer("capture://video");
        player.realize();
        //Grap the Video control and set it to the current display
        videoControl = (VideoControl) (player.getControl("VideoControl"));
        if (videoControl != null) {
            append((Item) (videoControl.initDisplayMode(
                    VideoControl.USE_GUI_PRIMITIVE, null)));
            captureCommand = new Command("CAPTURE", Command.SCREEN, 1);
            addCommand(captureCommand);
            messageItem.setText("OK");
        } else {
            messageItem.setText("No video control");
        }
    } catch (IOException ioe) {
        messageItem.setText("IOException: " + ioe.getMessage());
    } catch (MediaException me) {
        messageItem.setText("Media Exception: " + me.getMessage());
    } catch (SecurityException se) {
        messageItem.setText("Security Exception: " + se.getMessage());
    }
}

 *  the video should be visualized on the sreen
 *  therefore you have to start the player and set the videoControl visible

synchronized void start() {
    if (!active) {
        try {
            if (player != null) {
                player.start();
            }
            if (videoControl != null) {
                videoControl.setVisible(true);
                                   //midlet.snap();
            }
        } catch (MediaException me) {
            messageItem.setText("Media Exception: " + me.getMessage());
        } catch (SecurityException se) {
            messageItem.setText("Security Exception: " + se.getMessage());
        }
        active = true;
    }
}

 *  to stop the player. First the videoControl has to be set invisible
 *  than the player can be stopped

synchronized void stop() {
    if (active) {
        try {
            if (videoControl != null) {
                videoControl.setVisible(false);
            }
            if (player != null) {
                player.stop();
            }
        } catch (MediaException me) {
            messageItem.setText("Media Exception: " + me.getMessage());
        }
        active = false;
    }
}

 *  on the captureCommand a picture is taken and transmited to the server

public void commandAction(Command c, Displayable d) {
    if (c == exitCommand) {
        midlet.cameraFormExit();
    } else {
        if (c == captureCommand) {

                      midlet.snap();

        }

    }
}


}

The code for CameraMIDlet is below:

package Files; 

import java.io.*;

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

import javax.microedition.io.*;

import javax.microedition.media.control.*;

import java.io.IOException;

import javax.microedition.media.MediaException;


public class CameraMIDlet extends MIDlet {


private CameraForm cameraSave = null;

private DisplayImage displayImage = null;

    CameraForm  captureThread;

    private static VideoControl videoControl;

    private StringItem messageItem;

public CameraMIDlet() {
}
/*
 * startApp()
 * starts the MIDlet and generates cameraSave, displayImage, database
 *
 **/

public void startApp() {
    Displayable current = Display.getDisplay(this).getCurrent();
    if (current == null) {
        //first call
        cameraSave = new CameraForm(this);
        displayImage = new DisplayImage(this);
        Display.getDisplay(this).setCurrent(cameraSave);
        cameraSave.start();

    } else {
        //returning from pauseApp
        if (current == cameraSave) {
            cameraSave.start();
        }
        Display.getDisplay(this).setCurrent(current);
    }
}
public void pauseApp() {
    if (Display.getDisplay(this).getCurrent() == cameraSave) {
        cameraSave.stop();
    }
}
public void destroyApp(boolean unconditional) {
    if (Display.getDisplay(this).getCurrent() == cameraSave) {
        cameraSave.stop();
    }
}
private void exitRequested() {
    destroyApp(false);
    notifyDestroyed();
}
void cameraFormExit() {
    exitRequested();
}
/**
 * restart the camera again
 *
 */
void displayCanvasBack() {
    Display.getDisplay(this).setCurrent(cameraSave);
    cameraSave.start();
}


/**
 *  the byte[] of the image should be transmitted to a server
 *
 **/
void buildHTTPConnection(byte[] byteImage) {
    displayImage.setImage(byteImage);
    Display.getDisplay(this).setCurrent(displayImage);
    HttpConnection hc = null;
    OutputStream out = null;
    try {
        //enode the image data by the Base64 algorithm
        String stringImage = Base64.encode(byteImage);
        // URL of the Sevlet
        String url = new String(
                "http://ip-adress:8080/C:/Users/HASENDE/Documents/NetBeansProjects/Mobile/pics");
        // Obtain an HTTPConnection
        hc = (HttpConnection) Connector.open(url);
        // Modifying the headers of the request
        hc.setRequestMethod(HttpConnection.POST);
        // Obtain the output stream for the HttpConnection
        out = hc.openOutputStream();

        out.write(stringImage.getBytes());          
    } catch (IOException ioe) {
        StringItem stringItem = new StringItem(null, ioe.toString());
    } finally {
        try {
            if (out != null)
                out.close();
            if (hc != null)
                hc.close();
        } catch (IOException ioe) {
        }
    }
    // ** end network
}
/**
 *  stop the camera, show the captured image and transmit the image to a server
 **/
void transmitImage(byte[] image) {
    cameraSave.stop();
    Display.getDisplay(this).setCurrent(displayImage);
    buildHTTPConnection(image);
}

     public void snap(){
               try {
         byte[] image = videoControl.getSnapshot("encoding = jpeg");
         transmitImage(image);  
         messageItem.setText("Ok");
    } catch (MediaException me) {
          messageItem.setText("Media Exception: " + me.getMessage());
      } 

        }
}

Upvotes: 2

Views: 948

Answers (2)

Mr. Sajid Shaikh
Mr. Sajid Shaikh

Reputation: 7251

For Capturing photo use canvas instead of Form, Check follwing code for Photo Capture

public class ImageCaptureCanvas extends Canvas {

    UrMidlet midlet;
    VideoControl videoControl;
    Player player;
    SnapShotCanvas snap;
    private Display display;



    public ImageCaptureCanvas(UrMidlet midlet) throws MediaException {
        this.midlet = midlet;

        this.display = Display.getDisplay(midlet);
        this.setFullScreenMode(true);

        try {
            player = Manager.createPlayer("capture://image");
            player.realize();
            videoControl = (VideoControl) player.getControl("VideoControl");

        } catch (Exception e) {
            dm(e.getClass().getName());
        }

        videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);
        try {
            videoControl.setDisplayLocation(0,0);
            videoControl.setDisplaySize(getWidth(), getHeight());

        } catch (MediaException me) {
            try {
                videoControl.setDisplayFullScreen(true);
            } catch (MediaException me2) {
            }
        }
        dm("icc10");
        videoControl.setVisible(true);
        dm("icc11");
        player.start();
        this.display.setCurrent(this);
    }

     public void dm(String message) {
        Form form = new Form("Error");
        form.append(message);
        display.setCurrent(form);
    }

    public void paint(Graphics g) {
    }

    protected void keyPressed(int keyCode) {
        boolean prv=false;
        int actn=getGameAction(keyCode);
        switch (keyCode) {
            case KEY_NUM5:
                prv=true;
                Thread t = new Thread() {

                    public void run() {
                        try {
                            byte[] raw = videoControl.getSnapshot(null);
                            Image image = Image.createImage(raw, 0, raw.length);

                            snap = new SnapShotCanvas(image);
                            display.setCurrent(snap);
                        } catch (Exception e) {
                            dm(e.getClass().getName() + " " + e.getMessage());
                        }
                    }
                };
                t.start();
                break;
        }
        if(!prv){
            switch (actn) {
            case Canvas.FIRE:
                Thread t1 = new Thread() {

                    public void run() {
                        try {
                            byte[] raw = videoControl.getSnapshot(null);
                            Image image = Image.createImage(raw, 0, raw.length);

                           snap = new SnapShotCanvas(image);
                           display.setCurrent(snap);

                        } catch (Exception e) {
                            dm(e.getClass().getName() + " " + e.getMessage());
                        }
                    }
                };
                t1.start();
                break;

        }
        }

    }
}

SnapShotCanvas Code here

class SnapShotCanvas extends Canvas {

    private Image image;

    public SnapShotCanvas(Image image) {
        this.image = image;
        setFullScreenMode(true);
    }

    public void paint(Graphics g) {
        g.drawImage(image, getWidth() / 2, getHeight() / 2, Graphics.HCENTER | Graphics.VCENTER);
    }
}

Upvotes: 0

gnat
gnat

Reputation: 6228

By identifying the statement that throws NPE you get 99% close to finding the bug:

    byte[] image = videoControl.getSnapshot("encoding = jpeg");

NPE in above statement means videoControl is null. Now if you look at it closer, you may notice that in CameraMIDlet, videoControl is initialized with null and never changes to anything else - that's why you are getting NPE. By the way, from CameraForm code it looks like you intended to use videoControl object that is defined there, didn't you.

Side note. CameraForm seems to be designed to used in multiple threads (there are synchronized modifiers) - if this is the case, you better make sure that videoControl is also obtained from it in a synchronized way. Also in that case, add volatile modifier in definition of active flag:

    private volatile boolean active = false; // in CameraForm

Upvotes: 2

Related Questions