WindowManager是Android中一个重要的Service,是全局且唯一的。在Activity和Service中都可以直接使用这个方法来获得WindowManager。其getSystemService返回的是一个WindowManagerImpl对象,这是一个存在于本地进程中的一个对象。而事实是WindowManagerImpl继承了WindowManager,而WindowManger继承了ViewManager。
一、WindowManager
1.获取
wManager = (WindowManager) getApplicationContext().getSystemService(
Context.WINDOW_SERVICE);
2.WindowManager基本方法
(1)窗口添加
public void addView(View view, ViewGroup.LayoutParams params);
(2)窗口更新
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
(3)窗口删除
public void removeView(View view);
3.悬浮窗口需添加权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
4.允许显示在其他应用上方
光有悬浮窗权限还不够,在6.0以上手机还需要在设置里打开一个开关才可使用。
4.1使用反射判断该开关是否打开
/**
* 只适用于大多数手机
* @param context
* @return
*/
public boolean hasPermission(Context context) {
try {
try {
Class clazz = Settings.class;
Method canDrawOverlays = clazz.getDeclaredMethod("canDrawOverlays", Context.class);
return (Boolean) canDrawOverlays.invoke(null, context);
} catch (Exception e) {
}
} catch (Exception e) {
}
return false;
}
4.2 如果是未打开转态,我们需要使用代码引导用户到跳转打开
/**
* 只适用于大多数手机
* @param context
* @return
*/
public void openOverlayPermission(Context context) {
try {
Class clazz = Settings.class;
Field field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION");
Intent intent = new Intent(field.get(null).toString());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);
} catch (Exception e) {
}
}
二.使用windowmanger实现实时悬浮窗
其中悬浮的view具体自己可以随便定义,主要是 WindowManager.LayoutParams的使用配合,尤其是WindowManager.LayoutParams的type在不同版本手机上是不同的,下面给出核心代码
核心方法:
private void showFloatMenuView(final Context context) {
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.width = getScreenWidth();
params.height = getScreenHeight() - getStatusHeight(context);
params.gravity = Gravity.BOTTOM | Gravity.LEFT;
params.x = 0;
params.y = 0;
int versionCode = 24;
if (Build.VERSION.SDK_INT >= versionCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
/*android8.0用*/
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
/*android7.0不能用TYPE_TOAST*/
params.type = WindowManager.LayoutParams.TYPE_PHONE;
}
} else {
/*以下代码块使得android6.0之后的用户不必再去手动开启悬浮窗权限*/
String packname = context.getPackageName();
PackageManager pm = context.getPackageManager();
boolean permission = (PackageManager.PERMISSION_GRANTED ==
pm.checkPermission("android.permission.SYSTEM_ALERT_WINDOW", packname));
if (permission) {
params.type = WindowManager.LayoutParams.TYPE_PHONE;
} else {
params.type = WindowManager.LayoutParams.TYPE_TOAST;
}
}
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.format = PixelFormat.RGBA_8888;
mWindowManager.addView(mFloastMenuView, params);
}