使用Android拍摄照片';s摄影机(API 19):未调用onPictureTaken

使用Android拍摄照片';s摄影机(API 19):未调用onPictureTaken,android,android-camera,google-glass,gdk,Android,Android Camera,Google Glass,Gdk,我对一些非常简单的事情感到沮丧:使用Android的摄像头API(没有预览)拍照。我一直在跟踪stackoverflow的几个答案,但没有成功 最初我遵循这个答案(@sush): 但从未调用过PictureCallback。我接着回答了这个问题(@Alex Cohn): 您正确地发现,不应在startPreview()之前或之后立即调用takePicture()。() 这让我尝试了三种解决方案 解决方案1 第一个解决方案在SurfaceHolder中放置回调: public class Test

我对一些非常简单的事情感到沮丧:使用Android的摄像头API(没有预览)拍照。我一直在跟踪stackoverflow的几个答案,但没有成功

最初我遵循这个答案(@sush):

但从未调用过PictureCallback。我接着回答了这个问题(@Alex Cohn):

您正确地发现,不应在startPreview()之前或之后立即调用takePicture()。()

这让我尝试了三种解决方案

解决方案1 第一个解决方案在SurfaceHolder中放置回调:

public class TestActivity extends Activity
{
    private Camera mCamera;                         

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        takeSnapShot();
    }

    @Override
    protected void onPause()
    {
        clearCamera();
        super.onPause();
    }

    private void takeSnapShot()
    {
        if (mCamera == null)
        {
            try { mCamera = Camera.open(); }
            catch (Exception e) { e.printStackTrace(); }

            SurfaceView surface = (SurfaceView) findViewById(R.id.preview);
            surface.getHolder().addCallback(mSurfaceHolderCallback);

            try { mCamera.setPreviewDisplay(surface.getHolder()); }
            catch (IOException e) { e.printStackTrace(); }

            mCamera.startPreview();
        }
    }

    private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback()
    {
        @Override
        public void surfaceCreated(SurfaceHolder holder)
        {
            try
            {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
                mCamera.takePicture(null, null, mPictureCallback);
            }
            catch (IOException e) { e.printStackTrace(); }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {}

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
    };

    private final Camera.PictureCallback mPictureCallback = new Camera.PictureCallback()
    {
        @Override
        public void onPictureTaken(byte[] data, Camera camera)
        {
            FileOutputStream outStream = null;

            try
            {
                File dir_path =
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);

                File pictureFile = new File(dir_path, "snapshot-test.jpg");

                outStream = new FileOutputStream(pictureFile);
                outStream.write(data);
                outStream.close();
            }
            catch (FileNotFoundException e) { e.printStackTrace(); }
            catch (IOException e) { e.printStackTrace(); }
            finally { clearCamera(); }
        }
    };

    private void clearCamera()
    {
        if (mCamera != null)
        {
            try
            {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
            catch (final Exception e) { e.printStackTrace(); }
        }
    }
如果我只调用一次takeSnapShot,第一个解决方案就可以工作。不幸的是,我无法让mSurfaceHolderCallback运行SurfaceCreated多次

解决方案2 我的第二个解决方案是使用PreviewCallback。在这个解决方案中,我使用了onPause:

在此解决方案中,mRawPreviewCallbackmPictureCallback都不会被调用

解决方案3 我的最后一个例子是使用一个异步任务,在实际拍照之前等待一段时间。希望这会给预览设置足够的时间。在这个解决方案中,我使用了暂停和clearCamera:

公共类测试活动扩展活动
{
私人摄像机麦卡梅拉;
@凌驾
创建时受保护的void(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
takeSnapShot();
}
私有快照()
{
if(mCamera==null)
{
试试{mCamera=Camera.open();}
catch(异常e){e.printStackTrace();}
SurfaceView曲面=(SurfaceView)findViewById(R.id.preview);
请尝试{mCamera.setPreviewDisplay(surface.getHolder());}
catch(IOE异常){e.printStackTrace();}
mCamera.startPreview();
新建CameraTask().execute(mCamera);
}
}
私有类CameraTask扩展异步任务
{
受保护的字符串背景(摄像头…摄像头)
{
试试{Thread.sleep(1500);}catch(InterruptedException e)
{e.printStackTrace();}
mCamera=摄像机[0];
takePicture(null,null,mPictureCallback);
返回MPICUTREPATH;
}
private final Camera.PictureCallback mPictureCallback=新的Camera.PictureCallback()
{
@凌驾
公共void onPictureTaken(字节[]数据,摄像头)
{
FileOutputStream扩展流=null;
尝试
{
文件目录路径=
getExternalStoragePublicDirectory(Environment.DIRECTORY\u DCIM);
File pictureFile=新文件(dir_路径,“snapshot test.jpg”);
mPicturePath=pictureFile.getAbsolutePath();
outStream=新文件OutputStream(pictureFile);
外扩。写入(数据);
exptream.close();
}
catch(FileNotFoundException e){e.printStackTrace();}
catch(IOE异常){e.printStackTrace();}
最后{clearCamera();}
}
};
}
}
与解决方案2一样,从不调用onPictureTaken

在所有示例中,my SurfaceView的布局如下(无预览):



在这一点上,我已经没有什么想法了。我的第一个例子是成功拍摄了一张照片,因此如果我至少可以强制应用程序运行多次surfaceCreated,它应该可以工作。有什么想法吗?

好的,我以前在姜饼设备上遇到过这个问题。 请执行以下操作:

mCamera.takePicture(null, null, new Camera.PictureCallback() {
                                @Override
                                public void onPictureTaken(final byte[] originalData, Camera camera) {
 // logic here
}))

而不是:

 mCamera.takePicture(null, null,myCallback);
private PictureCallback mPicallback=新建PictureCallback(){ };

<SurfaceView
        android:id="@+id/preview"
        android:layout_width="1dp"
        android:layout_height="1dp"></SurfaceView>
mCamera.takePicture(null, null, new Camera.PictureCallback() {
                                @Override
                                public void onPictureTaken(final byte[] originalData, Camera camera) {
 // logic here
 mCamera.takePicture(null, null,myCallback);