在使用中显示相机表面

时间:2013-11-27 10:02:51

标签: android service camera surfaceview

我想用相机预览创建一个应用程序,每10秒拍摄一张照片。我用一个活动创建它,每件事都很好。 现在我想知道有没有办法从服务中拍照并在拍摄之前显示相机预览,所有这些都在服务中?

1 个答案:

答案 0 :(得分:1)

您可以使用OpenGL纹理显示来自服务的相机预览。

相机助手:

public class CameraHelper {
    private final static String TAG = "CameraHelper";

    private static Camera sCamera;
    private static Camera.Parameters sParameters;
    public synchronized static Camera getCameraInstance(){
        if (sCamera == null) {
            try {
                sCamera = Camera.open(); // attempt to get a Camera instance
            }
            catch (Exception e) {}
        }

        if (sCamera != null) {
            sParameters = sCamera.getParameters();
            getFormats();
        }
        return sCamera; // returns null if camera is unavailable
    }

    public static void getFormats() {
         List<Size> picSizes = sParameters.getSupportedPictureSizes();
         Size s = picSizes.get(1);
         sParameters.setPictureSize(s.width, s.height);
         picSizes = sParameters.getSupportedPreviewSizes();
         Size previewSize = picSizes.get(picSizes.size() - 1);
         sParameters.setPreviewSize(previewSize.width, previewSize.width);
         sParameters.setPreviewFormat(ImageFormat.JPEG);
    }

    public synchronized static void releaseCamera() {
        if (sCamera != null) {
            sCamera.stopPreview();
            sCamera.release();        // release the camera for other applications
            sCamera = null;
        }
    }
}

服务:

public class CameraServiceTexture extends Service {
    private final static String TAG = "CameraServiceTexture";
    private Camera mCamera;

    @Override public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override public int onStartCommand(Intent intent, int flags, int startId) {
        new PictureThread().start();
        return START_STICKY;
    }

    private class PictureThread extends Thread {
        SurfaceTexture texture;
        private byte[] callbackBuffer;
        public void run() {
            mCamera = CameraHelper.getCameraInstance();

            int textures[] = new int[1];
            GLES20.glGenTextures(1, textures, 0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
            int width  = 4; // size of preview
            int height = 4;  // size of preview
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width,
                    height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);

            texture = new SurfaceTexture(textures[0]);
            texture.setDefaultBufferSize(4, 4);

            try {
                mCamera.setPreviewTexture(texture);
            } catch (IOException e1) {
                e1.printStackTrace();
            }

            Size previewSize=mCamera.getParameters().getPreviewSize();
            int dataBufferSize=(int)(previewSize.height*previewSize.width*
                                   (ImageFormat.getBitsPerPixel(mCamera.getParameters().getPreviewFormat())/8.0));
            callbackBuffer = new byte[dataBufferSize];

            mCamera.addCallbackBuffer(callbackBuffer);
            //mCamera.setPreviewCallback(previewCallback);
            mCamera.setPreviewCallbackWithBuffer(previewCallback);

            mCamera.startPreview();


            time = System.currentTimeMillis();
        }

        private int mMaxCount = 100;
        private int mCount = 0;
        private long time;

        private final Camera.PictureCallback jpegCallBack = new Camera.PictureCallback() {
            @Override public void onPictureTaken(byte[] data, Camera camera) {
                long currentTime = System.currentTimeMillis();
                Log.i(TAG, "onPictureTaken " + data.length + " " + (currentTime - time));
                time = currentTime;
                texture.updateTexImage();
                mCamera.startPreview();
                ++mCount;
                if (mCount < mMaxCount) {
                    mCamera.takePicture(null, null, jpegCallBack);
                }
            }
        };

        private final Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
            @Override public void onPreviewFrame(byte[] data, Camera camera) {
                long currentTime = System.currentTimeMillis();
                Log.i(TAG, "onPreviewFrame " + data.length + " " + (currentTime - time));
                time = currentTime;
                mCamera.addCallbackBuffer(callbackBuffer);
            }
        };

    }
}