Android 悬浮窗
本文参考文章地址:https://juejin.cn/post/7009180088310693919
一、申请权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
二、创建悬浮窗service
<serviceandroid:name=".FloatingWindowService"android:enabled="true"android:exported="true">
</service>
三、悬浮窗布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><FrameLayoutandroid:id="@+id/layout_drag"android:layout_width="match_parent"android:layout_height="15dp"android:background="#dddddd"><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/iv_close"android:layout_width="15dp"android:layout_height="15dp"android:background="#111111"android:layout_gravity="end" /></FrameLayout><androidx.appcompat.widget.AppCompatTextViewandroid:id="@+id/tv_content"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center_horizontal"android:background="#eeeeee"android:scrollbars="vertical" />
</LinearLayout>
四、悬浮窗设置
private lateinit var windowManager: WindowManager
private lateinit var layoutParams: WindowManager.LayoutParams
private lateinit var tvContent: AppCompatTextView
private var floatingView: View? = null
private val stringBuilder = StringBuilder()
private var x = 0
private var y = 0// 获取windowManager并设置layoutParamswindowManager = getSystemService(WINDOW_SERVICE) as WindowManagerlayoutParams = WindowManager.LayoutParams().apply {type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY} else {WindowManager.LayoutParams.TYPE_PHONE}gravity = Gravity.START or Gravity.TOPflags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLEwidth = 300height = 500}if (Settings.canDrawOverlays(this)) {//新建悬浮窗事件floatingView = LayoutInflater.from(this).inflate(R.layout.layout_float_view, null)//文字显示控件tvContent = floatingView!!.findViewById(R.id.tv_content)//关闭悬浮窗floatingView!!.findViewById<AppCompatImageView>(R.id.iv_close).setOnClickListener {windowManager.removeView(floatingView)}// 设置TextView滚动tvContent.movementMethod = ScrollingMovementMethod.getInstance()//设置悬浮窗移动floatingView!!.findViewById<FrameLayout>(R.id.layout_drag).setOnTouchListener { _, event ->when (event.action) {MotionEvent.ACTION_DOWN -> {x = event.rawX.toInt()y = event.rawY.toInt()}MotionEvent.ACTION_MOVE -> {val currentX = event.rawX.toInt()val currentY = event.rawY.toInt()val offsetX = currentX - xval offsetY = currentY - yx = currentXy = currentYlayoutParams.x = layoutParams.x + offsetXlayoutParams.y = layoutParams.y + offsetYwindowManager.updateViewLayout(floatingView, layoutParams)}}true}windowManager.addView(floatingView, layoutParams)
}
五、通过广播联调显示悬浮窗
全部代码如下
class MainActivity : AppCompatActivity() {private lateinit var buttonSend: Buttonprivate lateinit var buttonView: Buttonprivate val TAG = "MainActivity"@SuppressLint("MissingInflatedId", "UnspecifiedRegisterReceiverFlag")override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)buttonSend = findViewById(R.id.buttonClick)buttonSend.setOnClickListener {sendMessage()}buttonView = findViewById(R.id.buttonView)buttonView.setOnClickListener {startWindow()}}//发送广播到悬浮窗private fun sendMessage() {Intent("android.intent.action.MyReceiver").apply {putExtra("content", "float view test!")sendBroadcast(this)}}//检查悬浮窗权限是否打开,若没有打开则打开系统设置页面private fun startWindow() {if (!Settings.canDrawOverlays(this)) {startActivityForResult(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:$packageName")), 0)} else {startService(Intent(this, FloatingWindowService::class.java))}}//请求权限override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)if (requestCode == 0) {if (Settings.canDrawOverlays(this)) {Toast.makeText(this, "悬浮窗权限授权成功", Toast.LENGTH_SHORT).show()startService(Intent(this, FloatingWindowService::class.java))}}}
}class FloatingWindowService : Service() {private lateinit var windowManager: WindowManagerprivate lateinit var layoutParams: WindowManager.LayoutParamsprivate lateinit var tvContent: AppCompatTextViewprivate lateinit var handler: Handlerprivate var receiver: ViewReceiver? = nullprivate var floatingView: View? = nullprivate val stringBuilder = StringBuilder()private var x = 0private var y = 0private var floatView = false@SuppressLint("UnspecifiedRegisterReceiverFlag")override fun onCreate() {super.onCreate()// 注册广播receiver = ViewReceiver()val filter = IntentFilter()filter.addAction("android.intent.action.MyReceiver")registerReceiver(receiver, filter);// 获取windowManager并设置layoutParamswindowManager = getSystemService(WINDOW_SERVICE) as WindowManagerlayoutParams = WindowManager.LayoutParams().apply {type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY//显示于所有应用之上} else {WindowManager.LayoutParams.TYPE_PHONE}gravity = Gravity.START or Gravity.TOPflags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLEwidth = 300height = 500}handler = Handler(this.mainLooper) { msg ->tvContent.text = msg.obj as String// 当文本超出屏幕自动滚动,保证文本处于最底部val offset = tvContent.lineCount * tvContent.lineHeightfloatingView?.apply {if (offset > height) {tvContent.scrollTo(0, offset - height)}}false}}override fun onBind(intent: Intent?): IBinder? {return null}@SuppressLint("ClickableViewAccessibility")override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {if (Settings.canDrawOverlays(this)) {//新建悬浮窗事件floatingView = LayoutInflater.from(this).inflate(R.layout.layout_float_view, null)//文字显示控件tvContent = floatingView!!.findViewById(R.id.tv_content)//关闭悬浮窗floatingView!!.findViewById<AppCompatImageView>(R.id.iv_close).setOnClickListener {stringBuilder.clear()windowManager.removeView(floatingView)floatView = false}// 设置TextView滚动tvContent.movementMethod = ScrollingMovementMethod.getInstance()//设置悬浮窗移动floatingView!!.findViewById<FrameLayout>(R.id.layout_drag).setOnTouchListener { _, event ->when (event.action) {MotionEvent.ACTION_DOWN -> {x = event.rawX.toInt()y = event.rawY.toInt()}MotionEvent.ACTION_MOVE -> {val currentX = event.rawX.toInt()val currentY = event.rawY.toInt()val offsetX = currentX - xval offsetY = currentY - yx = currentXy = currentYlayoutParams.x = layoutParams.x + offsetXlayoutParams.y = layoutParams.y + offsetYwindowManager.updateViewLayout(floatingView, layoutParams)}}true}windowManager.addView(floatingView, layoutParams)floatView = true}return super.onStartCommand(intent, flags, startId)}override fun onDestroy() {// 注销广播并删除浮窗unregisterReceiver(receiver)receiver = nullif (floatView) {windowManager.removeView(floatingView)}}inner class ViewReceiver : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent) {val content = intent.getStringExtra("content") ?: ""stringBuilder.append(content).append("\n")val message = Message.obtain()message.what = 0message.obj = stringBuilder.toString()handler.sendMessage(message)}}
}
相关文章:
Android 悬浮窗
本文参考文章地址:https://juejin.cn/post/7009180088310693919 一、申请权限 <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW" />二、创建悬浮窗service <serviceandroid:name".FloatingWindowService"an…...
3.物联网射频识别,(高频)RFID应用ISO14443-2协议
一。ISO14443-2协议简介 1.ISO14443协议组成及部分缩略语 (1)14443协议组成(下面的协议简介会详细介绍) 14443-1 物理特性 14443-2 射频功率和信号接口 14443-3 初始化和防冲突 (分为Type A、Type B两种接口&…...
数据分析笔记1
数据分析概述:数据获取--探索分析与可视化--预处理--分析建模--模型评估 数据分析含义:利用统计与概率的分析方法提取有用的信息,最后进行总结与概括 一、数据获取 实用网站:kaggle 阿里云天池 数据仓库:将所有业务数据…...
paramiko 3
import paramiko import concurrent.futuresdef execute_remote_command(hostname, username, password, command):try:# 创建SSH客户端client paramiko.SSHClient()client.set_missing_host_key_policy(paramiko.AutoAddPolicy())# 使用密码认证连接远程主机client.connect(h…...
基于Dlib训练自已的人脸数据集提高人脸识别的准确率
前言 由于图像的质量、光线、角度等因素影响。这时如果使用官方提供的模型做人脸识别,就会导至识别率不是很理想。人脸识别的准确率与图像的清晰度和质量有关。如果图像模糊、光线不足或者有其他干扰因素,Dlib 可能无法正确地识别人脸。为了确保图像质量…...
Git 详细安装教程(详解 Git 安装过程的每一个步骤
Git 详细安装教程(详解 Git 安装过程的每一个步骤) 该文章详细具体,值得收藏学习...
kafka伪集群部署,使用KRAFT模式
1:拉去管理kafka界面UI镜像 docker pull provectuslabs/kafka-ui2:拉去管理kafka镜像 docker pull bitnami/kafka3:docker-compose.yml version: 3.8 services:kafka-1:container_name: kafka1image: bitnami/kafka ports:- "19092:19092"- "19093:19093&quo…...
【双指针遍历】N数之和问题
文章目录 二数之和LC1三数之和LC15四数之和LC18最接近的三数之和LC16 二数之和LC1 题目链接 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对…...
Qt的QObject类
文章目录 QObject类如何在Qt中使用QObject的信号与槽机制?如何在Qt中使用QObject的属性系统?QObject的元对象系统如何实现对象的反射功能? QObject类 Qt的QObject类是Qt框架中的基类,它是所有Qt对象的父类。QObject提供了一些常用…...
【图论C++】链式前向星(图(树)的存储)
/*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 一个某双流一大学通信与信息专业大二在读 * * brief 一直在竞赛算法学习的路上* * copyright 2023.9* COPYRIGHT 原创技术笔记:转载需获得博主本人…...
16.PWM输入捕获示例程序(输入捕获模式测频率PWMI模式测频率和占空比)
目录 输入捕获相关库函数 输入捕获模式测频率 PWMI模式测频率和占空比 两个代码的接线图都一样,如下 测量信号的输入引脚是PA6,信号从PA6进来,待测的PWM信号也是STM32自己生成的,输出引脚是PA0。 需要配置电路连接图示如下&…...
pip version 更新
最近报了一个错: 解决办法: 在cmd输入“conda install pip” conda install pip 完了之后再输入: python -m pip install --upgrade pip ok....
Oracle - 多区间按权重取值逻辑
啰嗦: 其实很早就遇到过类似问题,也设想过,不过一致没实际业务需求,也就耽搁了;最近有业务提到了,和同事讨论,各有想法,所以先把逻辑整理出来,希望有更好更优的解决方案;…...
本次CTF·泰山杯网络安全的基础知识部分(二)
简记23年九月参加的泰山杯网络安全的部分基础知识的题目,随时补充 15(多选)网络安全管理工作必须坚持“谁主管、谁负责,谁运营、谁负责,谁使用、谁负责”的原则,和“属地管理”的原则 谁主管、谁负责&…...
MyBatis 映射文件(Mapper XML):配置与使用
MyBatis 映射文件(Mapper XML):配置与使用 MyBatis是一个强大的Java持久化框架,它允许您将SQL查询、插入、更新和删除等操作与Java方法进行映射。这种映射是通过MyBatis的映射文件,通常称为Mapper XML文件来实现的。本…...
基于 SpringBoot 的大学生租房网站
文章目录 1 简介2 技术栈3 需求分析4 系统设计5 系统详细设计5.1系统功能模块5.2管理员模块5.3房主功能模块5.4用户功能模块 源码咨询 1 简介 本大学生租房系统使用简洁的框架结构,专门用于用户浏览首页,房屋信息,房屋评价,公告资…...
BL808学习日志-0-概念理解
一、主核心的介绍 1.三个核心在FREERTOS系统中相互独立,各负责各自的外设和程序;其中M0和LP核心在一个总线上,D0单独在一个总线上,两个总线使用AXI4.0(??)通讯? CPU0(M0)-E907架构,320MHz; CPU1(LP)-E9…...
CISSP学习笔记:业务连续性计划
第三章 业务连续性计划 3.1 业务连续性计划 业务连续性计划(BCP): 对组织各种过程的风险评估,发生风险的情况下为了使风险对组织的影响降至最小而定制的各种计划BCP和DRP首先考虑的人不受伤害,然后再解决IT恢复和还原问题BCP的主要步骤: 项…...
.NET Nuget包推荐安装
文章目录 前言通用WPFWebApiBlazor 前言 我这里的包主要是.NET Core的,.NET Framework可能不支持。 通用 Newtonsoft.Json:最常用的C#和Json对象互转的包。支持匿名对象,但是不支持Enum枚举类型,显示的是Enum的数值,…...
【文献阅读】Pocket2Mol : 基于3D蛋白质口袋的高效分子采样 + CrossDocked数据集说明
Pocket2Mol: Efficient Molecular Sampling Based on 3D Protein Pockets code: GitHub - pengxingang/Pocket2Mol: Pocket2Mol: Efficient Molecular Sampling Based on 3D Protein Pockets 所用数据集 与“A 3D Generative Model for Structure-Based Drug Desi…...
TrustRadius 评论:为什么 Splashtop 优于 LogMeIn
在当今日益数字化的格局中,远程访问和远程支持工具不仅方便而且至关重要。无论对于居家办公人员,还是对于提供远程支持的 IT 专家,能够安全高效地访问远程系统已成为以技术为导向的日常生活的主要内容。 Splashtop 和 LogMeIn 是远程领域的两…...
【动态规划】动态规划经典例题 力扣牛客
文章目录 跳台阶 BM63 简单跳台阶扩展 JZ71 简单打家结舍 LC198 中等打家劫舍2 LC213中等最长连续递增序列 LC674 简单乘积最大子数组LC152 中等最长递增子序列LC300 中等最长重复子数组LC718最长公共子串NC BM66最长公共子序列LC1143 中等完全平方数LC279零钱兑换 LC322 中等单…...
统计模型----决策树
决策树 (1)决策树是一种基本分类与回归方法。它的关键在于如何构建这样一棵树。决策树的建立过程中,使用基尼系数来评估节点的纯度和划分的效果。基尼系数是用来度量一个数据集的不确定性的指标,其数值越小表示数据集的纯度越高。…...
C# List 复制之深浅拷贝
C# List 复制 之深浅拷贝 声明类 public class TestStu{public int Number{get;set; }public string Name{get;set; }}public static async Task<int> Main(string[] args){var stu1 new TestStu(){Number 1,Name "1"};var stu2 new TestStu(){Numbe…...
论<script> 标签可以直接写在 HTML 文件中的哪些位置?(可以将 <script> 标签直接插入到 HTML 文件的任何位置)
可以将 <script> 标签直接插入到 HTML 文件的任何位置,以在相应位置执行 JavaScript 代码。 以下是几个示例: 1.<head> 元素内部:在 <head> 元素内部放置 <script> 标签时,脚本将在页面加载过程中被下载和…...
【MySQL进阶】--- 存储引擎的介绍
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】🎈 本专栏旨在分享学习MySQL的一点学习心得,欢迎大家在评论区讨论💌 目录 一、什么…...
self-XSS漏洞SRC挖掘
本文由掌控安全学院 - 一朵花花酱 投稿 Markdown是一种轻量级标记语言,创始人为约翰格鲁伯(John Gruber)。它允许人们使用易读易写的纯文本格式编写文档,然后转换成有效的 XHTML(或者HTML)文档。这种语言吸…...
1859. 将句子排序
目录 一、题目 二、代码 一、题目 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 二、代码 定义了一个vector<vector<string>> v(MAX);采用const string& word : v[k] word 就会依次取得 v[k] 中的每个元素(v[k][0],…...
普通学校,普通背景,普通公司,不普通总结。
作者:阿秀 InterviewGuide大厂面试真题网站:https://top.interviewguide.cn 这是阿秀的第「313」篇原创 小伙伴们大家好,我是阿秀。 可能很多人点开牛客、知乎、B站,一看帖子的标题都是"某985xxxx"、"不入流211xxx…...
Flink之Watermark生成策略
在Flink1.12以后,watermark默认是按固定频率周期性的产生. 在Flink1.12版本以前是有两种生成策略的: AssignerWithPeriodicWatermarks周期性生成watermarkAssignerWithPunctuatedWatermarks[已过时] 按照指定标记性事件生成watermark 新版本API内置的watermark策略 单调递增的…...
wordpress网站如何app/百度网盘搜索引擎
文章目录大数据人工智能常见技术框架和算法的知识详细概要HadoopSparkHiveStromHbaseSolrElasticsearchLDA潜在狄利克雷分布模型MinHash聚类Kmeans聚类Canopy聚类贝叶斯分类算法总结大数据人工智能常见技术框架和算法的知识详细概要 Hadoop Hadoop是一个由Apache基金会所开发…...
不用vip的免费追剧软件/防城港网站seo
每次使用etcdctl,都要长长的一大串,太麻烦了,直接把变量写入文件中,就方便很多了 vi ~/.bashrc 行尾添加 export ETCDCTL_ENDPOINTShttps://127.0.0.1:2379export ETCDCTL_CACERT/etc/kubernetes/pki/etcd/ca.crtexport ETCDCTL_C…...
网络推广培训课程4万/专业放心关键词优化参考价格
状态 element和pad都可以处于不同的状态。pad的状态与element的状态相关联,因此状态的设计主要围绕element的状态进行。 一个element可以有 4 种状态。NULL、READY、PAUSED和PLAYING。当一个element最初被实例化时,它处于 NULL 状态。 状态定义 NULL&…...
微信开发者工具/百度seo什么意思
一个生活平庸的人带着命运的疑问去问禅师。他问禅师;这个世界上面真的有命运吗? 有的禅师回答。 “ 是不是我命中注定要穷苦一生?”他问。 禅师让他伸出左手,指给他看说:你看清出了么?这条横线是爱情线,这条斜线是事业线,另外一条竖线叫生…...
找老外做网站可靠吗/cms建站系统
f{} Python3.6及以上版本才有,Python3.5及以下版本会出错。 %s%() 常用格式 {}.format() {}里面可以带数字也可以不带数字,带数字编号可以调换输出顺序,还可以带关键字。 device torch.device(fcuda:{opt.local_rank}) #python3.6 device …...
培训网站计时怎么破/黑科技引流工具
前两天看到有人留言问在什么情况下需要部署hadoop,我给的回答也很简单,就是在需要处理海量数据的时候才需要考虑部署hadoop。关于这个问题在很早之前的一篇分享文档也有说到这个问题,数据量少的完全发挥不了hadoop的优势,所以也没…...