安卓后台静默拍照,适用于5.0以下版本,高版本未测试。
https://blog.csdn.net/feiyu1947/article/details/84840126
实际上,安卓拍照需要预览没错,但预览并非需要一个SurfaceView,如果用SurfaceView来作为预览输出,那么程序后台之后,没有界面,就无法拍照了。
mTexture = new SurfaceTexture(0);
try {
mCamera.setPreviewTexture(mTexture);
mCamera.startPreview();
} catch (IOException e) {
Log.e(TAG, "initiate camera failed, e: " + e.getMessage());
}
package company.camera;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.Typeface;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CameraManager implements Camera.PictureCallback, Camera.PreviewCallback {
final String TAG = "静默拍照";
private Camera mCamera;
private SurfaceTexture mTexture;
private String fileName;
private SurfaceHolder mHolder;
private Paint paint = new Paint();
private String osd = "牛逼";
private int fontHeight;
private int fontWidth;
private SurfaceView surfaceView;
static private Lock lock = new ReentrantLock();
public CameraManager(SurfaceView surfaceView) {
this.surfaceView = surfaceView;
mTexture = new SurfaceTexture(0);
mHolder = surfaceView.getHolder();
paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setTextSize(80);
paint.setAntiAlias(false);
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
this.fontHeight = fm.bottom - fm.top;
Rect bounds = new Rect();
paint.getTextBounds("牛", 0, 1, bounds);
this.fontWidth = bounds.right - bounds.left;
}
public boolean takePhoto(int id, final String fileName, int width, int height, String osd) {
lock.lock();
try {
closeCamera();
this.fileName = fileName;
this.osd = osd;
openCamera(id, width, height);
mCamera.takePicture(null, null, this);
return true;
} catch (Exception e) {
Log.e(TAG, "拍摄失败: " + e.getMessage());
return false;
} finally {
lock.unlock();
}
}
private void closeCamera() {
lock.lock();
try {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
}
mCamera = null;
} finally {
lock.unlock();
}
}
private boolean openCamera(int id, int width, int height) {
try {
mCamera = Camera.open(id);
mCamera.setPreviewTexture(mTexture);
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(width, height);
parameters.setPictureSize(width, height);
mCamera.setParameters(parameters);
mCamera.startPreview();
return mCamera != null;
} catch (Exception e) {
Log.e(TAG, "打开摄像头失败: " + e.getMessage());
return false;
}
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
closeCamera();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length).copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(bitmap);
String time = lyh.Utils.formatDateTime("yyyy-MM-dd HH:mm:ss EEE", new Date());
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int x, y;
x = 50;
y = fontHeight;
canvas.drawText(time, x, y, paint);
x = w - 50 - osd.length() * fontWidth;
y = h - fontHeight;
canvas.drawText(osd, x, y, paint);
lyh.Utils.mkdirs(fileName);
File pictureFile = new File(fileName);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
bitmap.recycle();
fos.close();
Log.i(TAG, "拍摄成功并保存文件: " + pictureFile);
} catch (Exception error) {
Log.e(TAG, "拍摄失败: " + error.getMessage());
}
Canvas canvasSV = surfaceView.getHolder().lockCanvas();
if (canvasSV != null) {
Rect src = new Rect(0, 0, w, h);
Rect dst = new Rect(0, 0, canvasSV.getWidth(), canvasSV.getHeight());
canvasSV.drawBitmap(bitmap, src, dst, null);
surfaceView.getHolder().unlockCanvasAndPost(canvasSV);
} else
Log.e(TAG, "屏幕锁定,无法显示输出图片");
}
}