详解android6.0版本下悬浮窗实现

悬浮窗在安卓中实现起来还是比较容易的,这几天在网上温习了相关资料,运行在我安卓6.0手机上才发现,原来在6.0手机上不是行的。

第一反应肯定是权限相关问题,做了相关处理后,果然让悬浮窗原形毕露了。直接贴代码。

public class MainActivity extends AppCompatActivity { private static final int ALERT_WINDOW_PERMISSION_CODE = 100; private Button start_float; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); start_float = (Button) findViewById(R.id.start_float); this.start_float.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (Build.VERSION.SDK_INT > 22) { sdk23Permission(); } else { startService(new Intent(MainActivity.this, FloatService.class)); finish(); } } }); } /** * @description 安卓6.0下权限处理 * @author ldm * @time 2017/3/20 15:00 */ public void sdk23Permission() { if (!Settings.canDrawOverlays(this)) { Toast.makeText(MainActivity.this, "当前无权限使用悬浮窗,请授权!", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, ALERT_WINDOW_PERMISSION_CODE); } else { startService(new Intent(MainActivity.this, FloatService.class)); finish(); } } /** * 用户返回 */ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == ALERT_WINDOW_PERMISSION_CODE) { if (!Settings.canDrawOverlays(this)) { Toast.makeText(MainActivity.this, "权限授予失败,无法开启悬浮窗", Toast.LENGTH_SHORT).show(); } else { startService(new Intent(MainActivity.this, FloatService.class)); finish(); } } } }

对应Service:

public class FloatService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { FloatViewUtils.getInstance(this).addFloatView(); super.onCreate(); } }

简单地FloatView:

