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