Original title: Share a long confused question: How to judge whether there is a pop-up window on the activity?
Today, let's look at a requirement. How to judge whether there is a pop-up window on the activity? Of course, there must be simple ways, such as recording in the Dialog show. But this way is not elegant enough. We need a more general way to judge.
Android currently has the following pop-up windows:
1. Common application window, such as Dialog.
2. Attach a child window to a common window, such as PopWindow.
3. System window, such as WindowManager type in FIRST_SYSTEM_WINDOW And LAST_SYSTEM_WINDOW between.
Use the diagram to simply understand the relationship between Window and View:
• Activity in attach Phase created PhoneWindow , and set AppToken Store to PhoneWindow Medium, then via createLocalWindowManager A local WindowManager , this instance is WindowManagerImpl , construct the incoming parentWindow by PhoneWindow 。 stay onResume Phase, from PhoneWindow Get in WindowManager come addView 。
• Dialog has its own PhoneWindow , but Dialog does not PhoneWindow Middle Go get WindowManager , but directly getSystemService Get the activity's WindowManager come addView 。
• PopWindow Internally, through getSystemService Come and get it Activity WindowManager +Pop up frame implemented by built-in sub window type.
one
Scheme 1. Judge by the activity interval in the mView set
From the above, we can simply understand that all window views of the current process will eventually be stored in WindowManagerGlobal In the mViews collection of a single example, can we start from the mView collection? Let's draw a storage diagram of mView:
When WindowManager addView is added, it will be added to the mView collection. Therefore, we only need to determine whether there are other views between two activities in the mView collection. If there are, there is a pop-up window. The development steps are as follows:
one registerActivityLifecycleCallbacks Get instances of all activities.
2. Pass in the target activity instance that you want to judge whether there is a pop-up window, and get the DecorView of the instance.
3. Get the DecorView collection of all activity instances.
4. Traverse the mView collection and determine whether the view in the mView is consistent with the DecorView of the target activity. If yes, it indicates that the index position of the activity has been found.
5. Next, continue to traverse the mView from the position of index+1 to determine whether the view in the mView is an instance in the DecorView collection. If not, it means that it is not an activity view. Continue to traverse until the view is an instance in the DecorView collection.
Some codes are implemented as follows:
fun hasFloatingWindowByView (activity: Activity ) : Boolean {
return getFloatWindowView(activity).isNotEmpty
}
fun getFloatWindowByView (activity: Activity ) : List<View> {
//Corresponding step 2
val targetDecorView = activity.window.decorView
//Corresponding step 3
val acDecorViews = lifecycle.getActivities.map { it.window.decorView }.toList
//Corresponding step 4
val mView = Window.getViews.map { it }.toList
val targetIndex = mView.first { it == targetDecorView }
//Corresponding step 5
val index = mView.indexOf(targetIndex)
val floatView = arrayListOf<View>
for (i in index + one until mView.size) {
if (acDecorViews.contains(mView[i])) {
break
}
floatView.add(mView[i])
}
return floatView
}
For specific demonstration, please refer to Demo. Here are the disadvantages of this scheme. Because mView is a list collection, every time a new View is added, press ArrayList.add To add a View, if we trigger the first activity to display the Dialog when starting the second activity, the display effect is as follows:
At this time, if the first activity is used to judge whether there is a pop-up window, there is a misjudgment, because there is no other view between the two activities at this time.
Therefore, there are still shortcomings in judging by intervals. Is there a way to directly traverse the mView collection to find the target activity? There is an AppToken.
two
Scheme II: Judge by AppToken
In the concept at the beginning of the article, we learned that PopWindow and Dialog use Activity WindowManager , and the WindowManager On initial creation, the constructor passes in the parentWindow by PhoneWindow , this parentWindow It's important because WindowManagerGlobal Of addView In the method, he will pass parentWindow Come and get it AppToken , then set to WindowManager. LayoutParams And participate in the final interface presentation. Let's take a look at the settings AppToken Code of:
parentWindow by PhoneWindow , is not empty, so it will enter PhoneWindow Of the parent class Window adjustLayoutParamsForSubWindow method:
one Sub window judgment : Get DecorView Inside WindowToken Set to the wp parameter. This DecorView In the Activity PhoneWindow DecorView , so the windowToken Activity's DecorView I got it in.
two System pop-up judgment : Do not set the token. The token parameter in wp is null.
three Common pop-up judgment : will AppToken Directly set to wp parameters. This AppToken In the Activity PhoneWindow AppToken 。
Through these three judgments, we know that the sub window's windowToken With ordinary pop-up window AppToken They can all be linked to activities. Now, you can find them through the target activity. As for the system pop-up window, we only need the token to be null.
The wp will eventually be added to the mParams collection. It corresponds to the mView and mRoot indexes one by one:
Draw a simple diagram to summarize:
And then combine adjustLayoutParamsForSubWindow The following development steps are described for the setting of token:
1. Pass in the target activity instance that you want to judge whether there is a pop-up window, and get the DecorView And windowToken 。
2. Get the mView collection according to the target activity's DecorView Find the index location.
3. Because mView and mParams set are one-to-one, you can find the target activity's AppToken 。
4. Traverse all the tokens in the mParams set to determine whether the token is the target windowToken , the target AppToken is either null, as long as it can hit, it means there is a pop-up window.
Some codes are implemented as follows:
fun hasFloatWindowByToken (activity: Activity ) : Boolean {
//Get the decorView of the target activity
val targetDecorView = activity.window.decorView
//Get the windowToken of the target activity
val targetSubToken = targetDecorView.windowToken
//Get the mView collection and find the index location of the target activity
val mView = Window.getViews.map { it }.toList
val targetIndex = mView.indexOfFirst { it == targetDecorView }
//Get mParams collection
val mParams = Window.getParams
//Find the target token from the mParams collection according to the target index
val targetToken = mParams[targetIndex].token
//When traversing the judgment, the target activity itself cannot be included, so the size needs to be greater than 1
return mParams
.map { it.token }
.filter { it == targetSubToken || it == null || it == targetToken }
.size > one
}
Demonstration steps:
Open the system pop-up window in the first activity, and then enter the second activity. Call two methods to get the result of whether there is a pop-up window:
The first scheme will fail to judge, because the pop-up view at this time is between the first activity and the second activity, so the second activity cannot judge whether there is a pop-up window by interval.
The second scheme is successful because the pop-up token is null and passes getFloatWindowViewByToken Method to get the pop-up View object.
three
summary
This issue explores the feasibility of the scheme by putting forward requirements. For boring source code, it is really a good idea to take a targeted look.
Attach the demo source code:
//github.com/MRwangqi/FloatingWindow
Finally, I would like to recommend my website to play Android: wanandroid.com , including a detailed knowledge system, easy-to-use tools, and a collection of articles on this public account, welcome to experience and collect!
:
Android Technology Weekly (Issue 11): New technology initiatives are coming again? 23
What is the accessibility permission used in the Hotlink App Appraisal | "Li Tiaotiao"?
What is the significance of MVI?
scan Follow my public account
If you want to share your article with everyone, you are welcome to contribute~
Shit! See you tomorrow! Go back to Sohu to see more
Editor in charge: