自定义摄像头预览功能
权限
动态权限略
<uses-permission android:name="android.permission.CAMERA" />
代码
- 使用SurfaceView
这里不能使用普通的View,因为要实时地显示摄像头捕获到的图像,简单来说View适合被动刷新的情况,SurfaceView适合主动刷新(在子线程里),其余的不多说了
- 获取相机
import android.hardware.Camera;
注意camera导包到这个,虽然过时了
private Camera getCamera() {
Camera camera;
try {
camera = Camera.open();
} catch (Exception e) {
camera = null;
}
return camera;
}
- 开始预览图像
private void setStartPreView(Camera camera, SurfaceHolder holder) {
try {
//把camera捕获到的图像显示在SurfaceView里
camera.setPreviewDisplay(holder);
//将预览效果横屏转为竖直的camera
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
- 释放相机,必须在ondestroy销毁
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
- 把相机的操作与SurfaceView生命周期绑定起来
@Override
public void surfaceCreated(SurfaceHolder holder) {
//开始预览
setStartPreView(mCamera, mHolder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// 当改变时候,先停止预览
mCamera.stopPreview();
//再次开始预览
setStartPreView(mCamera, mHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 释放掉相机
releaseCamera();
}
- Camera绑定Activity生命周期
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
@Override
protected void onResume() {
super.onResume();
if (mCamera == null) {
mCamera = getCamera();
if (mHolder != null) {
setStartPreView(mCamera, mHolder);
}
}
}
- 调用这些方法
public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private SurfaceView mPreview;
private Camera mCamera;
private SurfaceHolder mHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
mPreview = (SurfaceView) findViewById(R.id.surface);
mHolder = mPreview.getHolder();
mHolder.addCallback(this);
mPreview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCamera.autoFocus(null);//点击屏幕自动对焦
}
});
}
至此,你的应用已经具备摄像头预览功能了,点击屏幕会自动对焦
拍照功能
- 开始拍照
public void capture(View view) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
// 设定预览尺寸
parameters.setPreviewSize(900, 300);
// 对焦模式 自动
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// 自动对焦的回调
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
// 自动对焦成功后,拍照,会走mPictureCallback回调
mCamera.takePicture(null, null, mPictureCallback);
}
}
});
}
- 拍照成功后的回调
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
String mFilePath = Environment.getExternalStorageDirectory().getPath();
mFilePath = mFilePath + "/" + "temp.png";
File tempFile = new File(mFilePath);
try {
// 拿着byte[] data,写入图片文件
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(data);
fos.close();
// 我们将打开新的activity,把图片地址传递给下一个activity
Intent intent = new Intent(CameraActivity.this, ResultActivity.class);
intent.putExtra("picPatch", tempFile.getAbsolutePath());
startActivity(intent);
finish();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
- 在新的activity里显示照片
public class ResultActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
String path = getIntent().getStringExtra("picPatch");
ImageView iv = (ImageView) findViewById(R.id.iv);
try {
// 通过matrix把原图旋转90度,因为在拍照的时候,旋转了90度
//,所以现在也要旋转,不然图片是横着的
FileInputStream fis = new FileInputStream(path);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
Matrix matrix = new Matrix();
matrix.setRotate(90);
bitmap = Bitmap.createBitmap(
bitmap, 0, 0,
bitmap.getWidth(),
bitmap.getHeight(),
matrix,
true);
iv.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}