需求:
隐蔽拍照,没有预览界面打开这个activity直接调用前置摄像头“咔嚓”给你来张照片不能有声音、闪光灯,总之就是在用户不知情的情况下给你来张美美的自拍。
实现(小米5手机测试)
由于是后加的需求,我就在代码里创建surfaceView了
在onCreate的时候添加代码:
getWindow().setFormat(PixelFormat.TRANSLUCENT);
第一次创建surfaceView 的时候会黑屏一下 或者闪屏,将这个activity设置背景透明,或者在布局里创建这个surfaceView,或者在布局里创建一个宽高0dp的surfaceView(后面两种种方式没有实验过)
如果是fragment设置背景透明好像是不好用,可以用后两种方式(没测过)
/**
* 创建surfaceView
* 隐藏拍照需要有个容器来预览。
*/
private void createsurfaceView() {
/*获取手机分辨率*/
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
BaseLog.w("当前手机的分辨率宽" + width + "高度" + height);
surfaceView = new SurfaceView(mActivity);
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
/*设置Surface分辨率为手机的分辨率*/
surfaceView.getHolder().setFixedSize(width, height);
/*自定义设置Surface分辨率*/
/*surfaceView.getHolder().setFixedSize(6921,4052);*/
surfaceView.getHolder().setSizeFromLayout();
/*屏幕常亮*/
surfaceView.getHolder().setKeepScreenOn(true);
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
/*创建camera对象 open(1)标识开启前置摄像头 为空开启的是后置摄像头*/
camera = Camera.open(1);
/*设置用于显示拍照影像的SurfaceHolder对象*/
camera.setPreviewDisplay(holder);
cameraRotation = setCameraDisplayOrientation(mActivity, 1, camera);
camera.setDisplayOrientation(cameraRotation);
BaseLog.w("camera旋转的角度是:cameraRotation=" + cameraRotation);
try {
Camera.Parameters parameters = camera.getParameters();
/*
* mActivity.getResources().getConfiguration().orientation = 1 竖屏
* mActivity.getResources().getConfiguration().orientation = 2 横屏
* 个人理解:
* portrait 人像拍摄模式:
* 1.手机竖屏拍摄,图片竖直保存
* 2.手机横屏拍摄,图片竖直保存
* landscape 风景模式
* 1.手机竖屏拍摄,图片横向保存
* 2.手机横屏拍摄,图片横向保存
* (个人并未具体实验)
* */
BaseLog.w("orientation=" + mActivity.getResources().getConfiguration().orientation);
BaseLog.w("ORIENTATION_LANDSCAPE=" + Configuration.ORIENTATION_LANDSCAPE);
if (mActivity.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
/*这是一个众所周知但未文档化的特性*/
parameters.set("orientation", "portrait");
} else {
/*这是一个众所周知但未文档化的特性*/
parameters.set("orientation", "landscape");
}
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
camera.release();
/*打印异常*/
BaseLog.w("IOException = " + exception.getMessage());
}
/*开始预览*/
camera.startPreview();
/*自动对焦*/
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
/*只有加上了这一句,才会自动对焦。*/
camera.cancelAutoFocus();
}
}
});
/*调用拍照事件*/
takepicture();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
/*设置这个surfaceView 宽高为1像素,用户基本不可见*/
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(1, 1);
surfaceView.setLayoutParams(lp);
/*我是动态创建的,放到指定的view里*/
mRootContentFuncamera.addView(surfaceView);
}
/**
*获取旋转surfaceView预览的角度(这个方法在api里有,我做了些小改动 API:android.hardware.Camera 1525行-1583行)
*
* @param activity
* @param cameraId
* @param camera
*/
public int setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
BaseLog.w("info.orientation = " + info.orientation);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
bitmapRotation = info.orientation;
return result;
}
/**
* 隐藏拍照事件
*/
private void takepicture() {
if (camera == null) {
BaseLog.w("camera == null");
return;
}
/*
*第一个参数必须是null, 如果你new出来了,就算里面满什么都没写也会有快门声“咔嚓”,估计修改快门音乐也是在这里
*/
camera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
/*获取得到的bitmap对象*/
BaseLog.w("mBitmap旋转的角度是:bitmapRotation=" + bitmapRotation);
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
mImgShowFuncamera.setImageBitmap(rotateBitmap(mBitmap, bitmapRotation));
}
});
}
/**
* 旋转图片
*
* @param bitmap
* @param degress
* @return
*/
public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
if (bitmap != null) {
Matrix m = new Matrix();
m.postRotate(degress);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
}
问题
按照上面的方法细心的朋友会发现有些问题
- 有些朋友拍照之后,设置到img上的图方向不对
- 你横着拿手机拍的照,方向怎么都不对
关于这方面我也找了一些资料,也在网上尝试了一些方法,但是一直没找到合适的解决方案,如果谁有解决方法也可以下面贴出来,大家一起学习!
网友评论