我所说的粘滞是指不会通过调用启动器意图(intent.addCategory(Intent.CATEGORY_HOME
)来关闭的窗口。
以前这是使用WindowManager.LayoutParams.TYPE_PHONE
完成的,但现在不建议使用此类型,并在API28上抛出异常:
窗口管理器$BadTokenException ...窗口类型2002的权限被拒绝
这种行为仍然是可能的,因为facebook的Messenger是通过它的聊天"Heads“来实现的,这是基于facebook没有获得系统应用权限的假设,因为它预先安装在很多roms上。
使用WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
不起作用(例如,按下主页按钮也会隐藏覆盖窗口)。
编辑:问题是如何让覆盖窗口在用户单击主页按钮/调用启动器意图时不会被移除。这不适用于TYPE_APPLICATION_OVERLAY
,它适用于TYPE_PHONE
,但已被弃用。
编辑2:显然这对某些人是有效的,这是我正在运行的代码:
class MyClass {
var params: WindowManager.LayoutParams = WindowManager.LayoutParams(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
else WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT
).apply {
windowAnimations = android.R.style.Animation_Dialog
gravity = Gravity.CENTER or Gravity.CENTER
x = 0
y = 0
}
var windowManager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
init {
val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
rootView = layoutInflater.inflate(R.layout.view_overlay, null)
windowManager.addView(rootView, params)
}
}
发布于 2019-04-07 01:15:37
解决方案:不要直接在其他应用程序上膨胀你的覆盖。
正常情况下,使用TYPE_APPLICATION_OVERLAY
仍然像TYPE_PHONE
一样,我的问题是,当来自另一个应用程序的活动在前台时,我正在显示我的视图(windowManager.addView(rootView, params)
),而安卓将视图附加到当前的前台活动,所以当用户退出该活动时(例如,通过按下主页按钮),系统也会从我的应用程序中删除覆盖。对我来说,一个解决方案是非常具体的,我没有一个通用的解决方案,但有了这些信息,应该可以帮助人们找到一个。
发布于 2019-03-29 00:04:56
参考:https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html
public static final int TYPE_APPLICATION_OVERLAY
在API级别26中,此常量已被弃用。
用于非系统应用程序。请改用TYPE_APPLICATION_OVERLAY。
窗口类型:电话。These are non-application windows providing user interaction with the phone
(特别是来电)。这些窗口通常放置在所有应用程序的上方,但在状态栏之后。在多用户系统中,在所有用户的窗口中显示。
public static final int TYPE_APPLICATION_OVERLAY
窗口类型:应用程序覆盖窗口显示在所有活动窗口(类型介于FIRST_APPLICATION_WINDOW
和LAST_APPLICATION_WINDOW
之间)之上,但在关键系统窗口(如状态栏或输入法)之下。
系统可以在任何时候改变这些窗口的位置、大小或可见性,以减少用户的视觉混乱,并且还可以管理资源。
需要Manifest.permission.SYSTEM_ALERT_WINDOW
权限。
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
系统将调整具有此窗口类型的进程的重要性,以减少低内存杀手杀死它们的机会。
在多用户系统中,只在拥有用户的屏幕上显示。
我们必须在device Oreo上使用类型应用程序覆盖,或者稍后我们已经有了Manoj Perumarath给出的示例
您需要像这样定义窗口布局参数
//if device is Oreo or latter if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
//or else
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
Manifest.xml
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
//...other stuff
<service
android:name=".serviceClass"
android:enabled="true"
android:exported="false"/>
MainActivity
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, APP_PERMISSION_REQUEST);
}
else
{
//start service
}
读一遍
发布于 2019-03-28 23:45:18
在Manifest
中添加权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
在launcher活动中,您应该请求canDrawOverlays
权限`
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
!Settings.canDrawOverlays(this)) {
//If the draw over permission is not available open the settings screen
//to grant the permission.
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, CODE_DRAW_OVER_OTHER_APP_PERMISSION);
} else {
initializeView();
}
然后在你的服务中
//Inflate the floating view layout
mFloatingView =
LayoutInflater.from(this).inflate(R.layout.layout_floating_widget, null);
int LAYOUT_TYPE;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_PHONE;
}
//Add the view to the window.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG ,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
//Specify the view position
params.gravity = Gravity.TOP | Gravity.LEFT; //Initially view will be added to top-left corner
params.x = 0;
params.y = 100;
//Add the view to the window
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mWindowManager.addView(mFloatingView, params);
当用户按下Home
键时,这不会被忽略。
确保您的浮动小部件被定义为service
,否则当出现内存不足/配置更改之类的问题时,它将无法存活。还要在清单中注册服务
<service
android:name=".MyWidget"
android:enabled="true"
android:exported="false"/>
https://stackoverflow.com/questions/55251502
复制相似问题