简体   繁体   English

使用可在所有设备上运行的Camera API制作Android相机应用程序

[英]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. 我知道,这个问题曾被maaany问过,但我认为没有解决方案。 I'm developing application which should be targeted for all devices with android system and backfacing camera. 我正在开发应用程序,应该针对所有设备与Android系统和背面摄像头。 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. 我认为只有合理的解决方案才能找到相机api的代码示例,这些代码样本可以保证几乎适用于所有设备。 Does anybody can provide such sources ... but sources ... that really are tested on maaaaany (ALL) devices ? 有没有人可以提供这样的来源......但是来源......真的是在maaaaany(ALL)设备上测试过的吗? 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). 我已经失去了头脑中的所有头发......而且......我想我已经失去了理智......这都是因为我发布了应用程序(仅适用于我公司的测试),仅在两个测试中测试过设备,并以一种应该工作的方式使用相机api,但它似乎有一些手机,如HTC欲望HD或HTC Evo 3D(与3D相机),其中应用程序只是崩溃(因为相机)或冻结(也因为相机)。 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 . 如果有人拥有相机api的来源(拍摄没有用户gui互动的照片,定期),这些都经过了真正的测试,请非常友好,如果可以,请发布消息来源或将我重定向到正确的位置

Hmm maybe The question should sound like this: "Is it technically possible to use camera api on all devices ?" 嗯,也许这个问题应该是这样的:“技术上是否可以在所有设备上使用相机api?”

Maybe I will describe how I'm currently using api. 也许我会描述我目前如何使用api。

1) Initialize cam: 1)初始化凸轮:

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: 2)开始预览:

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: 3)拍照:

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. 4)完成后或表面处理后释放相机。

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. 在回调方法的第三个代码片段中,我再次调用startPreview,因为在拍摄照片后禁用预览,并且一些智能手机需要启动预览才能拍照。 All above method are part of class extending SurfaceView and implementing SurfaceHolder.Callback and is a part of activity. 以上所有方法都是扩展SurfaceView并实现SurfaceHolder.Callback的类的一部分,并且是活动的一部分。

SurfaceHolder.Callback is implemented as follows: SurfaceHolder.Callback实现如下:

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. 我还在考虑另一种方法 - 克服拍照,而不是注册onPreviewFrame回调,例如在此回调中检查标志是否已请求图片,如果是 - 将图像转换为位图并在进一步处理中使用它。 I was trying this approach, but then stuck with another problem - even If I register empty callback, a gui responds much slower. 我正在尝试这种方法,但后来遇到了另一个问题 - 即使我注册了空回调,gui响应慢得多。

For everyone who like me have problems using android camera api please refer to this link . 对于喜欢我的人来说,使用android camera api时遇到问题请参考此链接 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. 这对我有用,没有抱怨过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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