Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize suspension window by Android

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article will explain in detail how to realize the suspension window in Android. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.

1. Realization principle

1.1 suspension window insertion interface

Before implementing a suspended window, we need to know through what interface we can put a control on the screen. The interface drawing of Android is realized through WindowMananger services. So, since we want to achieve a floating window on an interface other than our own application, we have to use WindowManager to "tamper with".

(frameworks/base/core/java/android/view/WindowMananger.java)

@ SystemService (Context.WINDOW_SERVICE) public interface WindowManager extends ViewManager {...}

WindowManager implements the ViewManager interface, which can be obtained by obtaining WINDOW_SERVICE system services. The ViewManager interface has an addView method, which is how we add the floating window control to the screen.

1.2 permission settings and requests

Dangling windows need to display controls on top of other applications, which obviously requires certain permissions.

When API Level > = 23, you need to declare the permission SYSTEM_ALERT_WINDOW in the AndroidManefest.xml file to draw the control on other applications.

In addition to this permission, we also need to set the floating window permission for this application in the system setup. This permission needs to be started with Settings.ACTION_MANAGE_OVERLAY_PERMISSION in the application to allow the user to set the permission manually.

StartActivityForResult (new Intent (Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse ("package:" + getPackageName ()), REQUEST_CODE)

1.3 LayoutParam Settings

WindowManager's addView method has two parameters, one is the control object that needs to be added, and the other parameter is the WindowManager.LayoutParam object.

What needs to be highlighted here is the type variable in LayoutParam. This variable is used to specify the window type. When setting this variable, you need to pay attention to a pit, that is, you need to adapt different versions of the Android system.

If (Build.VERSION.SDK_INT > = Build.VERSION_CODES.O) {layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;} else {layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;}

Prior to Android 8.0, hovering windows could be set to TYPE_PHONE, a type of non-application window used to provide user interaction. Android 8.0 has made changes to the system and API behavior, including that applications with SYSTEM_ALERT_WINDOW permissions can no longer use the following window types to display reminder windows on top of other applications and windows:

-TYPE_PHONE-TYPE_PRIORITY_PHONE-TYPE_SYSTEM_ALERT-TYPE_SYSTEM_OVERLAY-TYPE_SYSTEM_ERROR

If you need to implement a reminder window on top of other applications and windows, it must be a new type of TYPE_APPLICATION_OVERLAY. If the hovering window of TYPE_PHONE type is still used in Android version 8.0 or later, the following exception message will appear:

Android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@f8ec928-- permission denied for window type 2002

two。 Concrete realization

Next, let's explain the specific implementation of the suspension window.

Complete source address: https://github.com/dongzhong/TestForFloatingWindow

In order to separate the suspension window from Activity, so that the suspension window can still run normally when the application is in the background, Service is used to start the suspension window and act as the logical support behind it. Before starting the service, you need to determine whether the suspension window is currently allowed to open.

(MainActivity.java)

Public void startFloatingService (View view) {... If (! Settings.canDrawOverlays (this)) {Toast.makeText (this, "No permission, Please authorize", Toast.LENGTH_SHORT); startActivityForResult (new Intent (Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse ("package:" + getPackageName ()), 0);} else {startService (new Intent (MainActivity.this, FloatingService.class)) } @ Overrideprotected void onActivityResult (int requestCode, int resultCode, Intent data) {if (requestCode = = 0) {if (! Settings.canDrawOverlays (this)) {Toast.makeText (this, "authorization failure", Toast.LENGTH_SHORT). Show ();} else {Toast.makeText (this, "authorization success", Toast.LENGTH_SHORT). Show (); startService (new Intent (MainActivity.this, FloatingService.class));}

The hovering window control can be a subclass type of any View. Let's start with an example of the simplest Button.

(FloatingService.java)

@ Overridepublic int onStartCommand (Intent intent, int flags, int startId) {showFloatingWindow (); return super.onStartCommand (intent, flags, startId);} private void showFloatingWindow () {if (Settings.canDrawOverlays (this)) {/ / get WindowManager service WindowManager windowManager = (WindowManager) getSystemService (WINDOW_SERVICE); / / New suspension window control Button button = new Button (getApplicationContext ()); button.setText ("FloatingWindow"); button.setBackgroundColor (Color.BLUE) / / set LayoutParam WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams (); if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.O) {layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;} else {layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;} layoutParams.format = PixelFormat.RGBA_8888; layoutParams.width = 500; layoutParams.height = 100; layoutParams.x = 300; layoutParams.y = 300; / / add suspension window controls to WindowManager windowManager.addView (button, layoutParams);}}

All right, it's done!

Yes, I read it right. The simplest suspension window has been realized. Isn't it easy? Let's see how it works.

Of course, the effect of this suspension window is only displayed, which is far from what you really want. However, the basic principle has been realized, and the rest is to add functions a little bit above.

3. Add small functions

3.1 drag function

The first feature you want to add is the ability to drag the suspension window. Because the position of the suspension window may block the information we want to see behind us, it would be best if we could drag the suspension window away. In Android, the handling of touch events is one of the most basic operations, directly on the code.

(FloatingService.java)

Private void showFloatingWindow () {... Button.setOnTouchListener (new FloatingOnTouchListener ());...} private class FloatingOnTouchListener implements View.OnTouchListener {private int x; private int y; @ Override public boolean onTouch (View view, MotionEvent event) {switch (event.getAction ()) {case MotionEvent.ACTION_DOWN: X = (int) event.getRawX (); y = (int) event.getRawY (); break; case MotionEvent.ACTION_MOVE: int nowX = (int) event.getRawX (); int nowY = (int) event.getRawY (); int movedX = nowX-x; int movedY = nowY-y X = nowX; y = nowY; layoutParams.x = layoutParams.x + movedX; layoutParams.y = layoutParams.y + movedY; / / Update suspension window control layout windowManager.updateViewLayout (view, layoutParams); break; default: break;} return false;}}

It is important to note here that the method of updating the layout of the floating window control in the code comments. Only when this method is called will the position of the floating window be changed. Let's see how it works.

3.2 automatic picture playback

Let's make some small changes to the suspension window to demonstrate a slightly more complex interface.

In the floating window interface here, we no longer simply use a Button control, but add an ImageView in a LinearLayout. The layout file is as follows.

(image_display.xml)

Make some changes where you created the floating window layout.

(FloatingService.java)

Private void showFloatingWindow () {... LayoutInflater layoutInflater = LayoutInflater.from (this); displayView = layoutInflater.inflate (R.layout.image_display, null); displayView.setOnTouchListener (new FloatingOnTouchListener ()); ImageView imageView = displayView.findViewById (R.id.image_display_imageview); imageView.setImageResource (images [imageIndex]); windowManager.addView (displayView, layoutParams);...}

We also want to switch pictures every two seconds, so let's do a mechanism to switch pictures on a regular basis.

(FloatingService.java)

@ Overridepublic void onCreate () {... ChangeImageHandler = new Handler (this.getMainLooper (), changeImageCallback);} private Handler.Callback changeImageCallback = new Handler.Callback () {@ Override public boolean handleMessage (Message msg) {if (msg.what = = 0) {imageIndex++; if (imageIndex > = 5) {imageIndex = 0;} if (displayView! = null) {((ImageView) displayView.findViewById (R.id.image_display_imageview)) .setImageResource (images [imageIndex]);} changeImageHandler.sendEmptyMessageDelayed (0, 2000);} return false;}} Private void showFloatingWindow () {... WindowManager.addView (displayView, layoutParams); changeImageHandler.sendEmptyMessageDelayed (0, 2000);}

3.3 Video Mini window

Let's take a look at the most common function of the suspension window: the video mini window. For example, when Wechat exits the interface during the video process, it will display the video in the form of a small window. Here, I will first play a network video with MediaPlay and SurfaceView to simulate the effect. The implementation is basically the same as the picture player above, except that the control and the corresponding playback logic are changed. The layout file is similar to the image player above, except that ImageView is replaced with SurfaceView. Create a floating window control.

(FloatingService.java)

Private void showFloatingWindow () {... MediaPlayer mediaPlayer = new MediaPlayer (); mediaPlayer.setAudioStreamType (AudioManager.STREAM_MUSIC); SurfaceView surfaceView = displayView.findViewById (R.id.video_display_surfaceview); final SurfaceHolder surfaceHolder = surfaceView.getHolder (); surfaceHolder.addCallback (new SurfaceHolder.Callback () {@ Override public void surfaceCreated (SurfaceHolder holder) {mediaPlayer.setDisplay (surfaceHolder);}...); mediaPlayer.setOnPreparedListener (new MediaPlayer.OnPreparedListener () {@ Override public void onPrepared (MediaPlayer mp) {mediaPlayer.start ();}}) Try {mediaPlayer.setDataSource (this, Uri.parse ("https://raw.githubusercontent.com/dongzhong/ImageAndVideoStore/master/Bruno%20Mars%20-%20Treasure.mp4")); mediaPlayer.prepareAsync ();} catch (IOException e) {Toast.makeText (this," unable to open video source ", Toast.LENGTH_LONG). Show ();} windowManager.addView (displayView, layoutParams);}

This is the end of the article on "how to realize the suspension window of Android". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report