兼容8.0,小米,魅族,华为等难适配机型都可完美适配。
https://github.com/czy1121/settingscompat
悬浮窗插入接口
在实现悬浮窗之前,我们需要知道通过什么接口,能够将一个控件放入到屏幕中去。 Android的界面绘制,都是通过WindowMananger的服务来实现的。那么,既然要实现一个能够在自身应用以外的界面上的悬浮窗,我们就要利用WindowManager来“做手脚”。
(frameworks/base/core/java/android/view/WindowMananger.java) @SystemService(Context.WINDOW_SERVICE)public interface WindowManager extends ViewManager { ...}
WindowManager实现了ViewManager接口,可以通过获取WINDOW_SERVICE系统服务得到。而ViewManager接口有addView方法,我们就是通过这个方法将悬浮窗控件加入到屏幕中去。
权限设置及请求
悬浮窗需要在别的应用之上显示控件,很显然,这需要某些权限才可以。 在API Level >= 23的时候,需要在AndroidManefest.xml文件中声明权限SYSTEM_ALERT_WINDOW才能在其他应用上绘制控件。
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
除了这个权限外,我们还需要在系统设置里面对本应用进行设置悬浮窗权限。该权限在应用中需要启动Settings.ACTION_MANAGE_OVERLAY_PERMISSION来让用户手动设置权限。
startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), REQUEST_CODE);
LayoutParam设置
WindowManager的addView方法有两个参数,一个是需要加入的控件对象,另一个参数是WindowManager.LayoutParam对象。
这里需要着重说明的是LayoutParam里的type变量。这个变量是用来指定窗口类型的。在设置这个变量时,需要注意一个坑,那就是需要对不同版本的Android系统进行适配。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;} else { layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;}
在Android 8.0之前,悬浮窗口设置可以为TYPE_PHONE,这种类型是用于提供用户交互操作的非应用窗口。
而Android 8.0对系统和API行为做了修改,包括使用SYSTEM_ALERT_WINDOW权限的应用无法再使用一下窗口类型来在其他应用和窗口上方显示提醒窗口:
TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR
如果需要实现在其他应用和窗口上方显示提醒窗口,那么必须该为TYPE_APPLICATION_OVERLAY的新类型。 如果在Android 8.0以上版本仍然使用TYPE_PHONE类型的悬浮窗口,则会出现如下异常信息:
android.view.WindowManagerW@f8ec928 -- permission denied for window type 2002
附悬浮相关,转载文章
推荐看看这个demo,star不多。有吸附,点击展开,定时缩小,交互体验不错
https://github.com/pengjianbo/FloatViewFinal
跳转系统设置界面开启权限库:
https://github.com/czy1121/settingscompat
star多,比较新