实现思路

1、将Activity移动到后台

2、取出用于展示视频通话的View

3、开启服务,将视频通话的View显示在屏幕上

4、关闭服务,将视频通话的View重现添加进Activity

实现步骤

1、AndroidMainfest.xml中声明权限

//允许系统弹窗

2、设置中打开悬浮窗权限

(1)在打开悬浮窗前判断是否在设置中允许了悬浮窗权限

8cce0c7ca6ec

if (Build.VERSION.SDK_INT >=23 && !Settings.canDrawOverlays(getApplicationContext())) {

//启动Activity让用户授权

Intent intent =new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,

Uri.parse("package:" + getPackageName()));

startActivityForResult(intent, 10);

return;

}

//如果已有权限,正常打开悬浮窗

(2)在onActivityResult中判断是否打开了权限

8cce0c7ca6ec

3、开启悬浮窗

8cce0c7ca6ec

//最小化Activity

moveTaskToBack(true);

//保存视频View的引用

Constents.mVideoViewLayout =mLayoutManagerTrtc;

//开启服务显示悬浮框

Intent floatVideoIntent =new Intent(this, FloatVideoWindowService.class);

mServiceBound = bindService(floatVideoIntent, mVideoCallServiceConnection, Context.BIND_AUTO_CREATE);

4、FloatVideoWindowService 代码

/**

* 视频通话悬浮窗 服务

*/

public class FloatVideoWindowService extends Service {

public static final String TAG = FloatVideoWindowService.class.getSimpleName();

private WindowManager mWindowManager;

private WindowManager.LayoutParams wmParams;

private LayoutInflater  inflater;

//浮动布局view

private View  mFloatingLayout;

//返回的按钮

private View mCancelView;

//存放视频的父View

private FrameLayout  mVideoView;

//触摸移动的view  触摸事件已被视频控件持有并使用。防止再次放到Activity时候出问题

private View  mTouchView;

@Override

public void onCreate() {

super.onCreate();

initWindow();//设置悬浮窗基本参数(位置、宽高等)

}

@Nullable

@Override

public IBinderonBind(Intent intent) {

initFloating();//悬浮框点击事件的处理

return new MyBinder();

}

public class MyBinder extends Binder {

public FloatVideoWindowService getService() {

return FloatVideoWindowService.this;

}

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

return super.onStartCommand(intent, flags, startId);

}

@Override

public void onDestroy() {

if (mFloatingLayout !=null) {

// 移除悬浮窗口

mWindowManager.removeView(mFloatingLayout);

mFloatingLayout =null;

Constents.isShowFloatWindow =false;

}

super.onDestroy();

}

/**

* 设置悬浮框基本参数(位置、宽高等)

*/

private void initWindow() {

mWindowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);

//设置好悬浮窗的参数

wmParams = getParams();

// 悬浮窗默认显示以左上角为起始坐标

wmParams.gravity = Gravity.LEFT | Gravity.TOP;

//悬浮窗的开始位置,因为设置的是从左上角开始,所以屏幕左上角是x=0;y=0

wmParams.x =70;

wmParams.y =210;

//得到容器,通过这个inflater来获得悬浮窗控件

inflater = LayoutInflater.from(getApplicationContext());

// 获取浮动窗口视图所在布局

mFloatingLayout =inflater.inflate(R.layout.alert_float_video_layout, null);

// 添加悬浮窗的视图

mWindowManager.addView(mFloatingLayout, wmParams);

}

private WindowManager.LayoutParams getParams() {

wmParams =new WindowManager.LayoutParams();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

}else {

wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;

}

//设置可以显示在状态栏上

wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |         WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |

WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |          WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |

WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;

//设置悬浮窗口长宽数据

wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;

wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

return wmParams;

}

