微信号:guolin_blog

介绍:Android技术分享平台,在这里不仅可以学到各种Android相关的最新技术,还可以将你自己的技术总结分享给其他人,每周定期更新.

教你如何在Android 6.0上创建系统悬浮窗

2016-05-24 07:37 郭霖

今天周二,又该跟大家分享由我执笔的文章了。从之前我写的deep links、通知栏微技巧这两篇文章中,大家应该能明显体会出什么叫短小精炼,但又很有技术价值的文章。后面我还会坚持分享这种类型的文章,尽量让大家十分钟内就可以读完,并且还能有所收获。




在Android上创建系统悬浮窗并不是什么新鲜技术,我人生第一篇博客就是写的关于如何实现类似于360手机卫士悬浮窗的功能,大家有兴趣的可以到 http://guolin.tech 去翻翻历史。不过如果你将项目的targetSdkVersion指定成23或者更高,你会发现之前创建悬浮窗的方式在Android 6.0系统上是无法运行的。不信的话我们就来试试。


首先建立一个非常非常简单的自定义View:

public class FloatView extends Button {    
   public FloatView(Context context) {
       super(context);        setBackgroundResource(R.drawable.logo);    } }

然后在程序中调用如下代码就可以创建出系统悬浮窗了:

public void showFloatView() {
   WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
   FloatView floatView = new FloatView(getApplicationContext());
   WindowManager.LayoutParams params = new WindowManager.LayoutParams();    params.type = WindowManager.LayoutParams.TYPE_PHONE;    params.format = PixelFormat.RGBA_8888;    params.gravity = Gravity.LEFT | Gravity.TOP;    params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;    params.width = 150;    params.height = 150;    params.x = 0;    params.y = 0;    windowManager.addView(floatView, params); }

上面的代码简单易懂,就不再进行解释了,如果对这部分代码还不理解的朋友请去参考我的历史第一篇博文好好学习一下。


最后还需要在AndroidManifest.xml中添加一个权限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

没错,就是这么简单,现在这段代码就已经可以成功创建出一个系统悬浮窗了,不过是在Android 6.0系统之前。


如果我们在6.0系统中运行上述代码(注意targetSdkVersion要指定顾23),程序就会直接崩溃,错误日志如下图所示:




咦?报了个权限被拒绝的错误,可是我们已经在AndroidManifest.xml中申请权限了,并且SYSTEM_ALERT_WINDOW权限也不是危险权限,并不需要进行运行时权限申请。


那么为什么在6.0系统上就会崩溃呢,我们来查看一下官方文档的描述吧:


Note: If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen. The app requests the user's approval by sending an intent with action ACTION_MANAGE_OVERLAY_PERMISSION. The app can check whether it has this authorization by calling Settings.canDrawOverlays().


能够熟练阅读各类英文文档也是一门非常重要的技能。上面的描述大概意思就是说,如果我们的targetSdkVersion指定成了23或者更高,在使用SYSTEM_ALERT_WINDOW权限时,需要先调用Settings.canDrawOverlays()来判断一下是否允许创建悬浮窗,如果允许的话就可以创建了,不允许的话还要发送一个action值为ACTION_MANAGE_OVERLAY_PERMISSION的Intent来让用户同意创建悬浮窗。


针对文档的描述,我们需要将代码改成下面这个样子:

public void buttonClick(View view) {
   if (Build.VERSION.SDK_INT >= 23) {
           if (Settings.canDrawOverlays(context)) {            showFloatView();        } else {
           Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);            startActivity(intent);        }    } else {        showFloatView();    } }

首先最外层先判断当前的系统版本,如果低于6.0的话那就直接创建悬浮窗就可以了。当系统是6.0或者更高的时候,我们就使用刚才文档中描述的流程来进行逻辑实现,现在运行一下代码,效果如下图所示:




可以看到,当第一次创建悬浮窗的时候,会先跳转到一个系统设置界面,在这里我们选择允许当前程序创建系统悬浮窗,然后下一次再点击按钮时就能成功创建出系统悬浮窗了。




如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。


欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:


 
郭霖 更多文章 LitePal 1.2.0版本已发布 《见证Android推送时刻》视频系列教程已完结 喜大普奔,LitePal 1.3.0 版本发布! LitePal 1.3.1发布了,从此支持图片存储! 告别难记的长域名!我的博客全新短域名上线
猜您喜欢 能学知识,能找同伴,还能抽大奖-HPE大数据邀您一起high起来! R语言入门第一讲:读取数据的第一步:read.table函数 “经分”女神的发明,在逗逼的路上越走越远! 理论实践:循序渐进理解AWR细致入微分析性能报告