安卓开发实现悬浮窗显示全局显示,通过悬浮窗实时监控当前流量

  • 1 实现效果
  • 2 参考学习
  • 3 实现说明
  • 4 项目代码
  • 5 下载地址

1 实现效果

2 参考学习

https://www.jb51.net/article/120126.htm
https://www.cnblogs.com/changyiqiang/p/11277069.html
原创链接https://blog.csdn.net/hongfei568718926/article/details/108760666
传送门
尊重原创

3 实现说明

1.悬浮窗的显示需要再服务中进行,否则无法对悬浮窗进行操作(测试只可以点击,其它就不行了,可能是线程问题)
2.悬浮窗需要考虑:Android 6.0之后的悬浮窗动态申请和
Window 的ype属性在Android8.0前后的适配
本次采用的是全局的悬浮窗开发,局部悬浮窗开发需要适配不同的手机进行,比较复杂.全局适配可以实现部分局部悬浮窗的功能,但是对于任务切换不能实现,(局部悬浮窗,任务切换的时候会显示,但是全局悬浮窗就不能实现)
3.安卓手机有一般权限,安全权限,和特殊权限(该项目使用了特殊权限的该应用可以至于其他应用上层)—>微信视频的时候默认必须打开这个权限,但是拼多多商城商品界面右上角直播的显示不打开也能实现,估计就是适配了任何app的局部悬浮窗实现的.
4.网络上面很多代码都跑不了添加addView的时候总是报错,估计是安卓系统版本和手机适配不一样,导致大家实现的功能不通用.
5.本代码,悬浮窗显示的时候通过设置了按钮点击的时长来判断是点击还是滑动.

4 项目代码

package com.example.trafficsate;import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;import org.w3c.dom.Text;public class MainActivity extends Activity {//定义浮动窗口布局LinearLayout mFloatLayout;//创建浮动窗口设置布局参数的对象WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();WindowManager mWindowManager;private Context mContext;private Button start;private Button remove;private boolean isFloatLayout=false;private ImageView floatView;private int x;private int y;private Intent serviceIntent;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext=MainActivity.this;start = (Button)findViewById(R.id.addbt);remove = (Button)findViewById(R.id.removebt);start.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){//Android 6.0之后的悬浮窗动态申请,覆盖显示权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !Settings.canDrawOverlays(getApplicationContext())) {startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + mContext.getPackageName())));}serviceIntent= new Intent(MainActivity.this, FxService.class);startService(serviceIntent);}});remove.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){stopService(serviceIntent);}});}@Overrideprotected void onPause() {super.onPause();}@Overrideprotected void onDestroy() {super.onDestroy();stopService(serviceIntent);}
}

2.流量实时监控

