一、WindowManagerSurfaceView实现预览和移动窗口流程
1、新建一个布局文件layout_window.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linear"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_height="400dp">
<SurfaceView
android:id="@+id/surface_view_camera2_activity"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
2、在AndroidManifest.xml中添加悬浮窗口权限和添加服务
//添加权限
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
//添加服务
<service android:name="wq.com.camerademo.MyService" >
</service>
3、代码实现(添加一个按钮,点击按钮后弹出窗口实现Camera预览效果)
public class MyService extends Service {
private static final String TAG = "MyService";
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private ImageView iv_show;
private CameraManager mCameraManager;//摄像头管理器
private Handler childHandler, mainHandler;
private String mCameraID;//摄像头Id 0 为后 1 为前
private ImageReader mImageReader;
private CameraCaptureSession mCameraCaptureSession;
private CameraDevice mCameraDevice;
private WindowManager.LayoutParams wmParams;
private WindowManager mWindowManager;
private View mWindowView;
private LinearLayout mText;
private Context context;
private int mStartX;
private int mStartY;
private int mEndX;
private int mEndY;
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind()");
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate()");
context = this;
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand()");
initWindowParams();
initView();
addWindowViewZWindow();
initClick();
return super.onStartCommand(intent, flags, startId);
}
// 调用startService方法启动Service时调用该方法
@Override
public void onStart(Intent intent, int startId) {
Log.e(TAG, "onStart()");
}
@Override
public void onDestroy() {
super.onDestroy();
if (mWindowView != null) {
//移除悬浮窗口
Log.i(TAG, "removeView");
mWindowManager.removeView(mWindowView);
}
Log.e(TAG, "onDestroy()");
}
/**
* 初始化Window对象的参数
*/
private void initWindowParams() {
Log.e(TAG, "initWindowParams()");
//1,获取系统级别的WindowManager
mWindowManager = (WindowManager) getApplication().getSystemService(getApplication().WINDOW_SERVICE);
wmParams =new WindowManager.LayoutParams();
//2,添加系统参数,确保悬浮框能显示到手机上
//电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
// flag 设置 Window 属性
wmParams.flags
|= WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
//期望的位图格式。默认为不透明
wmParams.format = PixelFormat.TRANSLUCENT;
//不许获得焦点
wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
//窗口停靠位置
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
}
/**
* 添加布局view,初始控件
*/
private void initView() {
Log.e(TAG, "initView()");
mWindowView = LayoutInflater.from(getApplication()).inflate(R.layout.layout_window, null);
mText = (LinearLayout) mWindowView.findViewById(R.id.linear);
mSurfaceView = (SurfaceView)mWindowView. findViewById(R.id.surface_view_camera2_activity);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setKeepScreenOn(true);
// mSurfaceView添加回调
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
Log.e(TAG,"surfaceCreated()");
// 初始化Camera
initCamera2();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e(TAG,"surfaceChanged()");
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
Log.e(TAG,"surfaceDestroyed()");
// 释放Camera资源
if (null != mCameraDevice) {
mCameraDevice.close();
MyService.this.mCameraDevice = null;
}
}
});
}
/**
* 添加View到桌面Window界面上
*/
private void addWindowViewZWindow() {
Log.e(TAG, "addWindowViewZWindow()");
mWindowManager.addView(mWindowView, wmParams);
}
/**
* 点击事件和拖拽事件
*/
private void initClick() {
mText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
//按下鼠标的时候记录下屏幕的位置
case MotionEvent.ACTION_DOWN:
mStartX = (int) event.getRawX();
mStartY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
mEndX = (int) event.getRawX();
mEndY = (int) event.getRawY();
if (needIntercept()) {
//getRawX是触摸位置相对于整个屏幕的位置,getX是控触摸点相对于控件最左边的位置
wmParams.x = (int) event.getRawX() - mWindowView.getMeasuredWidth() / 2;
wmParams.y = (int) event.getRawY() - mWindowView.getMeasuredHeight() / 2;
mWindowManager.updateViewLayout(mWindowView, wmParams);
return true;
}
break;
case MotionEvent.ACTION_UP:
if (needIntercept()) {
return true;
}
break;
}
return false;
}
});
mText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "点击了");
if (isAppAtBackground(MyService.this)) {
Intent intent = new Intent(MyService.this, TestActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
});
}
/**
* 判断当前应用是前台还是后台
*/
private boolean isAppAtBackground(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
/**
* 判断是否拦截,根据滑动的距离
*
* @return
*/
private boolean needIntercept() {
if (Math.abs(mStartX - mEndX) > 30 || Math.abs(mStartY - mEndY) > 30) {
return true;
}
return false;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void initCamera2() {
HandlerThread handlerThread = new HandlerThread("Camera2");
handlerThread.start();
childHandler = new Handler(handlerThread.getLooper());
mainHandler = new Handler(getMainLooper());
mCameraID = "" + CameraCharacteristics.LENS_FACING_FRONT;//后摄像头
mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG,1);
//ImageReader这个类被允许直接从Surface接收渲染的图像数据
//可以在这里处理拍照得到的临时照片 例如,写入本地
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Log.e(TAG,"onImageAvailable()");
mCameraDevice.close();
mSurfaceView.setVisibility(View.GONE);
//iv_show.setVisibility(View.VISIBLE);
// 拿到拍照照片数据
Image image = reader.acquireNextImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);//由缓冲区存入字节数组
final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
if (bitmap != null) {
// iv_show.setImageBitmap(bitmap);
}
}
}, mainHandler);
//获取摄像头管理
mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
//打开摄像头
mCameraManager.openCamera(mCameraID, stateCallback, mainHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
/**
* 摄像头创建监听
*/
private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onOpened(CameraDevice camera) {//打开摄像头
Log.e(TAG,"onOpened()");
mCameraDevice = camera;
//开启预览
takePreview();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onDisconnected(CameraDevice camera) {//关闭摄像头
Log.e(TAG,"onDisconnected()");
if (null != mCameraDevice) {
mCameraDevice.close();
MyService.this.mCameraDevice = null;
}
}
@Override
public void onError(CameraDevice camera, int error) {//发生错误
Log.e(TAG,"onError()");
Toast.makeText(MyService.this, "摄像头开启失败", Toast.LENGTH_SHORT).show();
}
};
/**
* 开始预览
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void takePreview() {
Log.e(TAG,"takePreview()");
try {
// 创建预览需要的CaptureRequest.Builder
final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
// 将SurfaceView的surface作为CaptureRequest.Builder的目标
previewRequestBuilder.addTarget(mSurfaceHolder.getSurface());
// 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() // ③
{
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
Log.e(TAG,"onConfigured()");
if (null == mCameraDevice) return;
// 当摄像头已经准备好时,开始显示预览
mCameraCaptureSession = cameraCaptureSession;
try {
// 自动对焦
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// 打开闪光灯
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
// 显示预览
CaptureRequest previewRequest = previewRequestBuilder.build();
mCameraCaptureSession.setRepeatingRequest(previewRequest, null, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
Log.e(TAG,"onConfigureFailed()");
Toast.makeText(MyService.this, "配置失败", Toast.LENGTH_SHORT).show();
}
}, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
4、效果图如下所示