@Tyhj
2018-05-19T17:02:06.000000Z
字数 1857
阅读 1775
Android
一般拍照调用系统相机就可以了,不过不同系统的相机可能有所差异,有些特殊的设备的系统相机可能根本调不起来或者没有系统相机,又或者拍照的时候不需要用户手动操作,这个时候就需要自定义相机了
最近做一个APP需要频繁的调用相机,类似后台拍照那种,可能在任何时候拍照或者拍视频,还有改变预览画面的大小,使用的是老版的相机API,发现在相机重启的时候容易出问题
这里使用一个系统悬浮窗(surfaceView)来预览画面,在service里面调用相机就可以在任何时候拍照了,通过设置和更新悬浮窗的大小可以实现预览画面的显示和隐藏
//创建悬浮窗
CameraService.class
public static WindowManager mWindowManager;
SurfaceView videoFloat;
WindowManager.LayoutParams wmParams;
public int cameraWidth = 1;
public int cameraHeight = 1;
public void createFloatWindow(Context context) {
WindowManager windowManager = getWindowManager(context);
if (videoFloat != null) {
windowManager.removeView(videoFloat);
//windowManager.removeViewImmediate(videoFloat);
}
wmParams = new WindowManager.LayoutParams();
wmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
//设置图片格式,效果为背景透明
wmParams.format = PixelFormat.RGBA_8888;
//设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)
wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
//调整悬浮窗显示的停靠位置为左侧置顶
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
wmParams.verticalMargin = 0;
//以屏幕左上角为原点,设置x、y初始值,相对于gravity
wmParams.x = 0;
wmParams.y = 0;
//设置悬浮窗口长宽数据
wmParams.width = cameraWidth;
wmParams.height = cameraHeight;
videoFloat = new SurfaceView(this);
videoFloat.getHolder().setFormat(PixelFormat.TRANSLUCENT);
windowManager.addView(videoFloat, wmParams);
}
//更新悬浮窗大小
private void setWmParams() {
wmParams.width = cameraWidth;
wmParams.height = cameraHeight;
getWindowManager(this).updateViewLayout(videoFloat, wmParams);
}
重启相机的时候需要先关闭相机,然后重新设置预览的surfaceView,再重新开启相机,如果是直接用之前的surfaceView那么相机会出现打不开的情况
然后如果先移除surfaceView,再重新初始化surfaceView,使用这个surfaceView打开相机,类似上面的代码,发现还是不行
但是如果直接重新创建一个surfaceView,添加到悬浮窗,然后使用它打开相机是可以的
问题就出在移除surfaceView这里,windowManager移除view有两种方法,根据上面的名字可以看出,removeViewImmediate是马上移除的意思那另一个可能就不会马上移除窗口,用这种方法然后重新初始化surfaceView再打开相机是没问题的
应该不会冲突,还没有试过