package com.example.trafficsate;
import android.content.Context;
import android.net.TrafficStats;
import android.os.Handler;
import android.os.Message;
import android.util.Log;import java.text.DecimalFormat;
import java.util.Timer;
import java.util.TimerTask;/*** Created by Ricky on 2016/10/13.*/
public class NetWorkSpeedUtils {private Context context;private Handler mHandler;private long lastTotalRxBytes = 0;private long lastTimeStamp = 0;public NetWorkSpeedUtils(Context context, Handler mHandler) {this.context = context;this.mHandler = mHandler;}TimerTask task = new TimerTask() {@Overridepublic void run() {showNetSpeed();}};public void startShowNetSpeed() {lastTotalRxBytes = getTotalRxBytes();lastTimeStamp = System.currentTimeMillis();new Timer().schedule(task, 1000, 1000); // 1s后启动任务,每2s执行一次}private long getTotalRxBytes() {return TrafficStats.getUidRxBytes(context.getApplicationInfo().uid) == TrafficStats.UNSUPPORTED ? 0 : (TrafficStats.getTotalRxBytes() / 1024);//转为KB}private void showNetSpeed() {long nowTotalRxBytes = getTotalRxBytes();long nowTimeStamp = System.currentTimeMillis();long speed = ((nowTotalRxBytes - lastTotalRxBytes) * 1000 / (nowTimeStamp - lastTimeStamp));//毫秒转换long speed2 = ((nowTotalRxBytes - lastTotalRxBytes) * 1000 % (nowTimeStamp - lastTimeStamp));//毫秒转换lastTimeStamp = nowTimeStamp;lastTotalRxBytes = nowTotalRxBytes;Message msg = mHandler.obtainMessage();msg.what = 100;msg.obj = getTotalSpeed(speed, speed2);//        msg.obj = String.valueOf(speed) + "." + String.valueOf(speed2) + " kb/s";mHandler.sendMessage(msg);//更新界面}private String getTotalSpeed(long speed, long speed2) {DecimalFormat showFloatFormat =new DecimalFormat("0.00");Log.d("速度", "speed: "+speed+",speed2"+speed2);String totalSpeedStr = "";if (speed >= 1024) {totalSpeedStr = showFloatFormat.format(speed/1024)+" M/s";} else {totalSpeedStr =showFloatFormat.format(speed+speed2/1024)+"K/s";}return totalSpeedStr;}
}

3.悬浮窗显示服务

package com.example.trafficsate;import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import java.lang.reflect.Method;public class FxService extends Service {//定义浮动窗口布局LinearLayout mFloatLayout;WindowManager.LayoutParams wmParams;//创建浮动窗口设置布局参数的对象WindowManager mWindowManager;private Context mContext;TextView mFloatView;private long startTime;private long endTime;private boolean isColor=true;private static final String TAG = "FxService";Handler handler=new Handler(){@Overridepublic void handleMessage(@NonNull Message msg) {switch (msg.what){case 100:mFloatView.setText(msg.obj.toString());break;}super.handleMessage(msg);}};@Overridepublic void onCreate(){super.onCreate();mContext=FxService.this;createFloatView();new NetWorkSpeedUtils(this,handler).startShowNetSpeed();}@Overridepublic IBinder onBind(Intent intent){return null;}private void createFloatView(){wmParams = new WindowManager.LayoutParams();//获取WindowManagerImpl.CompatModeWrappermWindowManager =  (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);//设置window typeif(Build.VERSION.SDK_INT>Build.VERSION_CODES.O){wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;}else{wmParams.type= WindowManager.LayoutParams.TYPE_TOAST;}//设置图片格式,效果为背景透明wmParams.format = PixelFormat.RGBA_8888;//设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)wmParams.flags =
//          LayoutParams.FLAG_NOT_TOUCH_MODAL |LayoutParams.FLAG_NOT_FOCUSABLE
//          LayoutParams.FLAG_NOT_TOUCHABLE;//调整悬浮窗显示的停靠位置为左侧置顶wmParams.gravity = Gravity.LEFT | Gravity.TOP;// 以屏幕左上角为原点,设置x、y初始值wmParams.x = 200;wmParams.y =200;//设置悬浮窗口长宽数据wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;LayoutInflater inflater = LayoutInflater.from(getApplication());//获取浮动窗口视图所在布局mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_layout, null);mFloatView = (TextView)mFloatLayout.findViewById(R.id.float_id);mWindowManager.addView(mFloatLayout, wmParams);// handler.sendEmptyMessage(1);//浮动窗口按钮mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));//设置监听浮动窗口的触摸移动mFloatView.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {boolean isclick=false;switch (event.getAction()){case MotionEvent.ACTION_DOWN:startTime=System.currentTimeMillis();break;case MotionEvent.ACTION_MOVE://getRawX是触摸位置相对于屏幕的坐标,getX是相对于按钮的坐标wmParams.x = (int) event.getRawX() - mFloatView.getMeasuredWidth()/2;wmParams.y = (int) event.getRawY() - mFloatView.getMeasuredHeight()/2 - 25;//刷新mWindowManager.updateViewLayout(mFloatLayout, wmParams);break;case MotionEvent.ACTION_UP:endTime=System.currentTimeMillis();//小于0.2秒被判断为点击if ((endTime - startTime) > 200) {isclick = false;} else {isclick = true;}break;}//响应点击事件if (isclick) {if(isColor){mFloatView.setBackgroundColor(Color.RED);isColor=!isColor;}else{mFloatView.setBackgroundColor(Color.GREEN);isColor=!isColor;}Toast.makeText(mContext, "点击了", Toast.LENGTH_SHORT).show();}return true;}});mFloatView.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){Toast.makeText(FxService.this, "onClick", Toast.LENGTH_SHORT).show();}});}@Overridepublic void onDestroy(){super.onDestroy();if(mFloatLayout != null){mWindowManager.removeView(mFloatLayout);}}}

4.权限配置.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.trafficsate"><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><serviceandroid:name=".FxService"android:enabled="true"android:exported="true"></service><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

5,2个布局文件.

<?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"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/addbt"android:text="加入浮动"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Buttonandroid:id="@+id/removebt"android:text="移除浮动"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout></LinearLayout><!--------布局文件2--------------><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/linearlayout"android:orientation="vertical" ><TextViewandroid:id="@+id/float_id"android:layout_width="30dp"android:layout_height="30dp"android:layout_gravity="center"android:background="@color/colorAccent"android:clickable="true"android:textSize="8dp"android:text="浮动显示"/></LinearLayout>

5 下载地址

https://download.csdn.net/download/hongfei568718926/12882438

安卓开发实现悬浮窗显示(全局显示),通过悬浮窗实时监控当前流量相关推荐

  1. Android悬浮窗适配,无需权限适配全机型,最简单最高性能的实现全局显示圆形悬浮

    github:https://github.com/feiyuu/FloatingView 适配方式就是不用悬浮窗,弹框之类的,在每个页面顶层添加布局.缺点是不能退出app后在手机桌面显示. 想做桌面 ...

  2. 关于安卓开发计步器在安卓10.0版本无法显示步数问题

      由于某种原因,要做一个安卓的简单计步器,只有一点JAVA知识的我参照了[二克拉梦想 ]这个大佬的CSDN博客和github,制作了 一个简单的安卓计步器.   首先万分感谢大佬的付出让我节省了很多 ...

  3. 炸弹人游戏开发系列(3):显示地图

    前言 上文我们进行了初步的高层设计,现在我们将实现图片预加载和显示地图的功能需求.我采用TDD开发,大家可以看到在实现的过程中我们会修改设计,修改设计后又会修改对应的实现代码,这是一个不断迭代的过程. ...

  4. HTML5游戏开发(四):飞机大战之显示场景和元素

    <HTML5游戏开发>系列文章的目的有:一.以最小的成本去入门egret小项目开发,官方的教程一直都是面向中重型:二.egret可以非常轻量:三.egret相比PIXI.js和sprite ...

  5. java 鼠标停留时,[Java教程]鼠标悬浮停留三秒 显示大图_星空网

    鼠标悬浮停留三秒 显示大图 2014-06-27 0 网站大连烟花网 http://dlyh365.com *{margin:0;padding:0;list-style-type:none;} im ...

  6. linux fedora kde桌面设置全局显示字体大小

    linux fedora kde桌面设置全局显示字体大小

  7. android 代码设置居右_Android 开发实现EditText 光标居右显示

    Android 开发实现EditText 光标居右显示 前言: 有些时候肯定会遇到这种奇葩的需求,光标要靠右显示,因为Android里面光标默认是靠左显示的,那怎么实现呢,肯定有办法的,这里提供一种实 ...

  8. iOS SwiftUI 开发实机测试 TextField 不显示字

    iOS SwiftUI 开发实机测试 TextField 不显示字 iOS 实机测试不显示文字 解决问题 iOS 实机测试不显示文字 记录一个很蠢的问题,如图所示: 我勒个大槽,明明预览和模拟机上都有 ...

  9. android下载通知栏,Android开发中实现下载文件通知栏显示进度条

    android开发中实现下载文件通知栏显示进度条. 1.使用asynctask异步任务实现,调用publishprogress()方法刷新进度来实现(已优化) public class myasync ...

  10. android时间24小时,安卓时间显示TextClock显示日期时间,24小时制和12小时制(自定义...

    安卓时间显示TextClock显示日期时间,24小时制和12小时制(自定义 安卓时间显示TextClock显示日期时间,24小时制和12小时制(自定义时间) 这个地方的是按24小时制还是12小时制 是 ...

最新文章

  1. 【Linux探索之旅】第二部分第五课:用户和权限,有权就任性
  2. HALCON查找圆心C++实现
  3. 进阶学习(1) Gradle 项目管理工具的使用
  4. ABP学习 解决:Update-Database : 无法将“Update-Database”项识别为 cmdlet、函数、脚本文件或可运行程序的名称的问题...
  5. i春秋DMZ大型靶场实验(四)Hash基础
  6. 微软家庭服务器,微软公布Windows Server 2012版本方案,不再提供家庭服务器版
  7. 一路向左or一路向右
  8. FFA 2021 专场解读 - 实时数据湖
  9. 官网下载STM32系列芯片的产品选型手册
  10. 计算机组成原理课程设计
  11. C51与MDK共存 Keil5安装教程
  12. 【Markdown 数学公式】markdown常用公式写法
  13. MySQL篇之授权用户可以远程访问数据库
  14. phpcms搜索功能实现
  15. 适合所有网站的前端优化技巧,值得你收藏!
  16. Tableau 添加加权平均参考线
  17. 楼教主的ACM心路历程
  18. 短文本匹配模型-ESIM
  19. mysql的cpu使用率突然增高_mysql cpu使用率过高解决方法
  20. 【博学谷学习记录】超强总结,用心分享 | 架构师 Netty框架学习总结

热门文章

  1. 5G基站:宏基站微基站皮基站飞基站
  2. biosrecovery什么意思_卡刷和线刷手机什么意思 Recovery使用方法
  3. 精神分析理论-弗洛伊德
  4. 【C语言】输出一个菱形
  5. 分位数回归(quantile regression)简介和代码实现
  6. KDD2020|字节联合密歇根州立大学提出推荐广告联合训练框架RAM(已开源)
  7. lbj学习日记 04 循环和选择结构的刷题心得
  8. 锻造互联网青铜时代 (转)
  9. php里macd预测算法,股票MACD指标算法公式
  10. 共模电感适用的频率_共模电感的原理以及使用情况