@Tyhj
2018-05-19T09:02:06.000000Z
字数 1857
阅读 2027
Android
一般拍照调用系统相机就可以了,不过不同系统的相机可能有所差异,有些特殊的设备的系统相机可能根本调不起来或者没有系统相机,又或者拍照的时候不需要用户手动操作,这个时候就需要自定义相机了
最近做一个APP需要频繁的调用相机,类似后台拍照那种,可能在任何时候拍照或者拍视频,还有改变预览画面的大小,使用的是老版的相机API,发现在相机重启的时候容易出问题
这里使用一个系统悬浮窗(surfaceView)来预览画面,在service里面调用相机就可以在任何时候拍照了,通过设置和更新悬浮窗的大小可以实现预览画面的显示和隐藏
//创建悬浮窗CameraService.classpublic 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初始值,相对于gravitywmParams.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再打开相机是没问题的
应该不会冲突,还没有试过
