安卓无障碍脚本开发全教程

在这里插入图片描述

文章目录

    • 第一部分:无障碍服务基础
      • 1.1 无障碍服务概述
        • 核心功能:
      • 1.2 基本原理与架构
      • 1.3 开发环境配置
        • 所需工具:
        • 关键依赖:
    • 第二部分:创建基础无障碍服务
      • 2.1 服务声明配置
      • 2.2 服务配置文件
        • 关键属性说明:
      • 2.3 实现服务类
    • 第三部分:高级功能实现
      • 3.1 节点查找与操作
        • 常用查找方法:
        • 节点操作示例:
      • 3.2 手势模拟
      • 3.3 全局事件监听
    • 第四部分:实战案例开发
      • 4.1 自动填写表单
      • 4.2 消息自动回复
      • 4.3 游戏自动化辅助
    • 第五部分:调试与优化
      • 5.1 调试技巧
        • ADB调试命令:
        • 日志记录最佳实践:
      • 5.2 性能优化
        • 优化建议:
        • 优化示例:
    • 第六部分:发布与安全
      • 6.1 权限与隐私
        • 必要权限声明:
        • 隐私注意事项:
      • 6.2 发布流程
    • 第七部分:高级主题
      • 7.1 与其他技术的结合
        • 与Tasker集成:
        • 使用机器学习:
      • 7.2 跨版本兼容性处理
        • 版本差异处理表:
        • 兼容性代码示例:

在这里插入图片描述

第一部分:无障碍服务基础

1.1 无障碍服务概述

安卓无障碍服务(Accessibility Service)是一种特殊类型的服务,旨在帮助残障用户或需要辅助功能的用户更好地使用设备。但它的功能远不止于此,开发者可以利用它实现自动化操作、界面监控和交互等功能。

核心功能:
  • 界面内容访问:获取屏幕上的UI元素信息
  • 自动化操作:模拟点击、滑动等用户操作
  • 事件监控:监听窗口变化、通知、焦点改变等系统事件
  • 增强交互:为特定应用提供定制化辅助功能

1.2 基本原理与架构

用户操作 目标应用 无障碍服务 系统框架 触发界面变化 更新界面状态 发送AccessibilityEvent 处理事件 可选: 执行操作(点击/滑动等) 执行请求的操作 用户操作 目标应用 无障碍服务 系统框架

1.3 开发环境配置

所需工具:
  • Android Studio最新版
  • 安卓设备或模拟器(API 16+)
  • ADB调试工具
关键依赖:
dependencies {implementation 'androidx.core:core-ktx:1.7.0'implementation 'androidx.appcompat:appcompat:1.4.1'
}

第二部分:创建基础无障碍服务

2.1 服务声明配置

AndroidManifest.xml中添加服务声明:

<serviceandroid:name=".MyAccessibilityService"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"android:exported="true"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService" /></intent-filter><meta-dataandroid:name="android.accessibilityservice"android:resource="@xml/service_config" />
</service>

2.2 服务配置文件

创建res/xml/service_config.xml

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"android:description="@string/accessibility_service_description"android:accessibilityEventTypes="typeAllMask"android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows"android:canRetrieveWindowContent="true"android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity"android:canRequestFilterKeyEvents="true"android:canPerformGestures="true"android:notificationTimeout="100"android:packageNames="com.example.targetapp" />
关键属性说明:
  • accessibilityEventTypes:监听的事件类型
  • packageNames:指定监控的应用包名(可选)
  • canPerformGestures:允许执行手势操作(API 24+)

2.3 实现服务类

创建基础服务类MyAccessibilityService.kt

