J2ME Null指针异常中的相机快照

时间:2012-04-06 15:19:20

标签: java-me midp mmapi

我在这方面花了很长时间,但还没有成功。在我的应用程序中捕获图像并发送到服务器,我在下面得到NullPointerException;

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)

错误发生在CameraMIDlet的byte[] image = videoControl.getSnapshot("encoding = jpeg");和CameraForm的midlet.snap();,在下面的代码中。

CameraForm的代码在这里:

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();

        }

    }
}


}

CameraMIDlet的代码如下:

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());
      } 

        }
}

2 个答案:

答案 0 :(得分:2)

通过识别抛出NPE的语句,您可以99%接近找到错误:

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

上述语句中的NPE表示videoControl为空。现在,如果您仔细观察它,您可能会注意到在CameraMIDlet中,videoControl初始化为null并且永远不会更改为其他任何东西 - 这就是您获得NPE的原因。顺便说一句,从CameraForm代码看起来你打算使用那里定义的videoControl对象,不是吗。

旁注。 CameraForm似乎被设计为在多个线程中使用(有synchronized修饰符) - 如果是这种情况,最好确保也以同步方式从中获取videoControl。同样在这种情况下,在volatile标志的定义中添加active修饰符:

    private volatile boolean active = false; // in CameraForm

答案 1 :(得分:0)

用于捕获照片使用画布而不是Form, 检查以下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;

        }
        }

    }
}

SnapShot Canvas Code

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);
    }
}