android仿assistivetouch悬浮窗实现(带功能实现)

一、悬浮窗点击后的界面:

主要有四个功能,返回、应用程序、退出和主界面。其他功能也可以类似添加。

界面布局代码就不贴出来了,源码(切记需要签名才能让功能实现):下载地址

二、主要是检测系统启动或者app启动的时候出现悬浮窗,并且只有当检测到前台运行了特定程序才会隐藏图标。

<receiver android:name="com.bumblebee.remindeasy.StartupReceiver" ><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter></receiver><service android:name="com.bumblebee.remindeasy.service.AuxiliaryService" />

添加检测BOOT_COMPLETED,需要添加权限,

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

三、开始写service,调用自定义的view。

public void onCreate() {super.onCreate();new EasyTouchView(this, this).initTouchViewEvent();}

四、自定义view的实现,主要是touchview的显示,以及移动操作和点击事件注册。

public EasyTouchView(Context context, ServiceListener listener) {super(context);mContext = context;mSerLisrener = listener;mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if (msg.what == 100) {if (isCellaretteAppforeground(mContext)) {//检测到“com.xxx.xxx“程序,将隐藏touchviewmTouchView.setVisibility(View.INVISIBLE);} else {mTouchView.setVisibility(View.VISIBLE);//否则显示touchview}this.sendEmptyMessageDelayed(100, 500);}}};}/** 检测是否存在某个应用com.xxx.xxx在前台运行。*/public boolean isCellaretteAppforeground(Context context) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<ActivityManager.RunningAppProcessInfo> appProcesses = am.getRunningAppProcesses();for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {if ("com.xxx.xxx".equals(appProcess.processName)) {return true;}break;}}return false;}public void initTouchViewEvent() {initEasyTouchViewEvent();initSettingTableView();}private void initEasyTouchViewEvent() {// 设置载入view WindowManager参数,获取WindowManagermWManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);midX = mWManager.getDefaultDisplay().getWidth() / 2 - 25;midY = mWManager.getDefaultDisplay().getHeight() / 2 - 44;mTouchView = LayoutInflater.from(mContext).inflate(R.layout.easy_touch_view, null);mIconImageView = (ImageView) mTouchView.findViewById(R.id.easy_touch_view_imageview);mTouchView.setBackgroundColor(Color.TRANSPARENT);mTouchView.setOnTouchListener(mTouchListener);WindowManager wm = mWManager;WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();mWMParams = wmParams;wmParams.type = 2003; // 这里的2002表示系统级窗口,你也可以试试2003。wmParams.flags = 40; // 设置桌面可控wmParams.width = 100;wmParams.height = 100;wmParams.format = -3; // 透明wm.addView(mTouchView, wmParams);mTouchView.setVisibility(View.INVISIBLE);mHandler.sendEmptyMessageDelayed(100, 1000);//发送消息}private void initSettingTableView() {mSettingTable = LayoutInflater.from(mContext).inflate(R.layout.floatmenu, null);//将悬浮窗布局载入,继而可以获取里面的控件进行点击事件注册btnback = (Button) mSettingTable.findViewById(R.id.btn_back);btnhome = (Button) mSettingTable.findViewById(R.id.btn_home_screen);btnexit = (Button) mSettingTable.findViewById(R.id.btn_exit);btnapps = (Button) mSettingTable.findViewById(R.id.btn_apps);btnback.setOnClickListener(mClickListener);btnhome.setOnClickListener(mClickListener);btnexit.setOnClickListener(mClickListener);btnapps.setOnClickListener(mClickListener);}private OnClickListener mClickListener = new OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_back: //执行了两次是因为第一次是回到小图标,然后在执行返回当前程序sendKeyCode(KeyEvent.KEYCODE_BACK);new Handler().postDelayed(new Runnable() {@Overridepublic void run() {sendKeyCode(KeyEvent.KEYCODE_BACK);}}, 500);break;case R.id.btn_home_screen:sendKeyCode(KeyEvent.KEYCODE_HOME);break;case R.id.btn_exit:sendKeyCode(KeyEvent.KEYCODE_BACK);break;case R.id.btn_apps:sendKeyCode(KeyEvent.KEYCODE_APP_SWITCH);break;}}};
//借用 input keyevent keycode命令,不同功能改变keycode即可,keycode对应值就百度~private void sendKeyCode(final int keyCode) {new Thread() {public void run() {String keyCommand = "input keyevent " + keyCode;try {Process process = Runtime.getRuntime().exec(keyCommand);} catch (IOException e) {e.printStackTrace();}}}.start();}
//监听touchprivate OnTouchListener mTouchListener = new OnTouchListener() {float lastX, lastY;int paramX, paramY;public boolean onTouch(View v, MotionEvent event) {final int action = event.getAction();float x = event.getRawX();float y = event.getRawY();if (mTag == 0) {mOldOffsetX = mWMParams.x;mOldOffsetY = mWMParams.y;}switch (action) {case MotionEvent.ACTION_DOWN:motionActionDownEvent(x, y);break;case MotionEvent.ACTION_MOVE:motionActionMoveEvent(x, y);break;case MotionEvent.ACTION_UP:motionActionUpEvent(x, y);break;default:break;}return true;}private void motionActionDownEvent(float x, float y) {lastX = x;lastY = y;paramX = mWMParams.x;paramY = mWMParams.y;}private void motionActionMoveEvent(float x, float y) {int dx = (int) (x - lastX);int dy = (int) (y - lastY);mWMParams.x = paramX + dx;mWMParams.y = paramY + dy;mTag = 1;mWManager.updateViewLayout(mTouchView, mWMParams);}private void motionActionUpEvent(float x, float y) {int newOffsetX = mWMParams.x;int newOffsetY = mWMParams.y;if (mOldOffsetX == newOffsetX && mOldOffsetY == newOffsetY) {mPopuWin = new PopupWindow(mSettingTable, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);mPopuWin.setTouchInterceptor(new OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {hideSettingTable();return true;}return false;}});mPopuWin.setBackgroundDrawable(new BitmapDrawable());mPopuWin.setTouchable(true);mPopuWin.setFocusable(true);mPopuWin.setOutsideTouchable(true);mPopuWin.setContentView(mSettingTable);if (Math.abs(mOldOffsetX) > midX) {if (mOldOffsetX > 0) {mOldOffsetX = midX;} else {mOldOffsetX = -midX;}}if (Math.abs(mOldOffsetY) > midY) {if (mOldOffsetY > 0) {mOldOffsetY = midY;} else {mOldOffsetY = -midY;}}mPopuWin.setAnimationStyle(R.style.AnimationPreview);mPopuWin.setFocusable(true);mPopuWin.update();mPopuWin.showAtLocation(mTouchView, Gravity.CENTER, -mOldOffsetX, -mOldOffsetY);// TODOmIconImageView.setBackgroundDrawable(getResources().getDrawable(R.drawable.transparent));catchSettingTableDismiss();} else {mTag = 0;}}};private void catchSettingTableDismiss() {mTimer = new Timer();mTask = new TimerTask() {@Overridepublic void run() {if (mPopuWin == null || !mPopuWin.isShowing()) {handler.sendEmptyMessage(0x0);}}};mTimer.schedule(mTask, 0, 100);}private void clearTimerThead() {if (mTask != null) {mTask.cancel();mTask = null;}if (mTimer != null) {mTimer.cancel();mTimer = null;}}Handler handler = new Handler() {public void handleMessage(Message msg) {mIconImageView.setBackgroundDrawable(getResources().getDrawable(R.drawable.touch_ic));};};public void showToast(Context context, String text) {if (mToast == null) {mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT);} else {mToast.setText(text);mToast.setDuration(Toast.LENGTH_SHORT);}mToast.show();}private void hideSettingTable(String content) {hideSettingTable();showToast(mContext, content);}private void hideSettingTable() {if (null != mPopuWin) {mPopuWin.dismiss();}}public interface ServiceListener {public void OnCloseService(boolean isClose);}

切记:需要签名,才可以实现input keyevent keycode

源码下载:下载地址

www.rebootvip.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/414161.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动态规划法例题

第一个空&#xff0c;用手工计算&#xff0c;可以用贪心法 先选择价值最大的物品&#xff0c;有两个价值是6的物品&#xff0c;重量合计246 剩余4个空间&#xff0c;只能放重量为2的物品&#xff0c;一共是66315 第二个空&#xff0c;需要将所有物品都放进背包舱室&#xff…

基于Python的量化交易回测框架Backtrader初识记录(一)

版权声明&#xff1a;本文为博主原创文章&#xff0c;如需转载请贴上原博文链接&#xff1a;基于Python的量化交易回测框架Backtrader初识记录&#xff08;一&#xff09;-CSDN博客 前言&#xff1a;近期以来&#xff0c;对股市数据获取及预处理算是告一段落&#xff0c;下一步…

OpenCV绘图函数(5)绘制标记函数drawMarker()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::drawMarker 函数在 OpenCV 中用于在一个给定的位置上绘制标记。目前支持几种不同的标记类型&#xff0c;具体信息可以参考 MarkerTypes 函数…

【C++ | 设计模式】观察者模式的详解与实现

1.概念 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;它的核心思想是定义对象间的一对多依赖关系&#xff0c;当一个对象的状态发生变化时&#xff0c;所有依赖于它的对象都会收到通知并自动更新。这个模式在现实生活中非常常见&#…

Selenium的四种部署方式详解

关于selenium 的部署&#xff0c;我在网上找了很多&#xff0c;基本上都没有提到或是说的比较清晰的。当时我一直有个困惑&#xff1a;测试的脚本代码&#xff0c;是放在跟浏览器同一台机器上呢&#xff0c;还是放在Application Server上&#xff1f; 在官方开发文档中&#x…

从0开始深度学习(2)——自动微分

1 微积分 1.1 导数和微分 略 1.2 偏导数 略 1.3 梯度&#xff08;gradient&#xff09; 1.3.1 定义 对于一个多变量函数 f ( x 1 , x 2 , … , x n ) f\left(x_{1}, x_{2}, \ldots, x_{n}\right) f(x1​,x2​,…,xn​)其中点 a ( a 1 , a 2 , … , a n ) \mathbf{a}(a_…

YGG深海传奇,创造财富无限可能!

随著区块链技术的创新与游戏产业的深度融合&#xff0c;GameFi赛道迅速崛起&#xff0c;成为全球投资者与玩家瞩目的新兴领域。 成立于2020年的Yield Guild Games(YGG)&#xff0c;作为全球区块链游戏领域的先锋公会之一&#xff0c;也加入到向去中心化经济模式的转型浪潮当中。…

E. Sheep Eat Wolves

https://codeforces.com/gym/104869/problem/E 赛时队友想贪心&#xff0c;贪不了一点&#xff0c;我想了数学办法每次都送固定的发现送过去就不满足了 赛后补&#xff0c;暴力做O&#xff08;n4) 至少要几次才能把安全所有羊送到对岸去 考虑最短路,bfs,用数组存下所有状态 …

17:4层板层叠设置

层叠设置参考PCB专栏 设置平面内缩 GND内缩设置20mil0.508mm 电源层内缩设置要比GND内缩大&#xff0c;设置40mil1mm

米家商城主题 html 页面源码分享,可用于网页设计作业

使用技术&#xff1a; HTML, CSS , Javascript 项目亮点&#xff1a; 1. 仿照米家商城页面布局所做的页面样式结构 2. 首页放置了可自动切换的轮播图 3. 登录页有表单结构&#xff0c;并且有切换的动画效果 4. 包含实时的动态时间&#xff0c;使用 js 实现 5. 页面布局清…

Datawhale X 李宏毅苹果书AI夏令营深度学习详解入门Task02

本文了解深度学习详解中的线性模型 本文了解深度学习详解中的线性模型将围绕梯度下降优化、线性模型的局限性、改进模型以及深度学习模型等关键要点展开讨论。 一、梯度下降优化 梯度下降是深度学习中常用的优化算法&#xff0c;它通过不断调整模型的参数&#xff0c;使得损失函…

axios发送post请求实例

在body中的数据格式又有两种&#xff0c;一种是 json 数据格式&#xff0c;另一种是 字符串。具体要用哪种格式取决于后端入参的格式。 如果后端接收json数据类型&#xff0c;post 的 headers 需要设置 { ‘content-type’: ’application/json’ }&#xff0c;传给后端的数…

【王树森】BERT:预训练Transformer模型(个人向笔记)

前言 BERT&#xff1a;Bidirectional Encoder Representations from TransformerBERT是用来预训练Transformer模型的encoder的本节课只讲述主要思想BERT用两个主要思想来训练Transformer的encoder网络&#xff1a;①随机遮挡单词&#xff0c;让encoder根据上下文来预测被遮挡的…

Fine-Grained Egocentric Hand-Object(中文翻译)

精细化自我中心手-物体分割&#xff1a; 数据集、模型&#xff08;model&#xff09;与应用 灵芝张1, 盛昊周1, 西蒙斯滕特 $ {}^{2} $, 和健博石 $ {}^{1} $ 摘要。 自我中心视频提供了高保真度建模人类行为的细粒度信息。手和交互对象是理解观众行为和意图的一个关键方面。…

掌握 JavaScript 解构赋值的指南

JavaScript 的解构赋值是一种从数组 or 对象中提取值并将其赋给变量的语法。这种语法让我们从复杂的数据结构中提取数据变得简洁和易读。解构赋值可以用在数组、对象以及嵌套结构中。 解构是&#xff1a;使用 ES6 的一种语法规则&#xff0c;将一个对象或数组的某个属性提取到…

JavaSE-递归法解决二分查找、快速排序

704. 二分查找https://leetcode.cn/problems/binary-search/ package demo;public class BinarySearch {public static void main(String[] args) {BinarySearch brnew BinarySearch();System.out.println(br.search(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}, 8));}public int s…

[Tools: LoRA] Diffusers中Stable Diffusion的实现

实现底层原理 Diffusers中的Attention操作实现在AttnProcessor类&#xff08;diffusers.models.attention_processor.py&#xff09;&#xff0c;里面定义了单次Attention操作。添加LoRA&#xff0c;本质上是用LoRAAttnProcessor类替换AttnProcessor类。LoRAAttnProcessor中新…

浅谈如何入门微信小程序?

一. 何为微信小程序&#xff1f; 1. 微信小程序是一种全新的连接用户与服务的方式 2. 它可以在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验 二. 如何开发小程序 1. 开发小程序的第一步&#xff1a; 你需要拥有一个小程序帐号&#xff0c;通过这个帐号你就…

vue如何引入element-ui

2.x用element-ui 3.x用element-plus https://blog.csdn.net/weixin_41207479/article/details/127066333 引入element-ui的三种方式

opencv之形态学

文章目录 1. 什么是形态学2. 形态学操作2.1 腐蚀2.2 膨胀2.3 通用形态学函数2.4 开运算2.5 闭运算2.6 形态学梯度运算2.7 礼帽运算2.8 黑帽运算 1. 什么是形态学 在图像处理领域&#xff0c;形态学是一种基于形状的图像分析技术&#xff0c;用于提取和处理图像的形态特征。这包…