简体   繁体   中英

Making android camera app using Camera API that will work on all devices

I know, this question was asked maaany times, but I do not think there was a solution for this. I'm developing application which should be targeted for all devices with android system and backfacing camera. The problem is I can test application on only two devices and have to be sure that it works on all devices. I think only reasonable solution would be to to find a code samples for camera api that are quaranteed to work on nearly all devices. Does anybody can provide such sources ... but sources ... that really are tested on maaaaany (ALL) devices ? I've lost all hairs from my head ... and .. and I'm loosing my mind i think... It is all because I've released app (only for tests in my company) which was tested on only two devices, and which uses camera api in a way that should work, but it appears there are some phones like for example HTC desire HD or HTC Evo 3d (with 3d camera) where the app simply crashes (because of fu..ing camera) or freezes (also because of fu..ing camera). If there is someone who have sources for camera api (taking a picture without user gui interaction, periodically) which are really tested, please be so kind and if You can, post the source or redirect me to proper place .

Hmm maybe The question should sound like this: "Is it technically possible to use camera api on all devices ?"

Maybe I will describe how I'm currently using api.

1) Initialize cam:

public void initCam()
{       
    LoggingFacility.debug("Attempting to initialize camera",this);
    LoggingFacility.debug("Preview is enabled:"+isPreview,this);
    try {
        if (camera==null) 
        {               
            camera = Camera.open();
            camera.setPreviewDisplay(mHolder);

            if (camera!=null)
            {
                Camera.Parameters parameters = camera.getParameters();              
                List<Size> sizes = parameters.getSupportedPictureSizes();
                if (sizes!=null)
                {
                    Size min = sizes.get(0);
                    for (Size size : sizes)         
                        if (size.width<min.width) min = size;   
                        {
                            parameters.setPictureSize(min.width, min.height);
                        }
                }           

                camera.setParameters(parameters);       
                setDisplayOrientation(90);
            }
        }            
        startPreview(aps);
    } catch (Throwable e){
        if (exceptionsCallback!=null)
            exceptionsCallback.onException(e);          
    } 
}

2) Start preview:

private void startPreview(AfterPreviewStarted after)
{
    try {
        if (!isPreview)
        {
            LoggingFacility.debug("Starting preview",this);
            //camera.stopPreview();             
            camera.startPreview();
            isPreview = true;
            LoggingFacility.debug("Preview is enabled:"+isPreview,this);                
        }
        if (after!=null) after.doAfter();
    }catch(Throwable e)
    {
        if (exceptionsCallback!=null)
            exceptionsCallback.onException(e);  
    }
}

3) Take picture:

public void takePicture(final PictureCallback callback)
{
    LoggingFacility.debug("Attempting to take a picture",this);
    if (camera!=null)
    {       
        if (isPreview)
        {
            try
            {
                LoggingFacility.debug("preview is enabled jut before taking picture",this);
                //AudioManager mgr = (AudioManager)ctx.getSystemService(Context.AUDIO_SERVICE);
                //mgr.setStreamMute(AudioManager.STREAM_SYSTEM, true);      
                LoggingFacility.debug("Taking picture... preview will be stopped...",this);
    isPreview = false;                  
    camera.takePicture(null, new PictureCallback(){
        public void onPictureTaken(byte[] arg0, Camera arg1)
        {
            //LoggingFacility.debug("Picture has been taken - 1t callback",CameraPreview.this);
        }               
    }, callback);

                //mgr.setStreamMute(AudioManager.STREAM_SYSTEM, false);          
            } catch (Throwable e){
                if (exceptionsCallback!=null)
                    exceptionsCallback.onException(e);          
            }
        }
    }   

4) Release camera after done, or after surface is disposed.

public void releaseCam()
{
    LoggingFacility.debug("Attempting to release camera",this);
    if (camera!=null)
    {
        isTakingPictures = false;
        camera.stopPreview();
        isPreview = false;
        camera.release();
        camera = null;          
        LoggingFacility.debug("A camera connection has been released...",this);
    }
}

In 3rd code snippet in callback method Im invoking startPreview again since after taking picture a preview is disabled, and some smartphones require preview to be started to make a picture. All above method are part of class extending SurfaceView and implementing SurfaceHolder.Callback and is a part of activity.

SurfaceHolder.Callback is implemented as follows:

public void surfaceCreated(SurfaceHolder holder) {  
    initCam();

}

public void surfaceDestroyed(SurfaceHolder holder) {         
    releaseCam(); 
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

}

Constructor of class

CameraPreview(Context context) {
    super(context);
    this.ctx = context;     
    mHolder = getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

I was also considering another approach - to overcome taking picture, and instead of this to register onPreviewFrame callback and for example in this callback check the flag if a picture has been requested, if so - convert image to bitmap and use it in further processing. I was trying this approach, but then stuck with another problem - even If I register empty callback, a gui responds much slower.

For everyone who like me have problems using android camera api please refer to this link . It seems the code from this sample works on majority of smartphones .

final int PICTURE_TAKEN = 1;

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(filename)));
startActivityForResult(intent, PICTURE_TAKEN);

This works for me, haven't had complaints sofar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM