当前位置: 首页 > news >正文

Android-悬浮窗口

在Android系统中,如果应用需要弹出一个悬浮窗口,就需要申请一项特殊权限

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

在Android O之前的系统中申请了该权限后,再给对应的window设置

WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_PHONE;

悬浮窗口就可以显示出来。

但是在Android O的系统中,google规定申请

android.permission.SYSTEM_ALERT_WINDOW
权限的应用需要给悬浮窗口设置如下type:

WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

悬浮窗口才能显示出来,“TYPE_APPLICATION_OVERLAY”是重点。
如果不设置该TYPE,应用会Crash,报错如下(后面的2002表示设置的type为TYPE_PHONE):

AndroidRuntime: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@c8d1f1a -- permission denied for window type 2002

另外说一下:申请
android.permission.SYSTEM_ALERT_WINDOW
权限不能使用 requestPermissions 方法。
可以使用下面的方法:

Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 100);

完整代码

1、添加权限

在AndroidManifest.xml中添加悬浮窗所需的权限:

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

2、请求权限(针对Android 6.0及以上)

  • 对于Android 6.0(API级别23)及以上的设备,需要运行时请求SYSTEM_ALERT_WINDOW权限。示例:
private static final int REQUEST_CODE_DRAW_OVER_OTHER_APPS_PERMISSION = 200;// 在Activity或Fragment中请求权限
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, REQUEST_CODE_DRAW_OVER_OTHER_APPS_PERMISSION);
}
  • 处理权限请求的结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == REQUEST_CODE_DRAW_OVER_OTHER_APPS_PERMISSION) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {// 权限被拒绝Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();} else {// 权限已授予,可以显示悬浮窗showFloatingWindow();}}
}

3、实现悬浮窗

  • 定义悬浮窗的布局和显示逻辑:
public void showFloatingWindow() {// 布局参数WindowManager.LayoutParams params;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);} else {params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_PHONE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);}// 设置悬浮窗的位置params.gravity = Gravity.TOP | Gravity.START; // 例如,设置在屏幕左上角params.x = 100; // x坐标params.y = 100; // y坐标// 创建浮动窗口视图LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);View floatingView = inflater.inflate(R.layout.floating_window_layout, null);// 获取WindowManagerWindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);try {// 添加悬浮窗到WindowManagerwindowManager.addView(floatingView, params);} catch (Exception e) {e.printStackTrace();}
}
  • 浮窗拖动
// 设置触摸监听器以实现拖动
floatingLayout.setOnTouchListener(new View.OnTouchListener() {private int initialX;private int initialY;private float initialTouchX;private float initialTouchY;@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 记录按下时的坐标initialX = params.x;initialY = params.y;initialTouchX = event.getRawX();initialTouchY = event.getRawY();break;case MotionEvent.ACTION_MOVE:// 计算移动的距离,并更新悬浮窗位置params.x = initialX + (int) (event.getRawX() - initialTouchX);params.y = initialY + (int) (event.getRawY() - initialTouchY);windowManager.updateViewLayout(floatingView, params);break;case MotionEvent.ACTION_UP:// 手指抬起,可以根据需要做一些操作,这里直接返回break;default:return false;}return true; // 消费掉这个事件,防止它被其他视图消费}
});
  • 关闭浮窗
public void removeFloatingWindow() {// 获取WindowManager实例WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);// 确保floatingView是之前添加到WindowManager的那个View实例// 这里假设floatingView是在showFloatingWindow()方法中创建并添加的View floatingView = ...; // 你需要确保这指向正确的View实例if (floatingView != null && windowManager != null) {// 移除悬浮窗视图windowManager.removeView(floatingView);}
}

悬浮窗开启关闭时前后台切换功能

app退到后台

方案一、启动Home页
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);

如果Launcher和Home不是同一个,就不能这么用。比如说机顶盒Launcher,启动第三方app都是从这里打开的。然后这里如果执行了上述代码,启动了Home,那就跳转到了Android系统的Home,就不是退到后台的效果了。

方案二、执行Activity#moveTaskToBack()
moveTaskToBack(false);
  • 关于moveTaskToBack的参数
/*** Move the task containing this activity to the back of the activity* stack.  The activity's order within the task is unchanged.** @param nonRoot If false then this only works if the activity is the root*                of a task; if true it will work for any activity in*                a task.** @return If the task was moved (or it was already at the*         back) true is returned, else false.*/public boolean moveTaskToBack(boolean nonRoot) {}
  • nonRoot=false时,只有当当前Activity为root activity根Activity时才会把当前task退回到后台。notRoot=true时,不管当前是否是root activity都会把当前task退回到后台。

app切到前台

方案一、使用Intent启动需要切到前台的Activity
Intent intent = new Intent(this, MainActivity.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setAction(Intent.ACTION_MAIN);
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(intent);
  • 这里的MainActivity.class就是需要启动的Activity
方案二、通过ActivityMananger把task切到前台
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
am.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_WITH_HOME);
  • 报错信息
java.lang.SecurityException: Permission Denial: moveTaskToFront() from pid=20744, uid=10516 requires android.permission.REORDER_TASKS
  • 这个方法需要权限 android.permission.REORDER_TASKS
  • 可能影响Google上架
权限申请
<uses-permission android:name="android.permission.REORDER_TASKS"/>
// 检查是否已经有了权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.REORDER_TASKS)!= PackageManager.PERMISSION_GRANTED) {// 如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.REORDER_TASKS)) {// 显示解释为什么需要这个权限的对话框,然后再次请求权限} else {// 没有权限,直接请求权限ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.REORDER_TASKS},MY_PERMISSIONS_REQUEST_REORDER_TASKS);}
} else {// 已经有权限,可以执行相应操作
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == MY_PERMISSIONS_REQUEST_REORDER_TASKS) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 权限被用户同意,可以执行moveTaskToFront操作} else {// 权限请求被拒绝,根据情况处理,如提示用户权限重要性或提供备选方案}}
}

相关文章:

Android-悬浮窗口

在Android系统中&#xff0c;如果应用需要弹出一个悬浮窗口&#xff0c;就需要申请一项特殊权限 <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW"/>在Android O之前的系统中申请了该权限后&#xff0c;再给对应的window设置 WindowM…...

打破僵局:Foxit Reader无法打开的终极解决方案

打破僵局&#xff1a;Foxit Reader无法打开的终极解决方案 在数字化阅读时代&#xff0c;Foxit Reader作为一款广受欢迎的PDF阅读器&#xff0c;其打不开的问题无疑会给用户带来诸多不便。本文将为您提供全面的解决方案&#xff0c;从基础检查到高级技巧&#xff0c;确保您能够…...

[调试] JTAG下运行正常,从QSPI或者SD卡启动则无响应,如何查找问题

[调试] JTAG下运行正常&#xff0c;从QSPI或者SD卡启动则无响应&#xff0c;如何查找问题 一、问题现象二、用自定义fsbl替代系统默认的fsbl1. 新建fsbl_new2. 如果提示缺少xilffs库3. 使能调试信息输出 三. 启动成功和失败情况下的典型输出1. JTAG启动模式: 正常加载2. QSPI启…...

Linux内核 -- 多线程之wait_event用法

Linux Kernel 中 wait_event 的高级用法及注意事项 在Linux内核编程中&#xff0c;wait_event 系列函数是用于实现进程等待和事件通知机制的重要工具。本文将详细介绍 wait_event 的高级用法以及注意事项。 1. 基本用法 wait_event 系列宏主要包括以下几种形式&#xff1a; …...

双指针系列第 8 篇:盛水最多的容器。几句话讲明白!

Leetcode 题目链接 思路 取首尾双指针和水量如下所示&#xff0c;设高度函数为 h ( i ) h(i) h(i)&#xff0c;在下图中 h ( l ) < h ( r ) h(l) < h(r) h(l)<h(r)。 观察以 l l l 为左边界所能构成的其他水量&#xff0c;与矮的右边界搭配结果如下。 与高的…...

c++高阶-1-模板

文章目录 模板一、模板基本语法二、函数模板1.基本语法2.函数模板注意事项3.普通函数和函数模板区别4.普通函数和函数模板调用规则 三、类模板1.基本语法2.类模板和函数模板的区别3.类模板中成员函数调用时机4.类模板对象做函数参数5.类模板与继承6.成员函数的类外实现 模板 一…...

.net core 的 winform 的 浏览器控件 WebView2

在.NET Core WinForms应用程序中&#xff0c;没有直接的“浏览器控件”&#xff0c;因为WinForms不支持像WebBrowser控件那样的功能。但是&#xff0c;你可以使用WebView2控件&#xff0c;它是一个基于Chromium的浏览器内核&#xff0c;可以在WinForms应用程序中嵌入Web内容。 …...

Django QuerySet对象,all()方法

all()方法 在Django中&#xff0c;all()方法是QuerySet对象的一个方法&#xff0c;用于获取模型的所有实例。 当你调用ModelName.objects.all()时&#xff0c;Django会生成一个SQL查询&#xff0c;从数据库中获取该模型的所有记录&#xff0c;并返回一个QuerySet对象&#xf…...

自动生成网站sitemap

要在 Next.js 和 Contentlayer 项目中实现自动生成 Sitemap 的功能&#xff0c;你可以编写一个脚本&#xff0c;在每次生成文档后自动生成 Sitemap。以下是一个示例脚本&#xff0c;你可以根据自己的需求进行调整。 步骤 1&#xff1a;安装必要的依赖 首先&#xff0c;你需要…...

中国经济昆虫志(55卷)

中国经济昆虫志&#xff0c;共55卷&#xff0c;内容包括概述、形态特征、分类等。各级分类单元均编有检索表&#xff0c;每个种有特征描述、地理分布&#xff0c;有的还记载有生活习性和防治方法。为便于鉴定&#xff0c;绘制有特征图和彩色图。 包括鞘翅目天牛科、半翅目蝽科、…...

linux环境安装elasticsearch缓存数据库和Kibana客户端

linux环境安装elasticsearch缓存数据库&#xff0c;今天我们安装7.17.18版本&#xff0c;并分析遇到的问题。 一、elasticsearch安装运行 1、直接下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.18-linux-x86_64.tar.gz2、解压 tar -…...

OpenSSL的一些使用案例

目录 一、介绍 二、基本使用 1、Shell &#xff08;1&#xff09;文件加解密 &#xff08;2&#xff09;生成密钥文件 2、API &#xff08;1&#xff09;md5sum &#xff08;2&#xff09;AES256加解密 一、介绍 本篇博客重点不是详细描述 OpenSSL 的用法&#xff0c;只…...

常用字符串方法<python>

导言 在python中内置了许多的字符串方法&#xff0c;使用字符串方法可以方便快捷解决很多问题&#xff0c;所以本文将要介绍一些常用的字符串方法。 目录 导言 string.center(width[,fillchar]) string.capitalize() string.count(sub[,start[,end]]) string.join(iterabl…...

线程池666666

1. 作用 线程池内部维护了多个工作线程&#xff0c;每个工作线程都会去任务队列中拿取任务并执行&#xff0c;当执行完一个任务后不是马上销毁&#xff0c;而是继续保留执行其它任务。显然&#xff0c;线程池提高了多线程的复用率&#xff0c;减少了创建和销毁线程的时间。 2…...

Python28-5 k-means算法

k-means 算法介绍 k-means 算法是一种经典的聚类算法&#xff0c;其目的是将数据集分成 ( k ) 个不同的簇&#xff0c;每个簇内的数据点尽可能接近。算法的基本思想是通过反复迭代优化簇中心的位置&#xff0c;使得每个簇内的点与簇中心的距离之和最小。k-means 算法的具体步骤…...

主流国产服务器操作系统技术分析

主流国产服务器操作系统 信创 "信创"&#xff0c;即信息技术应用创新&#xff0c;作为科技自立自强的核心词汇&#xff0c;在我国信息化建设的进程中扮演着至关重要的角色。自2016年起步&#xff0c;2020年开始蓬勃兴起&#xff0c;信创的浪潮正席卷整个信息与通信技…...

【Linux】线程封装与互斥(万字)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 C多线程的用法 对原生线程进行一次封装 理解pthread线程 Linux线程互斥 进程线程间的互斥相关背景概念 互斥量mutex 操作共享变量会有问题的售票…...

5分钟教你部署MySQL8.0环境

此方法基于Windows操作系统&#xff01; 一、在MySQL官网单击downloads&#xff08;下载&#xff09;MySQLhttps://www.mysql.com/cn/ 选择在Windows操作系统下载 二、选择合适的版本 推荐下载第二种&#xff0c;安装时离线安装即可 三、安装MySQL8.0 1、找到MySQL下载完成…...

LLM应用:传统NLP任务

LLM出来以后&#xff0c;知乎上就出现了“传统NLP已死”的言论&#xff0c;但是传统NLP真的就被扔进历史的垃圾桶了吗&#xff1f; 其实&#xff0c;尽管LLM具有出色的通用能力&#xff0c;但仍然无法有效应对低资源领域的自然语言处理任务&#xff0c;如小语种翻译。为了更好地…...

基于Hadoop平台的电信客服数据的处理与分析③项目开发:搭建Kafka大数据运算环境---任务11:基础环境准备

任务描述 任务主要是安装配置基础环境&#xff0c;主要内容包括&#xff1a; 1、安装java Kafka和ZooKeeper都需要安装Java环境&#xff0c;推荐至少Java8及以上版本 2、安装ZooKeeper ZooKeeper是Kafka集群的必要组件 3、安装kafka Kafka版本包括使用的scala语言版本和kafka版…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...