class MyAccessibilityService : AccessibilityService() {override fun onServiceConnected() {Log.d("A11yService", "无障碍服务已连接")// 可以在此处进行服务配置更新val info = AccessibilityServiceInfo().apply {eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED or AccessibilityEvent.TYPE_WINDOW_STATE_CHANGEDfeedbackType = AccessibilityServiceInfo.FEEDBACK_GENERICnotificationTimeout = 100flags = AccessibilityServiceInfo.DEFAULT orAccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS}this.serviceInfo = info}override fun onAccessibilityEvent(event: AccessibilityEvent?) {event ?: returnwhen (event.eventType) {AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED -> {handleWindowChange(event)}AccessibilityEvent.TYPE_VIEW_CLICKED -> {handleViewClick(event)}}}override fun onInterrupt() {Log.w("A11yService", "无障碍服务被中断")}private fun handleWindowChange(event: AccessibilityEvent) {val rootNode = rootInActiveWindow ?: returnLog.d("A11yService", "窗口变化: ${event.packageName}")// 遍历视图树traverseNode(rootNode)}private fun traverseNode(node: AccessibilityNodeInfo, depth: Int = 0) {if (node.childCount == 0) {Log.d("A11yTree", "${" ".repeat(depth)}${node.viewIdResourceName}")return}for (i in 0 until node.childCount) {node.getChild(i)?.let { child ->traverseNode(child, depth + 1)child.recycle()}}}
}

第三部分:高级功能实现

3.1 节点查找与操作

常用查找方法:
fun findNodes(root: AccessibilityNodeInfo) {// 通过文本查找val byText = root.findAccessibilityNodeInfosByText("搜索")// 通过View ID查找(全限定ID)val byId = root.findAccessibilityNodeInfosByViewId("com.example.app:id/btnSubmit")// 通过类名查找val editTexts = mutableListOf<AccessibilityNodeInfo>()val queue: Queue<AccessibilityNodeInfo> = LinkedList()queue.add(root)while (queue.isNotEmpty()) {val current = queue.poll()if (current.className == "android.widget.EditText") {editTexts.add(current)}for (i in 0 until current.childCount) {current.getChild(i)?.let { queue.add(it) }}}
}
节点操作示例:
fun performActions(node: AccessibilityNodeInfo) {// 点击操作if (node.isClickable) {node.performAction(AccessibilityNodeInfo.ACTION_CLICK)}// 文本输入val arguments = Bundle().apply {putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, "Hello")}node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)// 焦点控制node.performAction(AccessibilityNodeInfo.ACTION_FOCUS)// 滚动操作node.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)
}

3.2 手势模拟

Android支持通过无障碍服务模拟复杂手势:

fun performGesture(service: AccessibilityService) {val path = Path().apply {moveTo(100f, 100f)  // 起点lineTo(500f, 100f)   // 移动到右侧lineTo(500f, 500f)   // 向下移动lineTo(100f, 500f)   // 向左移动close()              // 闭合路径}val gestureBuilder = GestureDescription.Builder().addStroke(GestureDescription.StrokeDescription(path, 0L,  // 开始时间1000L,  // 持续时间(毫秒)false  // 是否持续))service.dispatchGesture(gestureBuilder.build(), object : AccessibilityService.GestureResultCallback() {override fun onCompleted(gestureDescription: GestureDescription?) {Log.d("Gesture", "手势完成")}override onCancelled(gestureDescription: GestureDescription?) {Log.w("Gesture", "手势取消")}}, null)
}

3.3 全局事件监听

监听系统级事件:

override fun onAccessibilityEvent(event: AccessibilityEvent) {when (event.eventType) {AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED -> {val notificationText = event.text.joinToString()Log.d("Notification", "新通知: $notificationText")}AccessibilityEvent.TYPE_ANNOUNCEMENT -> {Log.d("Announcement", "系统公告: ${event.text}")}AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START -> {Log.d("Touch", "触摸探索开始")}}
}

第四部分:实战案例开发

4.1 自动填写表单

class FormFillerService : AccessibilityService() {private val formData = mapOf("username" to "testuser","password" to "secure123","email" to "test@example.com")override fun onAccessibilityEvent(event: AccessibilityEvent) {if (event.eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) returnval rootNode = rootInActiveWindow ?: returnformData.forEach { (fieldName, value) ->val nodes = rootNode.findAccessibilityNodeInfosByViewId("com.example.app:id/$fieldName")nodes.firstOrNull()?.let { field ->if (field.className == "android.widget.EditText") {val args = Bundle().apply {putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, value)}field.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args)}}}// 自动提交表单rootNode.findAccessibilityNodeInfosByViewId("com.example.app:id/submit").firstOrNull()?.performAction(AccessibilityNodeInfo.ACTION_CLICK)}
}

4.2 消息自动回复

class AutoReplyService : AccessibilityService() {private val replyMessages = listOf("我正在开会,稍后回复您","好的,收到","谢谢通知")override fun onAccessibilityEvent(event: AccessibilityEvent) {if (event.packageName != "com.whatsapp") returnwhen (event.eventType) {AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED -> {// 处理通知事件val messages = event.text.filter { it.contains("发来消息") }if (messages.isNotEmpty()) {replyToLatestMessage()}}AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED -> {// 处理界面文本变化if (isChatOpen()) {autoReplyInChat()}}}}private fun replyToLatestMessage() {// 实现打开聊天界面并回复的逻辑}private fun isChatOpen(): Boolean {// 检测当前是否在聊天界面}private fun autoReplyInChat() {val root = rootInActiveWindow ?: returnval messageNodes = root.findAccessibilityNodeInfosByViewId("com.whatsapp:id/message_text")// 获取最后一条消息val lastMessage = messageNodes.lastOrNull()?.text ?: return// 随机选择回复内容val randomReply = replyMessages.random()// 找到输入框并发送root.findAccessibilityNodeInfosByViewId("com.whatsapp:id/entry").firstOrNull()?.let { input ->val args = Bundle().apply {putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, randomReply)}input.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args)// 发送消息root.findAccessibilityNodeInfosByViewId("com.whatsapp:id/send").firstOrNull()?.performAction(AccessibilityNodeInfo.ACTION_CLICK)}}
}

4.3 游戏自动化辅助

class GameHelperService : AccessibilityService() {private var isRunning = falseprivate val handler = Handler(Looper.getMainLooper())private val clickRunnable = object : Runnable {override fun run() {performAutoClick()if (isRunning) {handler.postDelayed(this, 1000) // 每秒点击一次}}}override fun onServiceConnected() {val info = AccessibilityServiceInfo().apply {eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGEDfeedbackType = AccessibilityServiceInfo.FEEDBACK_GENERICflags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS}serviceInfo = info}override fun onAccessibilityEvent(event: AccessibilityEvent) {if (event.packageName != "com.game.package") returnwhen (event.eventType) {AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED -> {checkGameState()}}}private fun checkGameState() {val root = rootInActiveWindow ?: returnval battleNode = root.findAccessibilityNodeInfosByViewId("com.game.package:id/battle_indicator")if (battleNode.isNotEmpty()) {startAutoClicking()} else {stopAutoClicking()}}private fun startAutoClicking() {if (!isRunning) {isRunning = truehandler.post(clickRunnable)}}private fun stopAutoClicking() {isRunning = falsehandler.removeCallbacks(clickRunnable)}private fun performAutoClick() {val root = rootInActiveWindow ?: returnval attackBtn = root.findAccessibilityNodeInfosByViewId("com.game.package:id/attack_button").firstOrNull()attackBtn?.performAction(AccessibilityNodeInfo.ACTION_CLICK)// 随机位置点击,避免被检测为机器人if (Math.random() < 0.3) {val randomX = (100..500).random()val randomY = (200..800).random()dispatchGesture(createClickGesture(randomX, randomY), null, null)}}private fun createClickGesture(x: Int, y: Int): GestureDescription {val clickPath = Path().apply {moveTo(x.toFloat(), y.toFloat())}return GestureDescription.Builder().addStroke(GestureDescription.StrokeDescription(clickPath, 0, 50)).build()}
}

第五部分:调试与优化

5.1 调试技巧

ADB调试命令:
# 查看已启用的无障碍服务
adb shell settings get secure enabled_accessibility_services# 启用服务
adb shell settings put secure enabled_accessibility_services com.example.pkg/.MyAccessibilityService# 查看无障碍事件日志
adb shell logcat -s AccessibilityEvent
日志记录最佳实践:
fun logNodeInfo(node: AccessibilityNodeInfo) {val sb = StringBuilder().apply {append("View ID: ${node.viewIdResourceName}\n")append("Text: ${node.text}\n")append("Class: ${node.className}\n")append("Bounds: ${node.boundsInScreen}\n")append("Actions: ${node.actionList.joinToString()}\n")append("ChildCount: ${node.childCount}\n")}Log.d("NodeInfo", sb.toString())
}

5.2 性能优化

优化建议:
  1. 减少遍历深度:只查找必要的节点层级
  2. 及时回收节点:调用recycle()释放资源
  3. 事件过滤:只监听必要的事件类型
  4. 延迟处理:对频繁事件使用防抖
  5. 后台处理:将耗时操作移到工作线程
优化示例:
class OptimizedService : AccessibilityService() {private val eventQueue = LinkedBlockingQueue<AccessibilityEvent>()private val workerThread = HandlerThread("EventProcessor").apply { start() }private val workerHandler = Handler(workerThread.looper)private val eventProcessor = object : Runnable {override fun run() {while (true) {val event = eventQueue.take()processEvent(event)}}}override fun onCreate() {super.onCreate()workerHandler.post(eventProcessor)}override fun onAccessibilityEvent(event: AccessibilityEvent) {// 快速将事件加入队列,避免阻塞主线程eventQueue.put(event)}private fun processEvent(event: AccessibilityEvent) {// 实际处理逻辑}override fun onDestroy() {workerThread.quitSafely()super.onDestroy()}
}

第六部分:发布与安全

6.1 权限与隐私

必要权限声明:
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
隐私注意事项:
  1. 明确告知用户:在隐私政策中说明数据收集范围
  2. 最小权限原则:只请求必要的权限
  3. 敏感数据处理:避免收集密码等敏感信息
  4. 数据加密:对存储的日志和数据进行加密

6.2 发布流程