private void initFloating() {

mCancelView =mFloatingLayout.findViewById(R.id.float_video_cancel);

mVideoView =mFloatingLayout.findViewById(R.id.float_video_content);

mTouchView =mFloatingLayout.findViewById(R.id.float_video_touch);

//腾讯视频布局管理者

TRTCVideoLayoutManager mTRTCVideoViewLayout = Constents.mVideoViewLayout;

if (mTRTCVideoViewLayout ==null) {

QLog.i(TAG, "没有找到VideoView");

return;

}

if (mTRTCVideoViewLayout.getParent() !=null) {

((ViewGroup) mTRTCVideoViewLayout.getParent()).removeView(mTRTCVideoViewLayout);

ViewGroup.LayoutParams layoutParams = mTRTCVideoViewLayout.getLayoutParams();

layoutParams.width = ScreenUtil.getPxByDp(80);

layoutParams.height = ScreenUtil.getPxByDp(120);

mVideoView.addView(mTRTCVideoViewLayout);

}

Constents.isShowFloatWindow =true;

//悬浮框点击事件

mCancelView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//在这里实现点击重新回到Activity

Intent intent =new Intent(FloatVideoWindowService.this, TRTCVideoCallActivity.class);

startActivity(intent);

}});

//悬浮框触摸事件,设置悬浮框可拖动

mTouchView.setOnTouchListener(new FloatingListener());

mTouchView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

}});}

//开始触控的坐标,移动时的坐标(相对于屏幕左上角的坐标)

private int mTouchStartX, mTouchStartY, mTouchCurrentX, mTouchCurrentY;

//开始时的坐标和结束时的坐标(相对于自身控件的坐标)

private int mStartX, mStartY, mStopX, mStopY;

//判断悬浮窗口是否移动,这里做个标记,防止移动后松手触发了点击事件

private boolean isMove;

private class FloatingListener  implements View.OnTouchListener {

@Override

public boolean onTouch(View v, MotionEvent event) {

int action = event.getAction();

switch (action) {

case MotionEvent.ACTION_DOWN:

isMove =false;

mTouchStartX = (int) event.getRawX();

mTouchStartY = (int) event.getRawY();

mStartX = (int) event.getX();

mStartY = (int) event.getY();

break;

case MotionEvent.ACTION_MOVE:

mTouchCurrentX = (int) event.getRawX();

mTouchCurrentY = (int) event.getRawY();

wmParams.x +=mTouchCurrentX -mTouchStartX;

wmParams.y +=mTouchCurrentY -mTouchStartY;

if (mWindowManager ==null ||mFloatingLayout ==null ||wmParams ==null) {

return false;

}

mWindowManager.updateViewLayout(mFloatingLayout, wmParams);

mTouchStartX =mTouchCurrentX;

mTouchStartY =mTouchCurrentY;

break;

case MotionEvent.ACTION_UP:

mStopX = (int) event.getX();

mStopY = (int) event.getY();

if (Math.abs(mStartX -mStopX) >=1 || Math.abs(mStartY -mStopY) >=1) {

isMove =true;

}

break;

default:

break;

}

//如果是移动事件不触发OnClick事件,防止移动的时候一放手形成点击事件

return isMove;

}}}

5、在Activity的onRestart()中,关闭服务。添加视频View

8cce0c7ca6ec

//不显示悬浮框

if (mServiceBound) {

unbindService(mVideoCallServiceConnection);

mServiceBound =false;

}

if (mLayoutManagerTrtc !=null &&mLayoutManagerTrtc.getParent() !=null) {

//先移除视频View的父布局,才能添加进Activity的根布局

((ViewGroup)mLayoutManagerTrtc.getParent()).removeView(mLayoutManagerTrtc);

//设置视频View的宽高

ViewGroup.LayoutParams layoutParams =mLayoutManagerTrtc.getLayoutParams();

layoutParams.width = ConstraintLayout.LayoutParams.MATCH_PARENT;

layoutParams.height = ConstraintLayout.LayoutParams.MATCH_PARENT;

//获取Activity的根布局

View childAt = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);

//将视频View添加进Activity的根布局

((ConstraintLayout) childAt).addView(mLayoutManagerTrtc, 0);

}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