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

Android10以上实现获取设备序列号功能

Android10以上实现获取设备唯一标识,目前只支持华为和荣耀设备。实现原理:通过无障碍服务读取序列号界面。

public class DeviceHelper implements Application.ActivityLifecycleCallbacks {static final String TAG = "WADQ_DeviceHelper";static final String ACTION_ACQUIRE_SERIAL_SUCCESS = "zwxuf.intent.action.ACQUIRE_SERIAL_SUCCESS";private static Handler mHandler = new Handler(Looper.getMainLooper());private boolean isMsgReceiverEnabled;private OnAcquireSerialListener mOnAcquireSerialListener;private Activity mActivity;private Application mApplication;public DeviceHelper(Activity mActivity) {this.mActivity = mActivity;mApplication = mActivity.getApplication();mApplication.registerActivityLifecycleCallbacks(this);}public void acquireSerial(OnAcquireSerialListener listener) {mOnAcquireSerialListener = listener;if (!isMsgReceiverEnabled) initMsgReceiver();AcquireSerialService.isSerialFound = false;AcquireSerialService.isStatusInfoFound = false;Intent intent = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mActivity.startActivity(intent);}private void releaseAcquireSerial() {List<Service> services = getServices();for (Service service : services) {if (service instanceof AcquireSerialService) {((AcquireSerialService) service).release();break;}}}private void initMsgReceiver() {IntentFilter filter = new IntentFilter(ACTION_ACQUIRE_SERIAL_SUCCESS);mActivity.registerReceiver(mMsgReceiver, filter);isMsgReceiverEnabled = true;}private BroadcastReceiver mMsgReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String serial = intent.getStringExtra("serial");if (mOnAcquireSerialListener != null) {mOnAcquireSerialListener.onAcquireSerial(serial);}releaseMsgReciever();}};private void releaseMsgReciever() {if (isMsgReceiverEnabled) {mActivity.unregisterReceiver(mMsgReceiver);isMsgReceiverEnabled = false;}}public void release() {releaseMsgReciever();mApplication.unregisterActivityLifecycleCallbacks(this);releaseAcquireSerial();}public boolean canAcquireSerial() {return isServiceEnabled(mActivity, AcquireSerialService.class);}public void openAcquireSerialSettings(final int requestCode) {Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);try {mActivity.startActivityForResult(intent, requestCode);} catch (Exception e) {e.printStackTrace();}}private static boolean isServiceEnabled(Context context, Class<? extends AccessibilityService> serviceClass) {if (serviceClass == null) {return false;}String serviceName = context.getPackageName() + "/" + serviceClass.getName();try {int enabled = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);if (enabled == 1) {String service = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);Log.i(TAG, service);return service != null && service.contains(serviceName);}} catch (Exception e) {e.printStackTrace();}return false;}static Handler getHandler() {return mHandler;}@Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {}@Overridepublic void onActivityStarted(Activity activity) {}@Overridepublic void onActivityResumed(Activity activity) {}@Overridepublic void onActivityPaused(Activity activity) {}@Overridepublic void onActivityStopped(Activity activity) {}@Overridepublic void onActivitySaveInstanceState(Activity activity, Bundle outState) {}@Overridepublic void onActivityDestroyed(Activity activity) {if (activity == mActivity) {release();}}private static List<Service> getServices() {List<Service> services = new ArrayList<>();Object mActivityThread = getActivityThread();try {Class mActivityThreadClass = mActivityThread.getClass();Field mServicesField = mActivityThreadClass.getDeclaredField("mServices");mServicesField.setAccessible(true);Object mServices = mServicesField.get(mActivityThread);if (mServices instanceof Map) {Map<IBinder, Service> arrayMap = (Map) mServices;for (Map.Entry<IBinder, Service> entry : arrayMap.entrySet()) {Service service = entry.getValue();if (service != null) {services.add(service);}}}} catch (Throwable e) {e.printStackTrace();}return services;}private static Object getActivityThread() {try {Class ActivityThread = Class.forName("android.app.ActivityThread");Method currentActivityThread = ActivityThread.getMethod("currentActivityThread");currentActivityThread.setAccessible(true);return currentActivityThread.invoke(null);} catch (Throwable e) {e.printStackTrace();}return null;}}
public class AcquireSerialService extends AccessibilityService {static boolean isStatusInfoFound;static boolean isSerialFound;@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {if (event.getPackageName() == null || event.getClassName() == null) {return;}String packageName = event.getPackageName().toString();String className = event.getClassName().toString();final AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo != null) {if (!packageName.equals(getApplicationContext().getPackageName())) {enumChildNodeInfo(packageName, nodeInfo, 0);}}}@Overridepublic void onInterrupt() {}private Runnable mScrollRunnalbe;private void enumChildNodeInfo(String packageName, AccessibilityNodeInfo nodeInfo, int level) {int count = nodeInfo.getChildCount();if (count > 0) {for (int i = 0; i < count; i++) {final AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);if (childNodeInfo == null) continue;if (childNodeInfo.isScrollable()) {childNodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);}if (!isSerialFound) {String serial = getSerialByNodeInfo(packageName, childNodeInfo);if (serial != null && !serial.isEmpty()) {//获取到snLog.i(DeviceHelper.TAG, serial);Intent intent = new Intent(DeviceHelper.ACTION_ACQUIRE_SERIAL_SUCCESS);intent.putExtra("serial", serial);sendBroadcast(intent);performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);DeviceHelper.getHandler().postDelayed(new Runnable() {@Overridepublic void run() {performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);release();}}, 200);return;}enumChildNodeInfo(packageName, childNodeInfo, level + 1);}}}nodeInfo.recycle();}private String getSerialByNodeInfo(String packageName, AccessibilityNodeInfo nodeInfo) {if (nodeInfo.getText() == null) {return null;}String text = nodeInfo.getText().toString();if (text.equals("序列号")) {isStatusInfoFound = true;isSerialFound = true;if (mScrollRunnalbe != null) {DeviceHelper.getHandler().removeCallbacks(mScrollRunnalbe);mScrollRunnalbe = null;}return getValue(nodeInfo);} else if (packageName.equals("com.android.settings") && (text.equals("状态信息") || text.equals("状态消息")) && !isStatusInfoFound) {isStatusInfoFound = true;AccessibilityNodeInfo statusInfoParent = nodeInfo.getParent();while (statusInfoParent != null && !statusInfoParent.isClickable()) {statusInfoParent = statusInfoParent.getParent();}if (statusInfoParent != null) {final AccessibilityNodeInfo finalStatusInfoParent = statusInfoParent;DeviceHelper.getHandler().postDelayed(new Runnable() {@Overridepublic void run() {finalStatusInfoParent.performAction(AccessibilityNodeInfo.ACTION_CLICK);}}, 200);}}return null;}private String getValue(AccessibilityNodeInfo nodeInfo) {AccessibilityNodeInfo snLayout = nodeInfo.getParent();if (snLayout != null) {while (true) {List<AccessibilityNodeInfo> snSummaryList = snLayout.findAccessibilityNodeInfosByViewId("android:id/summary");if (snSummaryList != null && !snSummaryList.isEmpty()) {AccessibilityNodeInfo snSummary = snSummaryList.get(0);if (snSummary != null && snSummary.getText() != null) {return snSummary.getText().toString();}}snLayout = snLayout.getParent();if (snLayout == null) {break;}}}return null;}private String getNodeText(AccessibilityNodeInfo nodeInfo) {if (nodeInfo != null && nodeInfo.getText() != null) {return nodeInfo.getText().toString();} else {return null;}}public void release() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {disableSelf();}}
}

public class MainActivity extends AppCompatActivity implements View.OnClickListener {private DeviceHelper mDeviceHelper;private TextView tv_serial, tv_phone;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv_serial = findViewById(R.id.tv_serial);mDeviceHelper = new DeviceHelper(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.bn_get_serial:getSerial();break;}}private void getSerial() {if (!mDeviceHelper.canAcquireSerial()) {new AlertDialog.Builder(this).setMessage("没有开启无障碍服务").setPositiveButton("去开启", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {mDeviceHelper.openAcquireSerialSettings(1000);}}).setNegativeButton("取消", null).create().show();return;}mDeviceHelper.acquireSerial(new OnAcquireSerialListener() {@Overridepublic void onAcquireSerial(String serial) {//Toast.makeText(MainActivity.this, serial, Toast.LENGTH_SHORT).show();tv_serial.setText("sn:" + serial);}});}}

下载地址:https://download.csdn.net/download/zzmzzff/89515671

相关文章:

Android10以上实现获取设备序列号功能

Android10以上实现获取设备唯一标识&#xff0c;目前只支持华为和荣耀设备。实现原理&#xff1a;通过无障碍服务读取序列号界面。 public class DeviceHelper implements Application.ActivityLifecycleCallbacks {static final String TAG "WADQ_DeviceHelper";s…...

从0到1:培训老师预约小程序开发笔记二

背景调研 培训老师预约小程序&#xff1a; 教师和学生可以更便捷地安排课程&#xff0c;并提升教学质量和学习效果&#xff0c;使之成为管理和提升教学效果的强大工具。培训老师可以在小程序上设置自己的可预约时间&#xff0c;学员可以根据老师的日程安排选择合适的时间进行预…...

【FFmpeg】av_read_frame函数

目录 1.av_read_frame1.2 从pkt buffer中读取帧&#xff08;avpriv_packet_list_get&#xff09;1.3 从流当中读取帧&#xff08;read_frame_internal&#xff09;1.3.1 读取帧&#xff08;ff_read_packet&#xff09;1.3.2 解析packet&#xff08;parse_packet&#xff09;1.3…...

女生学计算机好不好?感觉计算机分有点高……?

众所周知&#xff0c;在国内的高校里&#xff0c;计算机专业的女生是非常少的&#xff0c;很多小班30人左右&#xff0c;但是每个班女生人数只有个位数。这就给很多人一个感觉&#xff0c;是不是女生天生就不适合学这个东西呢&#xff1f;女生是不是也应该放弃呢&#xff1f;当…...

windows10/11 如何开启卓越性能模式

在Windows 10和Windows 11中&#xff0c;可以通过以下步骤启用“卓越性能”模式。请注意&#xff0c;卓越性能模式仅在Windows 10 Pro for Workstations和Windows 10 Enterprise版本中可用。 使用命令提示符启用卓越性能模式 打开命令提示符&#xff1a; 按Win X键&#xff0…...

JSP WEB开发(二) JavaBean

目录 JavaBean JavaBean特征 JavaBean的标签 JavaBean 的范围 标签 JavaBean JavaBean 是一种符合某些命名和设计规范的 Java 类&#xff0c;它是一种可重用组件技术&#xff0c;主要用于封装数据&#xff0c;执行负责的计算任务&#xff0c;封装事务逻辑等。JavaBean 的实…...

G2.【C语言】EasyX绘制颜色窗口

1.窗口 窗口&#xff1a;宽度*高度&#xff08;单位都是像素&#xff09; #include <stdio.h> #include <easyx.h> int main() {initgraph(640, 480);getchar();return 0; } 640是宽&#xff0c;480是高 2.操作窗口的三个按钮 #include <stdio.h> #incl…...

异构计算技术与DTK异构开发套件

异构计算技术与DTK异构开发套件 费林分类法&#xff1a;SISD SIMD MISD MIMD 指令流I和数据流D MIMD不同存储结构&#xff1a; UMA均匀存储访问模型NUMA非均匀存储访问模型Cluster集群 现在以Cluster为主 DTK异构开发套件 生态结构 异构并行编程模型是什么 HIP&#xff…...

数据结构之“栈”(全方位认识)

&#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;数据结构 前言 栈是一种数据结构&#xff0c;具有" 后进先出 "的特点 或者也可见说是 ” 先进后出 “。大家一起加油吧冲冲冲&#xff01;&#xff01; …...

vue项目打包部署后 浏览器自动清除缓存问题(解决方法)

vue打包部署后 浏览器缓存问题&#xff0c;导致控制台报错ChunkLoadError: Loading chunk failed的解决方案 一、报错如下&#xff1a; 每次build打包部署到服务器上时&#xff0c;偶尔会出现前端资源文件不能及时更新到最新&#xff0c;浏览器存在缓存问题&#xff0c;这时在…...

解决vscode配置C++编译带有中文名称报错问题

在新电脑上安装vscode运行带有中文路径和中文名称的C代码时遇到报错 根据别人的教程将laugh.json文件中"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",改成了"program": "${fileDirname}\\output\\test.exe",&#x…...

A61 STM32_HAL库函数 之 TIM扩展驱动 -- C -- 所有函数的介绍及使用

A61 STM32_HAL库函数 之 TIM扩展驱动 -- C -- 所有函数的介绍及使用 1 该驱动函数预览1.24 HAL_TIMEx_OnePulseN_Stop1.25 HAL_TIMEx_OnePulseN_Start_IT1.26 HAL_TIMEx_OnePulseN_Stop_IT1.27 HAL_TIMEx_ConfigCommutationEvent1.28 HAL_TIMEx_ConfigCommutationEvent_IT1.29 …...

使用瀚高数据库开发管理工具进行数据的备份与恢复---国产瀚高数据库工作笔记008

使用瀚高数据库,备份 恢复数据 然后找到对应的目录 其实就是hgdbdeveloper,瀚高的数据库开发管理工具 对应的包中有个dbclient 这个目录,选中这个目录以后,就可以了,然后 在对应的数据库,比如 data_middle 中,选中 某个模式,比如bigdata_huiju 然后右键进行,点击 恢复,然…...

css 选择器汇总

目录 所有选择器伪类选择器 所有选择器 选择器用法id选择器#myid类选择器.myclassname标签选择器div,h1,p相邻选择器h1p子选择器ul > li后代选择器li a通配符选择器*属性选择器a[rel“external”]伪类选择器a:hover, li:nth-child 伪类选择器 在CSS3中新增了一个结构伪类选…...

My Greedy Algorithm(贪心算法)之路(一)

引子&#xff1a;我们之前&#xff0c;其实也遇到过贪心算法&#xff0c;0,1背包就是一个典型的贪心算法问题&#xff0c;那今天我就来开始my-Greedy Algorithm的道路。 什么是贪心算法&#xff1f; 我愿称贪心算法为贪婪鼠目寸光&#xff0c;贪心算法&#xff08;Greedy Alg…...

Win11 Python3.10 安装pytorch3d

0&#xff0c;背景 Python3.10、cuda 11.7、pytorch 2.0.1 阅读【深度学习】【三维重建】windows10环境配置PyTorch3d详细教程-CSDN博客 1&#xff0c;解决方法 本来想尝试&#xff0c;结果发现CUB安装配置对照表里没有cuda 11.7对应的版本&#xff0c;不敢轻举妄动&#x…...

kotlin 中 string array 怎么表示

在 Kotlin 中&#xff0c;字符串数组可以使用 Array<String> 类型表示。你可以通过多种方式来创建和初始化字符串数组。以下是几种常见的方法&#xff1a; 使用 arrayOf 函数&#xff1a; val stringArray arrayOf("Hello", "World", "Kotli…...

ffmpeg使用bmp编码器把bgr24编码为bmp图像

version #define LIBAVCODEC_VERSION_MAJOR 60 #define LIBAVCODEC_VERSION_MINOR 15 #define LIBAVCODEC_VERSION_MICRO 100 note 不使用AVOutputFormat code void CFfmpegOps::EncodeBGR24ToBMP(const char* infile, const char* width_str, const char* height_str…...

基于YOLOv10+YOLOP+PYQT的可视化系统,实现多类别目标检测+可行驶区域分割+车道线分割【附代码】

文章目录 前言视频效果必要环境一、代码结构1、 训练参数解析2、 核心代码解析1.初始化Detector类2. torch.no_grad()3. 复制输入图像并初始化计数器4. 调用YOLOv10模型进行目标检测5. 提取检测结果信息6. 遍历检测结果并在图像上绘制边界框和标签7. 准备输入图像以适应End-to-…...

计算机网络之令牌总线

上文内容&#xff1a;什么是以太网 1.令牌总线工作原理 在总线的基础上&#xff0c;通过在网络结点之间有序地传递令牌来分配各结点对共享型总线的访问权利&#xff0c;形成闭合的逻辑环路。 完全采用半双工的操作方式&#xff0c;只有获得令牌的结点才能发送信息&#xff…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...