  1. 测试阶段

    • 在不同安卓版本上测试
    • 在各种品牌设备上测试(特别是国产ROM)
    • 测试电池消耗情况
  2. 应用商店要求

    • 明确说明是无障碍辅助工具
    • 提供详细的使用说明视频
    • 如果是自动化工具,需遵守各商店政策
  3. 持续更新

    • 定期适配新安卓版本
    • 针对流行应用的特殊适配
    • 根据用户反馈优化功能

第七部分:高级主题

7.1 与其他技术的结合

与Tasker集成:
// 接收Tasker的广播意图
private val taskerReceiver = object : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent) {if (intent.action == "net.dinglisch.android.tasker.ACTION_TRIGGER") {val task = intent.getStringExtra("task")when (task) {"start_automation" -> startAutomation()"stop_automation" -> stopAutomation()}}}
}override fun onCreate() {super.onCreate()registerReceiver(taskerReceiver, IntentFilter("net.dinglisch.android.tasker.ACTION_TRIGGER"))
}
使用机器学习:
// 使用ML Kit识别屏幕内容
fun detectTextFromScreen(bitmap: Bitmap): String {val recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)val image = InputImage.fromBitmap(bitmap, 0)return try {val result = recognizer.process(image).await()result.text} catch (e: Exception) {Log.e("ML", "识别失败", e)""}
}// 截图并处理
fun captureAndAnalyze() {val projection = MediaProjectionManager.createScreenCaptureIntent()// 需要先获取用户授权...val imageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2)imageReader.setOnImageAvailableListener({ reader ->val image = reader.acquireLatestImage()// 转换为Bitmap并传递给识别器val text = detectTextFromScreen(convertImageToBitmap(image))Log.d("ScreenText", "识别结果: $text")image.close()}, handler)
}

7.2 跨版本兼容性处理

版本差异处理表:
功能API 16-22API 23-28API 29+
节点信息获取基本支持增强支持受限
手势模拟不支持部分支持完全支持
隐私限制部分严格
后台服务允许限制严格限制
兼容性代码示例:
fun performActionCompat(node: AccessibilityNodeInfo, action: Int, args: Bundle? = null): Boolean {return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {node.performAction(action, args)} else {node.performAction(action)}
}fun getNodeTextCompat(node: AccessibilityNodeInfo): String {return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {node.text?.toString() ?: ""} else {node.text ?: ""}
}

在这里插入图片描述

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

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

相关文章

闲时处理技术---CAD C#二次开发

在CAD C#二次开发中&#xff0c;使用闲时处理技术可以提高程序的响应性能和资源利用率。以下是一般的实现步骤&#xff1a; 1. 了解CAD的事件机制 CAD提供了一些事件&#xff0c;如 Idle 事件&#xff0c;当CAD应用程序处于空闲状态时会触发该事件。你可以订阅这个事件来执行闲…

Git研究

以下命令在CentOS系统下执行 创建Git仓库 git init git-example 监控.git目录的变化情况&#xff1a; watch -n .5 tree .git 写入文件内容&#xff0c;并把文件添加到Stage暂存区 echo 1 > t.txtgit add 1.txt 观察结果如下&#xff1a;objects下多出了一个d00491fd…

野火鲁班猫(arrch64架构debian)从零实现用MobileFaceNet算法进行实时人脸识别(四)安装RKNN Toolkit Lite2

RKNN Toolkit Lite2 是瑞芯微专为RK系列芯片开发的NPU加速推理API。若不使用该工具&#xff0c;计算任务将仅依赖CPU处理&#xff0c;无法充分发挥芯片高达6TOPS的NPU算力优势。 按照官方文档先拉一下官方代码库&#xff0c;然后通过whl文件安装&#xff0c;因为我是python3.1…

Vue3集成Element Plus完整指南:从安装到主题定制下-实现后台管理系统框架搭建

本文将详细介绍如何使用 Vue 3 构建一个综合管理系统&#xff0c;包括路由配置、页面布局以及常用组件集成。 一、路由配置 首先&#xff0c;我们来看系统的路由配置&#xff0c;这是整个应用的基础架构&#xff1a; import {createRouter, createWebHistory} from vue-rout…

【Oracle】创建公共数据连接

需求描述 两个oracle数据库&#xff0c;想从B数据库创建视图脚本访问A数据库相关表的数据&#xff0c;该怎么访问呢&#xff1f; 解决方法 在Oracle数据库中&#xff0c;创建公共数据库链接&#xff08;Public Database Link&#xff09;可以允许数据库中的任何用户访问远程…

时序数据库IoTDB的分片与负载均衡策略深入解析

一、引言 随着数据库服务的业务负载增加&#xff0c;扩展服务资源成为必然需求。扩展方式主要分为纵向扩展和横向扩展。纵向扩展通过增加单台机器的能力&#xff08;如内存、硬盘、处理器&#xff09;来实现&#xff0c;但受限于单台机器的硬件能力。而横向扩展则通过增加更多…

计算机网络期末复习资料

我用夸克网盘分享了「计算机网络」&#xff0c; 链接&#xff1a;https://pan.quark.cn/s/8aac2f0b840e 计算机网络试题库 1单项选择题 1.1以下属于物理层的设备是 ( A) A. 中继器 B.以太网交换机 C. 桥 D. 网关 1.2在以太网中&#xff0c;是根据 (B) 地址来区分…

【IEEE 2025】低光增强KANT(使用KAN代替MLP)----论文详解与代码解析

【IEEE 2025】本文参考论文Enhancing Low-Light Images with Kolmogorov–Arnold Networks in Transformer Attention 虽然不是顶刊&#xff0c;但是有值得学习的地方 论文地址&#xff1a;arxiv 源码地址&#xff1a;github 文章目录 Part1 --- 论文精读Part2 --- 代码详解形状…

naivechain:简易区块链实现

naivechain&#xff1a;简易区块链实现 naivechain A naive and simple implementation of blockchains. 项目地址: https://gitcode.com/gh_mirrors/nai/naivechain 项目介绍 naivechain 是一个简单且易于理解的区块链实现项目。它使用 Go 语言编写&#xff0c;以极简…

Zabbix开源监控的全面详解!

一、zabbix的基本概述 zabbix&#xff0c;这款企业级监控软件&#xff0c;能全方位监控各类网络参数&#xff0c;确保企业服务架构的安全稳定运行。它提供了灵活多样的告警机制&#xff0c;帮助运维人员迅速发现并解决问题。此外&#xff0c;zabbix还具备分布式监控功能&#…

软考软件评测师——软件工程之开发模型与方法

目录 一、核心概念 二、主流模型详解 &#xff08;一&#xff09;经典瀑布模型 &#xff08;二&#xff09;螺旋演进模型 &#xff08;三&#xff09;增量交付模型 &#xff08;四&#xff09;原型验证模型 &#xff08;五&#xff09;敏捷开发实践 三、模型选择指南 四…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Blurry Loading (毛玻璃加载)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— Blurry Loading 组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ ✨ 组件目标 实现一个加载进度条&#xff0c;随着加载进度的…

WPF性能优化之延迟加载(解决页面卡顿问题)

文章目录 前言一. 基础知识回顾二. 问题分析三. 解决方案1. 新建一个名为DeferredContentHost的控件。2. 在DeferredContentHost控件中定义一个名为Content的object类型的依赖属性&#xff0c;用于承载要加载的子控件。3. 在DeferredContentHost控件中定义一个名为Skeleton的ob…

VLM-MPC:自动驾驶中模型预测控制器增强视觉-语言模型

《VLM-MPC: Model Predictive Controller Augmented Vision Language Model for Autonomous Driving》2024年8月发表&#xff0c;来自威斯康星大学的论文。 受视觉语言模型&#xff08;VLM&#xff09;的紧急推理能力及其提高自动驾驶系统可理解性的潜力的启发&#xff0c;本文…

推荐系统里真的存在“反馈循环”吗?

推荐系统里真的存在“反馈循环”吗&#xff1f; 许多人说&#xff0c;推荐算法不过是把用户早已存在的兴趣挖掘出来&#xff0c;你本来就爱听流行歌、买潮牌玩具&#xff0c;系统只是在合适的时间把它们端到你面前&#xff0c;再怎么迭代&#xff0c;算法也改变不了人的天性&a…

代码混淆技术的还原案例

案例一 eval 混淆 特征 &#xff1a; 反常的 eval 连接了一堆数据 练习网站 https://scrape.center/ spa9 这个案例 基本的还原方法 但是这个代码还是非常的模糊不好看 优化一下 &#xff1a; 当然还有更快捷的方法 &#xff1a; 好用的 js混淆还原的 web &#xf…

鸿蒙Flutter实战:22-混合开发详解-2-Har包模式引入

以 Har 包的方式加载到 HarmonyOS 工程 创建工作 创建一个根目录 mkdir ohos_flutter_module_demo这个目录用于存放 flutter 项目和鸿蒙项目。 创建 Flutter 模块 首先创建一个 Flutter 模块&#xff0c;我们选择与 ohos_app 项目同级目录 flutter create --templatemodu…

Go核心特性与并发编程

Go核心特性与并发编程 1. 结构体与方法&#xff08;扩展&#xff09; 高级结构体特性 // 嵌套结构体与匿名字段 type Employee struct {Person // 匿名嵌入Department stringsalary float64 // 私有字段 }// 构造函数模式 func NewPerson(name string, age int) *Pe…

Java 函数式接口(Functional Interface)

一、理论说明 1. 函数式接口的定义 Java 函数式接口是一种特殊的接口&#xff0c;它只包含一个抽象方法&#xff08;Single Abstract Method, SAM&#xff09;&#xff0c;但可以包含多个默认方法或静态方法。函数式接口是 Java 8 引入 Lambda 表达式的基础&#xff0c;通过函…

【python代码】一些小实验

目录 1. 测试Resnet50 ONNX模型的推理速度 1. 测试Resnet50 ONNX模型的推理速度 ############################### # 导出resnet50 模型 # 测试onnx模型推理 cpu 和 GPU 的对比 ###############################import time import numpy as np import onnxruntime as ort im…