功能描述:学校刷卡终端采用android系统,学生在进出学校时需要刷卡,刷卡同时系统自动拍照并保存照片,而拍照保存照片这个过程学生并不知晓,也就是后台自动拍照。
实现方式:自动拍照功能使用系统相机Camera即可实现,但是注意:Android 5.0以下版本和Android 5.0及以上版本的实现方式不同,因系统版本为Android 4.4 故采用Android 5.0以下版本的方式实现。
1. 添加系统权限。
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2. 在布局文件中添加SurfaceView, SurfaceView的width和height均设置为0.1dp,这样用户就不能看见相机了,但是注意一定不能设置为0dp。
<SurfaceView
android:id="@+id/texture"
android:layout_width="0.1dp"
android:layout_height="0.1dp"
android:layout_alignParentTop="true" />
3. Activity中初始化Camera,同时实现SurfaceHolder.Callback,Camera.PictureCallback两个接口。
@Bind(R.id.texture)
SurfaceView texture;
private SurfaceHolder surfaceHolder;
private Camera camera;
private void initCamera() {
surfaceHolder = texture.getHolder();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this);
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
if (data != null) {
Bitmap bitmap = Bytes2Bitmap(data);
saveImageToGallery(getApplicationContext(), bitmap);
}
camera.startPreview();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
int cameraNums = Camera.getNumberOfCameras();
L.e("CAMERA_CONTROLL", cameraNums + "");
try {
//我的设备只有一个摄像头,故而直接使用,若为双摄像头,则需要设置使用的是前摄像头还是后摄像头
camera = Camera.open(0);
} catch (Exception e) {
L.e("CAMERA_CONTROLL", e.getMessage());
}
try {
camera.setPreviewDisplay(holder);
Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
camera.setDisplayOrientation(90);
parameters.setRotation(90);
camera.setParameters(parameters);
} catch (Exception e) {
// TODO Auto-generated catch block
if (camera != null) {
camera.release();
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (camera != null) {
camera.stopPreview();
camera.release();
}
}
4. 刷卡事件触发立即拍照。
camera.takePicture(null, null, StudentAttendanceActivity.this);
5. Bytes转Bitmap方法。
public Bitmap Bytes2Bitmap(byte[] b) {
L.e("byte length", b.length + "");
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
5. 将拍照的照片命名后保存到系统相册目录下。
/**
* 保存图片到本地
*
* @param context
* @param bmp
*/
public void saveImageToGallery(Context context, Bitmap bmp) {
// 首先保存图片
File appDir = new File(Environment.getExternalStorageDirectory(), AppConstants.FILEDIR);
if (!appDir.exists()) {
appDir.mkdir();
}
String fileName = dateStr + ".jpg";
File file = new File(appDir, fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 其次把文件插入到系统图库
try {
MediaStore.Images.Media.insertImage(context.getContentResolver(),
file.getAbsolutePath(), fileName, null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
7. Activity退出后释放资源。
@Override
protected void onDestroy() {
super.onDestroy();
ButterKnife.unbind(this);
if (camera!=null) {
camera.release();
camera = null;
}
}
8. 总结:
后台自动拍照保存照片功能,主要在于设置SurfaceView的width和height均设置为0.1dp,则假装对用户不可见,然后设置拍照触发事件,在事件中调用camera.takePicture方法即可。至于照片保存及照片处理可根据业务需求来确定,由于系统拍照拍出的照片很大,一般都要进行压缩处理。
注: 图片压缩工具见我的github项目AndroidUtils 的BitmapCompressor.java 。同时AndroidUtils里还有一些其它常用的工具类哦。