最近项目中需要后台拍照 悄悄上传至后台。
public class MainActivity extends AppCompatActivity {
private String[] cameraIdList;
private CameraDevice.StateCallback cameraDeviceStateCallback;
private TextureView mTextureView;
private ImageReader mImageReader;
private CameraCaptureSession.StateCallback cameraCaptureSessionStateCallback;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
private File mFile;
private CaptureRequest.Builder mPreviewBuilder;
private CaptureRequest mPreviewRequest;
private CameraCaptureSession mCaptureSession;
private CameraDevice mCameraDevice;
/**
* 初始化Thread
*/
private void initThread() {
mBackgroundThread = new HandlerThread("CameraBackground");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initThread();
mFile = new File(getExternalFilesDir(null), "mTextureView.jpg");
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
CameraManager cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
try {
cameraIdList = cameraManager.getCameraIdList();
} catch (CameraAccessException e) {
e.printStackTrace();
}
mTextureView = new TextureView(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(100, 100);
mTextureView.setLayoutParams(params);
WindowManager.LayoutParams wl = new WindowManager.LayoutParams(200, 200, 0, 0, PixelFormat.TRANSPARENT);
// flag 设置 Window 属性
wl.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
// type 设置 Window 类别(层级)
wl.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
wl.gravity = Gravity.CENTER;
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG,/*maxImages*/7);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
cameraManager.openCamera(cameraIdList[1], cameraDeviceStateCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
}
});
findViewById(R.id.tv1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
windowManager.addView(mTextureView, wl);
}
});
cameraDeviceStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
SurfaceTexture texture = mTextureView.getSurfaceTexture();
//assert(texture != null);
// We configure the size of default buffer to be the size of camera preview we want.
texture.setDefaultBufferSize(mTextureView.getWidth(), mTextureView.getHeight());
// This is the output Surface we need to start preview.
Surface surface = new Surface(texture);
try {
mPreviewBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
} catch (CameraAccessException e) {
e.printStackTrace();
}
mPreviewBuilder.addTarget(surface);//预览时,是将Surface()作为目标
try {
mCameraDevice = camera;
camera.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), cameraCaptureSessionStateCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
}
};
cameraCaptureSessionStateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
mPreviewRequest = mPreviewBuilder.build();
try {
session.setRepeatingRequest(mPreviewRequest, new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
mCaptureSession = session;
CaptureRequest.Builder captureBuilder =
null;
try {
captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
} catch (CameraAccessException e) {
e.printStackTrace();
}
captureBuilder.addTarget(mImageReader.getSurface());//拍照时,是将mImageReader.getSurface()作为目标
// Use the same AE and AF modes as the preview.
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
// Orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
// showToast("Saved: " + mFile);
Toast.makeText(MainActivity.this, "图片拍照成功路径" + mFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
//Log.d("customCarmeraActivity", mFile.toString());
// unlockFocus();//恢复预览
windowManager.removeView(mTextureView);
}
};
try {
mCaptureSession.stopRepeating();
mCaptureSession.abortCaptures();
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
}
};
}
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
//showToast("onImageAvailable: " );
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));
}
};
/**
* Saves a JPEG {@link Image} into the specified {@link File}.
*/
private static class ImageSaver implements Runnable {
/**
* The JPEG image
*/
private final Image mImage;
/**
* The file we save the image into.
*/
private final File mFile;
ImageSaver(Image image, File file) {
mImage = image;
mFile = file;
}
@Override
public void run() {
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
FileOutputStream output = null;
try {
output = new FileOutputStream(mFile);
output.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
if (null != output) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
点击按钮之后弹出系统级别的弹出框,悄悄拍照后上传至后台。