调用相机并在SD卡中保存图像时出现问题

时间:2011-11-03 14:07:00

标签: blackberry

在我的任务中,我必须通过单击按钮调用相机并拍照,并且必须保存并在同一屏幕中显示图像。我已经尝试过并在模拟器中取得成功。但它不适用于真实设备。得到一些错误。尝试了很多。但是无法找到问题所在。更多,它在9700模拟器中完美运行,并在9500中显示一些错误。

public class CameraScreen extends MainScreen implements FieldChangeListener
{
/** The camera's video controller */
private VideoControl _videoControl;
private Field _videoField;
private EncodingProperties[] _encodings; 
private int _indexOfEncoding = 0;
private static String FILE_NAME = System.getProperty("fileconn.dir.photos")+"IMAGE"; //"file:///SDCard/" + "myphotos/" + "IMAGE";//
private static String EXTENSION = ".bmp";
private static int _counter;
int flag = 0;
BitmapField imageField = new BitmapField();

HorizontalFieldManager menuBar = new HorizontalFieldManager(Field.USE_ALL_WIDTH);

VerticalFieldManager main_vfm = new VerticalFieldManager();

VerticalFieldManager camera_vfm = new VerticalFieldManager();

VerticalFieldManager image_vfm = new VerticalFieldManager();

ButtonField bt = new ButtonField("Click",ButtonField.CONSUME_CLICK);
ButtonField front_bt = new ButtonField("Front",ButtonField.CONSUME_CLICK);
ButtonField back_bt = new ButtonField("Back",ButtonField.CONSUME_CLICK);
ButtonField side1_bt = new ButtonField("Side 1",ButtonField.CONSUME_CLICK);
ButtonField side2_bt = new ButtonField("Side 2",ButtonField.CONSUME_CLICK);


public CameraScreen()
{
    setTitle("First Screen");


     bt.setChangeListener(this);
     front_bt.setChangeListener(this);
     back_bt.setChangeListener(this);
     side1_bt.setChangeListener(this);
     side2_bt.setChangeListener(this);

     image_vfm.add(menuBar);
     menuBar.add(front_bt);
     menuBar.add(back_bt);
     menuBar.add(side1_bt);
     menuBar.add(side2_bt);

     image_vfm.add(bt);
     try {
        Bitmap image = Bitmap.createBitmapFromBytes( readFile(),0, -1, 5 );
        imageField.setBitmap(image);
        image_vfm.add(imageField);              
    } catch(Exception e) { 
            System.out.println(e.toString());
    }

     main_vfm.add(image_vfm);
     add(main_vfm);

     front_bt.setFocus();
    // Initialize the camera object and video field
    initializeCamera();

    // Initialize the list of possible encodings
    initializeEncodingList();


    // If the field was constructed successfully, create the UI
    if(_videoField != null)
    {
        createUI();
    }
    // If not, display an error message to the user
    else
    {
        camera_vfm.add( new RichTextField( "Error connecting to camera." ) );
    }

}

/**
 * Takes a picture with the selected encoding settings
 */   
public void takePicture()
{
    try
    {
        // A null encoding indicates that the camera should
        // use the default snapshot encoding.
        String encoding = null;            

        if( _encodings != null )
        {
            // Use the user-selected encoding
            encoding = _encodings[_indexOfEncoding].getFullEncoding();
        }

        // Retrieve the raw image from the VideoControl and
        // create a screen to display the image to the user.
        createImageScreen( _videoControl.getSnapshot( encoding ) );
    }
    catch(Exception e)
    {
        home.errorDialog("ERROR " + e.getClass() + ":  " + e.getMessage());
    }  
}

/**
 * Prevent the save dialog from being displayed
 * @see net.rim.device.api.ui.container.MainScreen#onSavePrompt()
 */
protected boolean onSavePrompt()
{
    return true;
}

/**
 * Initializes the Player, VideoControl and VideoField
 */
private void initializeCamera()
{
    try
    {
        // Create a player for the Blackberry's camera
        Player player = Manager.createPlayer( "capture://video" );

        // Set the player to the REALIZED state (see Player javadoc)
        player.realize();

        // Grab the video control and set it to the current display
        _videoControl = (VideoControl)player.getControl( "VideoControl" );

        if (_videoControl != null)
        {
            // Create the video field as a GUI primitive (as opposed to a
            // direct video, which can only be used on platforms with
            // LCDUI support.)
            _videoField = (Field) _videoControl.initDisplayMode (VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field");
            _videoControl.setDisplayFullScreen(true);
            //_videoControl.setDisplaySize(50, 50);
            _videoControl.setVisible(true);
        }

        // Set the player to the STARTED state (see Player javadoc)
        player.start();
    }
    catch(Exception e)
    {
        home.errorDialog("ERROR " + e.getClass() + ":  " + e.getMessage());
    }
}

/**
 * Initialize the list of encodings
 */
private void initializeEncodingList()
{
    try
    {
        // Retrieve the list of valid encodings
        String encodingString = System.getProperty("video.snapshot.encodings");

        // Extract the properties as an array of word
        String[] properties = StringUtilities.stringToKeywords(encodingString);

        // The list of encodings
        Vector encodingList = new Vector();

        //Strings representing the four properties of an encoding as
        //returned by System.getProperty().
        String encoding = "encoding";
        String width = "width";
        String height = "height";
        String quality = "quality";

        EncodingProperties temp = null;

        for(int i = 0; i < properties.length ; ++i)
        {
            if( properties[i].equals(encoding))
            {
                if(temp != null && temp.isComplete())
                {
                    // Add a new encoding to the list if it has been
                    // properly set.
                    encodingList.addElement( temp );
                }
                temp = new EncodingProperties();

                // Set the new encoding's format
                ++i;
                temp.setFormat(properties[i]);
            }
            else if( properties[i].equals(width))
            {
                // Set the new encoding's width
                ++i;
                temp.setWidth(properties[i]);
            }
            else if( properties[i].equals(height))
            {
                // Set the new encoding's height
                ++i;
                temp.setHeight(properties[i]);
            }
            else if( properties[i].equals(quality))
            {
                // Set the new encoding's quality
                ++i;
                temp.setQuality(properties[i]);
            }
        }

        // If there is a leftover complete encoding, add it.
        if(temp != null && temp.isComplete())
        {
            encodingList.addElement( temp );
        }

        // Convert the Vector to an array for later use
        _encodings = new EncodingProperties[ encodingList.size() ];
        encodingList.copyInto((Object[])_encodings);
    }
    catch (Exception e)
    {
        // Something is wrong, indicate that there are no encoding options
        _encodings = null;
        home.errorDialog(e.toString());
    }
}

/**
 * Adds the VideoField to the screen
 */
private void createUI()
{
    // Add the video field to the screen
    camera_vfm.add(_videoField);
}

/**
 * Create a screen used to display a snapshot
 * @param raw A byte array representing an image
 */
private void createImageScreen( byte[] raw )
{
    main_vfm.replace(camera_vfm, image_vfm);
    fieldChanged(raw);
        Bitmap image1 = Bitmap.createBitmapFromBytes( readFile(),0, -1, 5 );
        try{
            if(flag == 1){

            }
            else{
                image_vfm.delete(imageField);
            }              
           imageField.setBitmap(image1);
           image_vfm.add(imageField);
        }
        catch(Exception e){System.out.println(e.toString());}
}

private byte[] readFile() {
    byte[] result = null;
    FileConnection fconn = null;
    try {
        fconn = (FileConnection)Connector.open(FILE_NAME + "_front" + EXTENSION);
    } catch (IOException e) {
        System.out.print("Error opening file");
    }

    if (!fconn.exists()) {
        //Dialog.inform("file not exist");
    } else {

        InputStream in = null;
        ByteVector bytes = new ByteVector();
        try {
            in = fconn.openInputStream();
        } catch (IOException e) {
            System.out.print("Error opening input stream");
        }

        try {
            int c = in.read();
            while (-1 != c) {
                bytes.addElement((byte) c);
                c = in.read();
            }
            result = bytes.getArray();
        } catch (IOException e) {
            System.out.print("Error reading input stream");
        }

        try {
            fconn.close();
        } catch (IOException e) {
            System.out.print("Error closing file");
        }
    }
    return result;
}



public void fieldChanged( final byte[] _raw )
{
    try
    {    
        flag ++;
        // Create the connection to a file that may or
        // may not exist.
        FileConnection file = (FileConnection)Connector.open(FILE_NAME + "_front" + EXTENSION);

        // If the file exists, increment the counter until we find
        // one that hasn't been created yet.
        if (file.exists()) {
            file.delete();
            file.close();
            file = (FileConnection) Connector.open(FILE_NAME + "_front" + EXTENSION);
        }       

        //FileConnection file_temp = (FileConnection)Connector.open(FILE_NAME + "tempimg" + EXTENSION);
        //file_temp.delete();
        // We know the file doesn't exist yet, so create it
        file.create();

        // Write the image to the file
        OutputStream out = file.openOutputStream();
        out.write(_raw);

        // Close the connections
        //out.close();
        file.close();
        //Dialog.inform( "Saved to " + FILE_NAME + "_front" + EXTENSION );
    }
    catch(Exception e)
    {
        home.errorDialog("ERROR " + e.getClass() + ":  " + e.getMessage());
        Dialog.inform( "File not saved this time");
    }        
}

/**
 * Sets the index of the encoding in the 'encodingList' Vector
 * @param index The index of the encoding in the 'encodingList' Vector
 */
public void setIndexOfEncoding(int index)
{
    _indexOfEncoding = index;
}

/**
 * @see net.rim.device.api.ui.Screen#invokeAction(int)
 */   
protected boolean invokeAction(int action)
{
    boolean handled = super.invokeAction(action); 

    if(!handled)
    {
        switch(action)
        {
            case ACTION_INVOKE: // Trackball click
            {         
                takePicture();
                return true;
            }
        }
    }        
    return handled;                
}

public void fieldChanged(Field field, int context) {
    // TODO Auto-generated method stub

    srn2 screen2 = new srn2();
    srn3 screen3 = new srn3();
    srn4 screen4 = new srn4();

    if(field==bt)
    {
        main_vfm.replace(image_vfm, camera_vfm);
    }

    if(field==back_bt)
    {
        UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
        UiApplication.getUiApplication().pushScreen(screen2);
    }

    if(field==side1_bt)
    {
        UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
        UiApplication.getUiApplication().pushScreen(screen3);
    }

    if(field==side2_bt)
    {
        UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
        UiApplication.getUiApplication().pushScreen(screen4);
    }
}
}

注意:此错误首先显示“javax.microedition.media.MediaException:已有另一个活动播放器。在现有播放器上调用Player.close()以释放资源。”和相机打开,当我尝试拍照时,此错误显示“Error Class Java.lang.ArrayIndexOutOfBoundsException:Index 0&gt; = 0”

2 个答案:

答案 0 :(得分:0)

在调用_videoControl.getSnapshot( encoding )后,您需要关闭播放器(即拨打player.close()。这正是异常所说的内容。

然而,这种拍摄图像的方法非常不可靠 - 您无法将其用于每个BB设备模型。我不知道为什么RIM会把它放在SDK样本中。通过这样做,RIM以错误的方式推动开发人员。由于alishaik786提到在BB上拍摄图像的正确方法是使用Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments())FileSystemJournalListener实现。只需在这些上搜索StackOverflow以获取实现细节。我模糊地回忆起实现是痛苦的(就像BB上的许多其他部分一样),但一旦完成它就可以在任何设备上运行。

答案 1 :(得分:0)

你有两个错误

1."javax.microedition.media.MediaException: There is already another active Player. Call Player.close()

如果您尝试打开相机(播放器)而另一个相机实例已打开,则抛出此异常。在您的代码中,您需要将播放器对象定义为类级别,并且必须在拍摄快照后关闭播放器(如果您从一个屏幕推送到另一个屏幕,还需要关闭播放器)。

2."Error Class Java.lang.ArrayIndexOutOfBoundsException: Index 0>=0"

当编码数组大小为零时访问编码数组时,可能会发生此错误。 您可以使用_videoControl.getSnapshot(null)来确保此问题,该快照以默认编码方式拍摄。

首先确保这些问题并回复我。