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);}});}}

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

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

相关文章

Zoom使用的基本步骤和注意事项

Zoom是一款功能强大的视频会议软件&#xff0c;广泛应用于远程办公、在线教育、团队协作等多个场景。以下是Zoom使用的基本步骤和注意事项&#xff1a; 一、注册与登录 注册Zoom账户&#xff1a; 访问Zoom官方网站&#xff08;如zoom.us&#xff09;&#xff0c;点击“注册”…

mybatis实现动态sql

第一章、动态SQL MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验&#xff0c;你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格&#xff0c;还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特…

[ C++ ] 深入理解模板( 进 阶 )

目录 非类型模板参数 类模板没有实例化的情况 模板的特化 注意函数特化中遇到的问题 建议&#xff1a;&#xff08;直接使用函数重载&#xff09; 类模板特化 全特化 偏特化 偏特化有以下两种表现方式&#xff1a; 部分特化&#xff08;将模板参数类表中的一部分参数特化…

旅游系统(附管理端+前台)PHP源码

一. 前言 今天小编给大家带来了一款可学习&#xff0c;可商用的&#xff0c;旅游系统 源码&#xff0c;支持二开&#xff0c;无加密。支持景点管理&#xff0c;登录&#xff0c;景点预定&#xff0c;意见反馈&#xff0c;统计等功能。详细界面和功能见下面视频演示。 二. 视频…

【flutter问题记录】 无效的源发行版:17

问题描述 在看开源项目的时候&#xff0c;clone下来后一直编译失败&#xff0c;提示&#xff1a;无效的源发行版:17&#xff0c;看描述大概是jdk的版本问题&#xff0c;但是在Android studio各种指定都无用&#xff0c;网上资料也没有flutter项目的解决方案&#xff0c;最后在…

广州自闭症机构哪家好?

在广州&#xff0c;众多的自闭症康复机构中&#xff0c;星贝育园自闭症儿童康复学校以其独特的优势脱颖而出。 一、专业的师资团队 我们拥有一支经验丰富、专业素养极高的师资队伍。每位老师都经过严格的专业培训&#xff0c;深入了解自闭症儿童的特点和需求。他们不仅具…

深入挖掘海外快手kwai ads推广巴西slots手游广告独家优势

深入挖掘海外快手kwai ads推广巴西slots手游广告独家优势 在数字化时代&#xff0c;广告投放已成为各行各业不可或缺的一部分&#xff0c;特别是在游戏行业&#xff0c;如何有效地推广游戏产品&#xff0c;吸引玩家的眼球&#xff0c;成为了每一个游戏开发商和广告主所关注的焦…

假设性文档嵌入 HyDE:大模型 + 对比学习,从关键词相似度搜索到语义搜索

假设性文档嵌入 HyDE&#xff1a;大模型 对比学习&#xff0c;从关键词相似度搜索到语义搜索 提出背景流程图解法拆解类比1. 单一文档嵌入空间的搜索2. 指令跟随型语言模型&#xff08;InstructLM&#xff09;的引入3. 生成文档的嵌入编码 提出背景 论文&#xff1a;https://…

python怎么样将一段程序无效掉

1、python中可以用注释屏蔽一段语句&#xff0c;具体方法如下&#xff0c;首先打开一段python的示例程序&#xff1a; 2、然后单行注释的方法是在语句前面加上#&#xff0c;程序运行后添加注释的地方的语句会被自动跳过&#xff0c;这里可以看到将打印变量a的语句添加注释就没有…

【实验室精选】PFA反应瓶带鼓泡球 高效气体鼓泡 化学分析优选

PFA反应瓶带鼓泡球是一种特殊设计的实验室容器&#xff0c;它集成了鼓泡球和PFA&#xff08;全氟烷氧基&#xff09;材料的反应瓶&#xff0c;用于气体的鼓泡和液体的混合。以下是它的一些特点和用途&#xff1a; 特点&#xff1a; 鼓泡球设计&#xff1a;鼓泡球周围布满小孔&…

界面材料知识

界面材料是用于填充芯片和散热器之间的空隙&#xff0c;将低导热系数的空气挤出&#xff0c;换成较高导热系数的材料&#xff0c;以提高芯片散热能力。参考下图 图片来源网上 热阻是衡量界面材料性能最终的参数&#xff0c;其中与热阻有关的有&#xff1a; 1、导热系数&#x…

从零开始学习SLAM(三)

旋转向量 #include <Eigen/Geometry> #include <Eigen/Core>AngleAxisd 类有几种构造函数&#xff0c;其中最常用的是&#xff1a; Eigen::AngleAxisd(const Scalar& angle, const Axis& axis);angle 是旋转的角度&#xff0c;通常以弧度表示。axis 是旋…

element-ui el-select选择器组件下拉框增加自定义按钮

element-ui el-select选择器组件下拉框增加自定义按钮 先看效果 原理&#xff1a;在el-select下添加禁用的el-option&#xff0c;将其value绑定为undefined&#xff0c;然后覆盖el-option禁用状态下的默认样式即可 示例代码如下&#xff1a; <template><div class…

【 VIPKID-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

基于Istio的多网关运行时:配置、部署和应用

1. 引言 Istio是一个开源的服务网格&#xff0c;主要应用于简化微服务架构中的服务间通信、提供强大的监控能力以及加强服务的安全管理。通过利用Sidecar模式部署的Envoy代理&#xff0c;Istio能够在几乎无需修改服务代码的情况下&#xff0c;实现服务发现、负载均衡、加密通信…

WRF学习——使用CMIP6数据驱动WRF/基于ncl与vdo的CMIP6数据处理

动力降尺度 国际耦合模式比较计划&#xff08;CMIP&#xff09;为研究不同情景下的气候变化提供了大量的模拟数据&#xff0c;而在实际研究中&#xff0c;全球气候模式输出的数据空间分辨率往往较低&#xff08;>100Km&#xff0c;缺乏区域气候特征&#xff0c;为了更好地研…

【pytorch14】感知机

单层感知机模型 对于单层的感知机&#xff0c;它的激活函数是一个sigmoid 对于符号的定义做一个规范化&#xff0c;输入层每一层进行一个编号 输入是第0层&#xff0c;上标0表示属于输入层&#xff0c;下标0到n表示一共有n个节点(这里严格来说应该是0~n-1&#xff0c;为了书写…

一站式广告监测新体验,Xinstall助你广告投放更精准

在这个移动互联网飞速发展的时代&#xff0c;App推广与运营成为了每个开发者与广告主关注的焦点。然而&#xff0c;面对琳琅满目的广告平台和复杂的投放环境&#xff0c;如何精准评估广告效果、优化投放策略&#xff0c;成为了摆在面前的一道难题。今天&#xff0c;我们就来聊聊…

Jemeter--关联接口压测

Jemeter–独立不变参接口压测 Jemeter–独立变参接口压测 Jemeter–关联接口压测 案例分析 比如&#xff1a;有个波次复核接口很慢&#xff0c;优化后需要压测。但是波次复核接口数据是由另外两个接口&#xff08;配单详情、内盒信息&#xff09;的数据组合而来&#xff0c;而…

fastadmin最新版导出数据时 表格中会有 html标签的解决办法

fastadmin 自带的导出方法&#xff0c; 是一个纯前端的导出&#xff0c; 没有请求后台的接口 当我们使用导出功能时&#xff0c; 有些数据&#xff0c; 我们在设计的时候&#xff0c;配置的是 枚举类型的 但是当我们导出数据的时候&#xff0c; 居然导出的数据中带有 html 的…