需求:
在页面上实时捕捉画面并预览,
在nfc打卡校验通过的时候自动拍照;
无法通过本地的相机实现该功能,只能自定义了
权限
<uses-permission android:name="android.permission.CAMERA"/>
//即使没有没有相机这个硬件也可以安装
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
创建预览相机需要的surfaceview
public class CameraView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraView(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder=getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
//接口回调
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.v("meee",getClass()+":\n"+"设置相机预览失败");
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
if (mHolder.getSurface()==null)
return ;
mCamera.stopPreview();
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.v("meee",getClass()+":\n"+"设置相机预览失败");
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
}
页面
布局:
布局很简单,线性布局上方是一个framelayout下方是一个button
public class MainActivity extends AppCompatActivity {
private FrameLayout fl;
private Button btn;
Camera mCamera;
CameraView mCameraView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
if (!hasCamera(this)){
Toast.makeText(getApplicationContext(),"开发板不支持相机",Toast.LENGTH_SHORT).show();
}else {
initCamera();
}
}
private void initView() {
fl = (FrameLayout) findViewById(R.id.fl);
btn = (Button) findViewById(R.id.btn);
}
private void initCamera() {
mCamera=getCameraInstance();
mCameraView=new CameraView(this,mCamera);
fl.addView(mCameraView);
}
//判断是否存在相机
private boolean hasCamera(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA))
return true;
return false;
}
//获取相机
public static Camera getCameraInstance() {
Camera camera = Camera.open();
return camera;
}
}
添加拍照的回调
//拍照的回调
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
if (file == null) {
Toast.makeText(getApplicationContext(), "读取权限异常", Toast.LENGTH_SHORT).show();
return;
}
String pictureName = new DateFormat().format("yyyyMMddHHmmss",
new Date()).toString()
+ ".png";
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file + File.separator + pictureName);
fos.write(data);
fos.close();
Log.v("meee", getClass() + ":\n" + "成功保存至" + file);
} catch (FileNotFoundException e) {
Log.v("meee", getClass() + ":\n" + "保存失败");
} catch (IOException e) {
Log.v("meee", getClass() + ":\n" + "保存失败");
}
}
};
//在需要的时刻通过handler进行拍照
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case TAKE_PHOTO:
mCamera.takePicture(null, null, mPictureCallback);
break;
}
}
};
定时拍照
new Timer().schedule(new TimerTask() {
@Override
public void run() {
mHandler.sendEmptyMessage(TAKE_PHOTO);
}
},10000);
获取时间精确到秒
String pictureName = new DateFormat().format("yyyyMMdd-HH:mm:ss",
new Date()).toString()
+ ".png";
设置摄像头的方向
//获取摄像头的信息
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
//camreaId=0代表后置摄像头,1代表前置
android.hardware.Camera.getCameraInfo(camreaId,cameraInfo);
//获取当前页面的旋转角度
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
判断是否是前置摄像头
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
Log.v("meee","qian");
result = (cameraInfo.orientation + degree) % 360;
result = (360 - result) % 360;
}
#