Проблема в вызове камеры и сохранении изображений на SD-карту - PullRequest
0 голосов
/ 03 ноября 2011

В моей задаче я должен вызвать камеру одним нажатием кнопки и сделать снимок, сохранить его и отобразить изображение на том же экране. Я попробовал это и преуспел в эмуляторе. но это не работает в реальном устройстве. получать некоторые ошибки. много пробовал. но не могу выяснить проблему. Более того, он отлично работает в эмуляторе 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 () для существующего проигрывателя, чтобы освободить ресурсы». и камера открывается, и когда я пытаюсь сделать снимок, эта ошибка отображает «Ошибка класса Java.lang.ArrayIndexOutOfBoundsException: Index 0> = 0»

Ответы [ 2 ]

0 голосов
/ 21 ноября 2011

вы получили две ошибки

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), который делает снимок в кодировке по умолчанию.

Итак, сначала застрахуйте эту проблему и ответьте мне.

0 голосов
/ 05 ноября 2011

После вызова _videoControl.getSnapshot( encoding ) вам нужно закрыть игрока (т.е. позвонить player.close(). И это именно то, о чем говорит исключение.

Однако этот метод съемки изображений крайне ненадежен - вы не сможете использовать его для каждой модели устройства BB. Я не знаю, почему RIM поместил его в образцы SDK. Делая это, RIM толкает разработчиков в неправильном направлении. Как alishaik786 упоминает, что правильный метод получения изображений на ББ - это использование Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments()) с реализацией FileSystemJournalListener. Просто поищите в StackOverflow по ним детали реализации. Я смутно припоминаю, что реализация болезненна (как и многие другие части на BB), но после этого она будет работать на любом устройстве.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...