In the project, Tencent Cloud Audio and Video that needs to be accessed, it can be displayed in the floating window. The floating window can be dragged and dropped, and the floating window does not affect the focus of other activities.
This great master's articleAndroid based on Tencent Cloud real-time audio and video imitation WeChat video calls minimized suspensionHe talked about displaying the remote video in a floating window during video calls. According to his code, I partially simplified it.
1. The effect of floating window:Click the zoom-out button to load the current remote video into the floating window, and the floating window can be dragged and dropped, without affecting the focus of other interfaces; click the floating window to return to the original Activity
2. To realize the floating window:
Apply for floating window permissions in androidManifest<uses-permission android:name=".SYSTEM_ALERT_WINDOW"/>
Register FloatWindowService in androidManifest
3. Video activity implementation:
- Put activity in the background Key code: moveTaskToBack(true);//Put activity in the background
-Open the floating window
/** * Define the callback for service binding and enable the video call service connection */ private ServiceConnection mVideoCallServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // Obtain the operation object of the service binder = () service; (); } @Override public void onServiceDisconnected(ComponentName name) { } }; /* * Turn on the floating video service */ private void startVideoService() { //Minimize Activity moveTaskToBack(true);//Put activity in the background //Open the service display floating box Intent serviceVideoIntent = new Intent(this, ); mServiceBound = bindService(serviceVideoIntent, mVideoCallServiceConnection, Context.BIND_AUTO_CREATE);//Binding Service }
- At the end of the floating window
//Unbind and destroy related content in onDestroy() and onReStart()if (mServiceBound) { unbindService(mVideoCallServiceConnection);//Unbind mServiceBound = false; }
4. Related codes for floating window implementation:
/** * Video floating window service */ public class FloatWindowService extends Service implements { private WindowManager mWindowManager; private wmParams; private LayoutInflater inflater; //Floating layout view private View mFloatingLayout; //Container parent layout private View mMainVIew; //The coordinates of the start touch, the coordinates when moving (relative to the coordinates in the upper left corner of the screen) private int mTouchStartX, mTouchStartY, mTouchCurrentX, mTouchCurrentY; //The coordinates at the beginning and the coordinates at the end (relative to the coordinates of the own control) private int mStartX, mStartY, mStopX, mStopY; //Judge whether the floating window is moving, make a mark here to prevent the click event from being triggered after releasing the move private boolean isMove; @Override public void onCreate() { (); initWindow();//Set basic parameters of the floating window (position, width, height, etc.) } @Nullable @Override public IBinder onBind(Intent intent) { currentBigUserId = ("localUserId"); remoteUserId = ("remoteUserId"); initFloating();// Handling of floating box click event return new MyBinder(); } public class MyBinder extends Binder { public FloatWindowService getService() { return ; } } @Override public int onStartCommand(Intent intent, int flags, int startId) { return (intent, flags, startId); } @Override public void onDestroy() { (); if (mFloatingLayout != null) { // Remove the floating window (mFloatingLayout); mFloatingLayout = null; } } /** * Set basic parameters of the floating frame (position, width, height, etc.) */ private void initWindow() { mWindowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); //Set the parameters of the floating window wmParams = getParams(); // The floating window is displayed by default with the upper left corner as the starting coordinate = | ; //The start position of the floating window, because it is set to start from the upper right corner, so the upper left corner of the screen is x=the maximum screen value; y=0 = 10; = 120; //Get the container and use this inflater to obtain the floating window control inflater = (getApplicationContext()); // Get the layout where the floating window view is located mFloatingLayout = (.dlg_floatview, null); // Add a view of the floating window (mFloatingLayout, wmParams); } private getParams() { wmParams = new (); if (.SDK_INT >= Build.VERSION_CODES.O) { = .TYPE_APPLICATION_OVERLAY; } else { = .TYPE_PHONE; } //Settings can be displayed on the status bar = .FLAG_NOT_FOCUSABLE | .FLAG_NOT_TOUCH_MODAL | .FLAG_LAYOUT_IN_SCREEN | .FLAG_LAYOUT_INSET_DECOR | .FLAG_WATCH_OUTSIDE_TOUCH; //Set the length and width data of the floating window = .WRAP_CONTENT; = .WRAP_CONTENT; return wmParams; } //Load the remote video: Do this to operate on the contents in the floating window private void initFloating() { //Load the subview into the floating window View mMainView = (.trtc_video_view_layout_float);//Floating window parent layout View mChildView = ();//The subview loaded into the floating window, this VIew comes from the View that needs to be loaded in the Activity that has been turned from heaven. (mChildView);//Put the Viewadd that needs to be suspended into mTXCloudVideoView //The floating frame touch event, set the floating frame to drag (this::onTouch); //Floating box click event (new () { @Override public void onClick(View v) { //Implement here to click back to Activity Intent intent = new Intent(, );// Jumping from the service to the activity will wake the activity from the background, so the activity will go onReStart() (Intent.FLAG_ACTIVITY_NEW_TASK);//Redirecting from Service to RTCActivity requires Intent.FLAG_ACTIVITY_NEW_TASK, otherwise it will crash startActivity(intent); } }); } //Touch Event @Override public boolean onTouch(View v, MotionEvent event) { int action = (); switch (action) { case MotionEvent.ACTION_DOWN: isMove = false; mTouchStartX = (int) (); mTouchStartY = (int) (); mStartX = (int) (); mStartY = (int) (); break; case MotionEvent.ACTION_MOVE: mTouchCurrentX = (int) (); mTouchCurrentY = (int) (); += mTouchStartX - mTouchCurrentX; += mTouchCurrentY - mTouchStartY; ("FloatingListener() onTouch",mTouchCurrentX,mTouchStartX,mTouchCurrentY,mTouchStartY); (mFloatingLayout, wmParams); mTouchStartX = mTouchCurrentX; mTouchStartY = mTouchCurrentY; break; case MotionEvent.ACTION_UP: mStopX = (int) (); mStopY = (int) (); if ((mStartX - mStopX) >= 1 || (mStartY - mStopY) >= 1) { isMove = true; } break; default: break; } //If it is a mobile event, the OnClick event will not be triggered, so as to prevent the click event from being formed when moving. return isMove; } }
ps: Use Service as the carrier for the floating window to associate the opening and closing of the floating frame with the binding and unbinding of the service service. Turning on the service is equivalent to opening our floating frame, and unbinding the service is equivalent to closing the floating frame, so as to achieve better control effect.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.