public class FloatView extends View { public static final int WIDTH = 150; public static final int HEIGHT = 150; private Paint circlePaint; private Paint textPaint; private static final String text = "50%"; public FloatView(Context context) { this(context, null, 0); } public FloatView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public FloatView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initPaints(); } /** * @description 初始化相关画笔Paint * @author ldm * @time 2017/3/20 */ private void initPaints() { circlePaint = new Paint(); circlePaint.setAntiAlias(true); circlePaint.setColor(Color.GRAY); textPaint = new Paint(); //设置抗锯齿 textPaint.setAntiAlias(true); //设置字体大小 textPaint.setTextSize(30); //设置颜色 textPaint.setColor(Color.WHITE); //设置(仿)粗体 textPaint.setFakeBoldText(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(WIDTH, HEIGHT); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawCircle(WIDTH / 2, HEIGHT / 2, WIDTH / 2, circlePaint); float textWidth = textPaint.measureText(text); float x = WIDTH / 2 - textWidth / 2; Paint.FontMetrics fms = textPaint.getFontMetrics(); float dy = -(fms.descent + fms.ascent) / 2; float y = HEIGHT / 2 + dy; canvas.drawText(text, x, y, textPaint); } }

以及FloatView管理工具类:

public class FloatViewUtils { private static FloatViewUtils instance; private Context mContext; private WindowManager manager; private FloatView floatView; private FloatViewUtils(Context mContext) { this.mContext = mContext; manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); floatView = new FloatView(mContext); } public static FloatViewUtils getInstance(Context mContext) { if (null == instance) { synchronized (FloatViewUtils.class) { if (null == instance) { instance = new FloatViewUtils(mContext); } } } return instance; } public void addFloatView() { WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); //悬浮窗口大小 lp.width = floatView.WIDTH; lp.height = floatView.HEIGHT; // 调整悬浮窗口位置 lp.gravity = Gravity.LEFT | Gravity.CENTER; // 以屏幕左上角为原点,设置x、y初始值 // lp.x = 0; // lp.y = 0; //设置悬浮窗口类型 lp.type = WindowManager.LayoutParams.TYPE_PHONE; //设置悬浮窗口不接受焦点及触摸事件 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; //设置图片格式,效果为背景透明 lp.format = PixelFormat.RGBA_8888; manager.addView(floatView, lp); } }

最后不要忘记在AndroidManifest.xml中添加权限(当然还有注册Service):

复制代码 代码如下:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-07-31 10:49:27

详解android6.0版本下悬浮窗实现的相关文章

详解Android6.0运行时权限管理_Android

自从Android6.0发布以来,在权限上做出了很大的变动,不再是之前的只要在manifest设置就可以任意获取权限,而是更加的注重用户的隐私和体验,不会再强迫用户因拒绝不该拥有的权限而导致的无法安装的事情,也不会再不征求用户授权的情况下,就可以任意的访问用户隐私,而且即使在授权之后也可以及时的更改权限.这就是6.0版本做出的更拥护和注重用户的一大体现. 一.认知 今天我们就来学习下Android6.0的权限管理. Android6.0系统把权限分为两个级别: 一个是Normal Permiss

详解Android6.0运行时权限管理

自从Android6.0发布以来,在权限上做出了很大的变动,不再是之前的只要在manifest设置就可以任意获取权限,而是更加的注重用户的隐私和体验,不会再强迫用户因拒绝不该拥有的权限而导致的无法安装的事情,也不会再不征求用户授权的情况下,就可以任意的访问用户隐私,而且即使在授权之后也可以及时的更改权限.这就是6.0版本做出的更拥护和注重用户的一大体现. 一.认知 今天我们就来学习下Android6.0的权限管理. Android6.0系统把权限分为两个级别: 一个是Normal Permiss

android6.0版本调用系统相册返回参数cursor为空

问题描述 android6.0版本调用系统相册返回参数cursor为空 Uri selectedImage = data.getData(); pathString = CommonTools.Uri2Path(selectedImage, SharedPhotoActivity.this); /** * 通过uri得到path */ public static String Uri2Path(Uri uri, Context context) { String[] filePathColumn

详解Python3.1版本带来的核心变化_python

这里我们将对Python 3.1核心语言的变化进行分析,包括字符串的格式化.说明符以及其他方面的内容.希望这些变化能对大家了解Python 3.1有所帮助. Python 3.0发布七个月之后,Python核心开发人员于2009年6月27日发布了新的Python 3.1版本.虽然此3.1版本只是对Python 3.0的一次小型升级,但是它不仅为开发者带来许多让人感兴趣的特性,同时在性能方面也有所改善.本文将为读者详细介绍Python 3.1版本在核心语言.标准程序库和性能改善方面的变化. 一.字

详解CentOS 5.8下varnish-2.1.5的安装配置

Varnish是一款强大的反向代理加速软件,关于其工作原理可以参考上图,其具体流程及VCL语法我这里就不做说明,网上资料多,大家还可以对照参考其官方网站和<Varnish中文权威指南>. 一.安装CentOS5.8系统环境下的依耐关系 yum install gcc gcc-c++ yum install automake autoconflibtool ncurses-devel libxslt groff pcre-devel pkgconfig libtool -y 二.下载varnis

oracle10g 手动创建数据详解(linux)下

本文紧跟上篇内容. <oracle10g 手动创建数据详解(linux)上>       http://www.cnblogs.com/fnng/archive/2012/07/19/2600167.html 考虑篇幅过长不易于阅读,所以分个上下两节来进行.这一节中重点解决上一节中第四步与第九步的难题.   设置参数文件与创建数据库命令                                                       如何获得一个的参数文件pfile 呢? 1.问or

关于wamp启动是80端口被占用的问题详解(win7系统下WAMP 80端口被Microsoft-HTTPAPI/2.0占用的解决办法)

原贴地址:http://www.soaspx.com/dotnet/service/service_20120720_9432.html   问题如下图:       网上有关于这个处理办法,说道:   VS2010在更新了SP1后,会在开机时自动启动一个服务,占用WAMP的80端口,导致WAMP无法正常启动Apache.提示信息: Your port 80 is actually used by : Server: Microsoft-HTTPAPI/2.0 Press Enter to ex

学习PHP:详解mysql4.0以后的编码配置

简要说一下mysql4.1以后的问题第一:mysql4.1的存储方式已经是utf8的了..也就是说他的文件编码是utf8格式,我们不需要担心会有存储不了的字符第二:mysql服务器需要以一种编码方式来启动,设定连接(通讯)过来的字符编码是什么,就是所谓的我们的交流语言第三:mysql的client端,需要设定一种编码去和mysql的服务器端通讯,也是交流语言 那么为什么回出现乱码哪?就是出在这个连接的过程中,试想一个人用英文和你说话,而你只明白中文,真的和小燕子一样,三块肉喂了马吃了.. 那么如

详解Windows 10版本布局 最好用的是它

自从微软于2014年秋季发布会上正式公布了Windows 10之后,正式宣布了毁誉参半的Windows 8/8.1的一页已经揭去,而微软将数字从8直接升至10,不仅意味着功能上的大步伐跃进,也意味着相比之前封闭式的内部测试,Windows 10是微软第一次尝试将操作系统的开发任务部分交予用户.虽然这在开放与交流上是一次不可多得的尝试,但也是第一次将诸多专业词汇推至用户面前:通道.分支 (Branch).预览.Ring,等等.故本文仅在于扫盲,向刚刚接触Windows 10的用户简单介绍一下细节,