Java实现安卓手机模拟操作
文章目录
- 第一部分:安卓模拟操作基础
- 1.1 安卓输入系统概述
- 1.1.1 输入事件传递机制
- 1.1.2 输入事件类型
- 1.2 模拟操作的核心类
- 1.2.1 Instrumentation类
- 1.2.2 KeyEvent类
- 1.2.3 MotionEvent类
- 1.3 权限要求
- 1.3.1 普通权限
- 1.3.2 特殊权限
- 第二部分:基础模拟操作实现
- 2.1 按键模拟
- 2.1.1 单个按键操作
- 2.1.2 组合按键操作
- 2.2 触摸模拟
- 2.2.1 单点触摸
- 2.2.2 滑动操作
- 2.3 文本输入模拟
- 2.3.1 单个字符输入
- 2.3.2 字符串输入
- 第三部分:高级模拟操作技术
- 3.1 多指触控模拟
- 3.1.1 MotionEvent多指支持
- 3.1.2 双指缩放实现
- 3.2 复杂手势模拟
- 3.2.1 画圆手势
- 3.3 无障碍服务实现模拟操作
- 3.3.1 无障碍服务配置
- 3.3.2 手势分发实现
- 第四部分:实用案例与应用场景
- 4.1 自动化测试应用
- 4.1.1 测试用例录制与回放
- 4.2 游戏辅助工具
- 4.2.1 连点器实现
- 4.3 远程控制实现
- 4.3.1 通过Socket接收指令
- 第五部分:优化与进阶
- 5.1 性能优化
- 5.1.1 事件批量发送
- 5.1.2 事件时间戳优化
- 5.2 兼容性处理
- 5.2.1 不同安卓版本适配
- 5.2.2 不同设备分辨率适配
- 5.3 安全与权限管理
- 5.3.1 动态权限申请
- 结语

第一部分:安卓模拟操作基础
1.1 安卓输入系统概述
1.1.1 输入事件传递机制
安卓系统中的输入事件遵循以下传递路径:
- 硬件层:触摸屏、物理按键等硬件设备产生原始输入信号
- 内核层:Linux内核通过设备驱动接收原始输入事件
- 系统服务层:InputManagerService处理输入事件
- 应用层:事件通过View层级传递到具体应用
1.1.2 输入事件类型
- 按键事件(KeyEvent):物理按键、键盘输入
- 触摸事件(MotionEvent):触摸屏交互
- 轨迹球事件(TrackballEvent):现已较少使用
- 游戏控制器事件:手柄等外设输入
1.2 模拟操作的核心类
1.2.1 Instrumentation类
public class Instrumentation {// 发送按键事件public void sendKeySync(KeyEvent event) { ... }// 发送触摸事件public void sendPointerSync(MotionEvent event) { ... }// 发送字符串public void sendStringSync(String text) { ... }
}
1.2.2 KeyEvent类
public class KeyEvent extends InputEvent implements Parcelable {// 常用按键代码public static final int KEYCODE_HOME = 3;public static final int KEYCODE_BACK = 4;public static final int KEYCODE_DPAD_CENTER = 23;public static final int KEYCODE_ENTER = 66;// 构造方法public KeyEvent(long downTime, long eventTime, int action, int code, int repeat) { ... }
}
1.2.3 MotionEvent类
public abstract class MotionEvent extends InputEvent implements Parcelable {// 动作类型public static final int ACTION_DOWN = 0;public static final int ACTION_UP = 1;public static final int ACTION_MOVE = 2;// 获取坐标public final float getX() { ... }public final float getY() { ... }// 创建事件public static MotionEvent obtain(long downTime, long eventTime,int action, float x, float y, int metaState) { ... }
}
1.3 权限要求
1.3.1 普通权限
<uses-permission android:name="android.permission.INTERNET" />
1.3.2 特殊权限
<!-- 注入事件权限 -->
<uses-permission android:name="android.permission.INJECT_EVENTS" tools:ignore="ProtectedPermissions" />
注意:INJECT_EVENTS是系统权限,普通应用无法获取,需要系统签名或root权限。
第二部分:基础模拟操作实现
2.1 按键模拟
2.1.1 单个按键操作
// 模拟返回键
public void simulateBackKey() {long downTime = SystemClock.uptimeMillis();long eventTime = SystemClock.uptimeMillis();KeyEvent downEvent = new KeyEvent(downTime, eventTime, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK, 0);KeyEvent upEvent = new KeyEvent(downTime, eventTime, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK, 0);try {Instrumentation inst = new Instrumentation();inst.sendKeySync(downEvent);inst.sendKeySync(upEvent);} catch (Exception e) {e.printStackTrace();}
}
2.1.2 组合按键操作
// 模拟Home键长按(打开最近任务)
public void simulateLongPressHome() {long downTime = SystemClock.uptimeMillis();long eventTime = SystemClock.uptimeMillis() + 1000; // 长按1秒KeyEvent downEvent = new KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HOME, 0);KeyEvent upEvent = new KeyEvent(downTime, eventTime, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HOME, 0);try {Instrumentation inst = new Instrumentation();inst.sendKeySync(downEvent);Thread.sleep(1000); // 保持按下状态inst.sendKeySync(upEvent);} catch (Exception e) {e.printStackTrace();}
}
2.2 触摸模拟
2.2.1 单点触摸
// 模拟在(x,y)位置的点击
public void simulateTap(int x, int y) {long downTime = SystemClock.uptimeMillis();long eventTime = SystemClock.uptimeMillis();// 按下动作MotionEvent downEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);// 抬起动作MotionEvent upEvent = MotionEvent.obtain(downTime, eventTime + 100, MotionEvent.ACTION_UP, x, y, 0);try {Instrumentation inst = new Instrumentation();inst.sendPointerSync(downEvent);inst.sendPointerSync(upEvent);} catch (Exception e) {e.printStackTrace();} finally {downEvent.recycle();upEvent.recycle();}
}
2.2.2 滑动操作
// 模拟从(startX,startY)滑动到(endX,endY)
public void simulateSwipe(int startX, int startY, int endX, int endY) {long downTime = SystemClock.uptimeMillis();// 按下动作MotionEvent downEvent = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, startX, startY, 0);// 移动动作MotionEvent moveEvent = MotionEvent.obtain(downTime, downTime + 50, MotionEvent.ACTION_MOVE, startX + (endX-startX)/2, startY + (endY-startY)/2, 0);// 抬起动作MotionEvent upEvent = MotionEvent.obtain(downTime, downTime + 100, MotionEvent.ACTION_UP, endX, endY, 0);try {Instrumentation inst = new Instrumentation();inst.sendPointerSync(downEvent);inst.sendPointerSync(moveEvent);inst.sendPointerSync(upEvent);} catch (Exception e) {e.printStackTrace();} finally {downEvent.recycle();moveEvent.recycle();upEvent.recycle();}
}
2.3 文本输入模拟
2.3.1 单个字符输入
// 模拟输入单个字符
public void simulateCharInput(char c) {try {Instrumentation inst = new Instrumentation();inst.sendCharacterSync(KeyEvent.KEYCODE_A); // 替换为对应字符的键码} catch (Exception e) {e.printStackTrace();}
}
2.3.2 字符串输入
// 模拟输入字符串
public void simulateTextInput(String text) {try {Instrumentation inst = new Instrumentation();inst.sendStringSync(text);} catch (Exception e) {e.printStackTrace();}
}
第三部分:高级模拟操作技术
3.1 多指触控模拟
3.1.1 MotionEvent多指支持
安卓通过指针索引(pointer index)和指针ID(pointer id)支持多点触控:
- 每个触摸点有唯一的pointer id
- pointer index是当前活动触摸点的索引
3.1.2 双指缩放实现
// 模拟双指缩放手势
public void simulatePinchZoom(int centerX, int centerY, float scaleFactor) {long downTime = SystemClock.uptimeMillis();int startDistance = 100; // 初始两指距离int endDistance = (int)(startDistance * scaleFactor);// 第一指按下MotionEvent downEvent1 = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_DOWN,centerX - startDistance/2,centerY, 0);// 第二指按下MotionEvent downEvent2 = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_POINTER_DOWN |(1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT),centerX + startDistance/2,centerY, 0);// 移动过程List<MotionEvent> moveEvents = new ArrayList<>();for (int i = 1; i <= 5; i++) {float fraction = i / 5f;int currentDistance = (int)(startDistance + (endDistance - startDistance) * fraction);long eventTime = downTime + i * 50;MotionEvent moveEvent = MotionEvent.obtain(downTime, eventTime,MotionEvent.ACTION_MOVE,centerX - currentDistance/2,centerY, 0);moveEvent.setLocation(centerX + currentDistance/2, centerY);moveEvents.add(moveEvent);}// 抬起第二指MotionEvent upEvent2 = MotionEvent.obtain(downTime, downTime + 300,MotionEvent.ACTION_POINTER_UP |(1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT),centerX + endDistance/2,centerY, 0);// 抬起第一指MotionEvent upEvent1 = MotionEvent.obtain(downTime, downTime + 350,MotionEvent.ACTION_UP,centerX - endDistance/2,centerY, 0);try {Instrumentation inst = new Instrumentation();inst.sendPointerSync(downEvent1);inst.sendPointerSync(downEvent2);for (MotionEvent event : moveEvents) {inst.sendPointerSync(event);event.recycle();}inst.sendPointerSync(upEvent2);inst.sendPointerSync(upEvent1);} catch (Exception e) {e.printStackTrace();} finally {downEvent1.recycle();downEvent2.recycle();upEvent1.recycle();upEvent2.recycle();}
}
3.2 复杂手势模拟
3.2.1 画圆手势
// 模拟画圆手势
public void simulateCircleGesture(int centerX, int centerY, int radius) {long downTime = SystemClock.uptimeMillis();int steps = 36; // 圆的细分段数double angleStep = 2 * Math.PI / steps;// 按下动作MotionEvent downEvent = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_DOWN,centerX + radius,centerY, 0);// 移动动作序列List<MotionEvent> moveEvents = new ArrayList<>();for (int i = 1; i <= steps; i++) {double angle = angleStep * i;int x = (int)(centerX + radius * Math.cos(angle));int y = (int)(centerY + radius * Math.sin(angle));long eventTime = downTime + i * 20;MotionEvent moveEvent = MotionEvent.obtain(downTime, eventTime,MotionEvent.ACTION_MOVE,x, y, 0);moveEvents.add(moveEvent);}// 抬起动作MotionEvent upEvent = MotionEvent.obtain(downTime, downTime + steps * 20,MotionEvent.ACTION_UP,centerX + radius,centerY, 0);try {Instrumentation inst = new Instrumentation();inst.sendPointerSync(downEvent);for (MotionEvent event : moveEvents) {inst.sendPointerSync(event);event.recycle();}inst.sendPointerSync(upEvent);} catch (Exception e) {e.printStackTrace();} finally {downEvent.recycle();upEvent.recycle();}
}
3.3 无障碍服务实现模拟操作
3.3.1 无障碍服务配置
AndroidManifest.xml配置:
<service android:name=".MyAccessibilityService"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService" /></intent-filter><meta-data android:name="android.accessibilityservice"android:resource="@xml/accessibility_service_config" />
</service>
res/xml/accessibility_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="flagRequestFilterKeyEvents"android:canRequestFilterKeyEvents="true"android:canPerformGestures="true"android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity" />
3.3.2 手势分发实现
public class MyAccessibilityService extends AccessibilityService {@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {// 处理无障碍事件}@Overridepublic void onInterrupt() {// 服务中断处理}// 分发手势public boolean dispatchGesture(int x, int y) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {Path path = new Path();path.moveTo(x, y);GestureDescription.Builder builder = new GestureDescription.Builder();builder.addStroke(new GestureDescription.StrokeDescription(path, 0, 50));return dispatchGesture(builder.build(), null, null);}return false;}// 更复杂的多指手势public boolean dispatchMultiFingerGesture(List<Point> points) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {GestureDescription.Builder builder = new GestureDescription.Builder();for (Point point : points) {Path path = new Path();path.moveTo(point.x, point.y);builder.addStroke(new GestureDescription.StrokeDescription(path, 0, 100));}return dispatchGesture(builder.build(), null, null);}return false;}
}
第四部分:实用案例与应用场景
4.1 自动化测试应用
4.1.1 测试用例录制与回放
public class TestRecorder {private List<InputEvent> recordedEvents = new ArrayList<>();private boolean isRecording = false;public void startRecording() {recordedEvents.clear();isRecording = true;}public void stopRecording() {isRecording = false;}public void recordEvent(InputEvent event) {if (isRecording) {recordedEvents.add(event);}}public void replayEvents() {try {Instrumentation inst = new Instrumentation();for (InputEvent event : recordedEvents) {if (event instanceof KeyEvent) {inst.sendKeySync((KeyEvent)event);} else if (event instanceof MotionEvent) {inst.sendPointerSync((MotionEvent)event);}Thread.sleep(50); // 事件间延迟}} catch (Exception e) {e.printStackTrace();}}
}
4.2 游戏辅助工具
4.2.1 连点器实现
public class AutoClicker {private boolean isClicking = false;private int clickInterval = 500; // 毫秒private int targetX, targetY;private Thread clickingThread;public void startClicking(int x, int y) {targetX = x;targetY = y;isClicking = true;clickingThread = new Thread(() -> {while (isClicking) {simulateTap(targetX, targetY);try {Thread.sleep(clickInterval);} catch (InterruptedException e) {break;}}});clickingThread.start();}public void stopClicking() {isClicking = false;if (clickingThread != null) {clickingThread.interrupt();}}public void setClickInterval(int interval) {clickInterval = interval;}
}
4.3 远程控制实现
4.3.1 通过Socket接收指令
public class RemoteControlService extends Service {private static final int PORT = 12345;private ServerSocket serverSocket;private boolean isRunning = true;@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(() -> {try {serverSocket = new ServerSocket(PORT);while (isRunning) {Socket clientSocket = serverSocket.accept();handleClient(clientSocket);}} catch (IOException e) {e.printStackTrace();}}).start();return START_STICKY;}private void handleClient(Socket clientSocket) {try {BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));String inputLine;while ((inputLine = in.readLine()) != null) {processCommand(inputLine);}} catch (IOException e) {e.printStackTrace();}}private void processCommand(String command) {String[] parts = command.split(",");switch (parts[0]) {case "TAP":int x = Integer.parseInt(parts[1]);int y = Integer.parseInt(parts[2]);simulateTap(x, y);break;case "SWIPE":int startX = Integer.parseInt(parts[1]);int startY = Integer.parseInt(parts[2]);int endX = Integer.parseInt(parts[3]);int endY = Integer.parseInt(parts[4]);simulateSwipe(startX, startY, endX, endY);break;case "KEY":int keyCode = Integer.parseInt(parts[1]);simulateKey(keyCode);break;}}@Overridepublic void onDestroy() {isRunning = false;try {if (serverSocket != null) {serverSocket.close();}} catch (IOException e) {e.printStackTrace();}super.onDestroy();}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}
}
第五部分:优化与进阶
5.1 性能优化
5.1.1 事件批量发送
public void sendEventsBulk(List<InputEvent> events) {try {Instrumentation inst = new Instrumentation();// 开始批量Method beginBatchMethod = Instrumentation.class.getDeclaredMethod("beginBatch");beginBatchMethod.setAccessible(true);beginBatchMethod.invoke(inst);// 发送事件for (InputEvent event : events) {if (event instanceof KeyEvent) {inst.sendKeySync((KeyEvent)event);} else if (event instanceof MotionEvent) {inst.sendPointerSync((MotionEvent)event);}}// 结束批量Method endBatchMethod = Instrumentation.class.getDeclaredMethod("endBatch");endBatchMethod.setAccessible(true);endBatchMethod.invoke(inst);} catch (Exception e) {e.printStackTrace();}
}
5.1.2 事件时间戳优化
// 更精确的事件时间戳控制
public void simulatePreciseTap(int x, int y, long duration) {long downTime = SystemClock.uptimeMillis();long upTime = downTime + duration;MotionEvent downEvent = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_DOWN,x, y, 0);MotionEvent upEvent = MotionEvent.obtain(downTime, upTime,MotionEvent.ACTION_UP,x, y, 0);try {Instrumentation inst = new Instrumentation();inst.sendPointerSync(downEvent);Thread.sleep(duration);inst.sendPointerSync(upEvent);} catch (Exception e) {e.printStackTrace();} finally {downEvent.recycle();upEvent.recycle();}
}
5.2 兼容性处理
5.2.1 不同安卓版本适配
public void simulateClickCompat(int x, int y) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {// 使用无障碍服务APIif (myAccessibilityService != null) {myAccessibilityService.dispatchGesture(x, y);}} else {// 使用InstrumentationsimulateTap(x, y);}
}
5.2.2 不同设备分辨率适配
public Point convertCoordinates(int x, int y) {DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();int screenWidth = metrics.widthPixels;int screenHeight = metrics.heightPixels;// 假设原始坐标是基于1080x1920设计的float scaleX = screenWidth / 1080f;float scaleY = screenHeight / 1920f;return new Point((int)(x * scaleX), (int)(y * scaleY));
}
5.3 安全与权限管理
5.3.1 动态权限申请
private static final int REQUEST_INJECT_PERMISSION = 1;public void checkAndRequestPermissions(Activity activity) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (!Settings.canDrawOverlays(activity)) {Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + activity.getPackageName()));activity.startActivityForResult(intent, REQUEST_INJECT_PERMISSION);}}
}@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == REQUEST_INJECT_PERMISSION) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (Settings.canDrawOverlays(this)) {// 权限已授予} else {// 权限被拒绝}}}
}
结语
本文详细介绍了使用Java实现安卓手机模拟操作的各种技术和方法,从基础的单点触摸、按键模拟到复杂的多指手势、无障碍服务实现,涵盖了开发过程中可能遇到的多种场景和需求。
需要注意的是,模拟用户操作涉及到用户隐私和设备安全,在实际开发中应当:
- 明确告知用户应用将执行的操作
- 获取用户的明确授权
- 仅在必要的情况下使用这些技术
- 遵循Google Play和其他应用商店的相关政策
相关文章:
Java实现安卓手机模拟操作
文章目录 第一部分:安卓模拟操作基础1.1 安卓输入系统概述1.1.1 输入事件传递机制1.1.2 输入事件类型 1.2 模拟操作的核心类1.2.1 Instrumentation类1.2.2 KeyEvent类1.2.3 MotionEvent类 1.3 权限要求1.3.1 普通权限1.3.2 特殊权限 第二部分:基础模拟操…...
一文讲清楚PLC、运动控制卡、运动控制器
随着工业技术的发展,工业机器人应用越来越广泛,PLC也不再是简单的可编程逻辑控制器,各个品牌厂家都推出了自己的运动控制型PLC,来实现一些运动控制功能,与此同时,运动控制卡及运动控制器也在如火如荼地发展…...
蓝桥杯备战
#include<bits/stdc.h> using namespace std; int main(){ios::sync_with_stdio(false);cin.tie(0);return 0; } 输入输出加速 ios::sync_with_stdio(false) 作用: 禁用 C 和 C 标准流的同步,使 cin/cout 速度接近 scanf/printf。 适用性ÿ…...
python保留关键字详解
一、什么是保留关键字? 保留关键字是Python语言中具有特殊含义和功能的词汇,这些词汇构成了Python的语法基础。它们不可被重新定义或用作变量名、函数名等标识符,在代码中承担着控制程序逻辑、定义数据结构等重要职责。 二、查看保留关键字…...
NLP中的“触发器”形式
在自然语言处理(NLP)中,触发器的设计更加依赖于文本特征,而非视觉特征。以下是NLP中常见的触发器类型及其实现方式: 1. 特定词汇或短语 定义:在文本中插入特定的单词、短语或符号。示例: 罕见…...
uView修改样式(持续更新)
场景 通过样式穿透修改uView2.0组件样式,用于app 注意版本不一样方法可能不同 实现 通用 .uni-body{line-height: 0; }u-input ::v-deep .u-input{height: 20.51rpx !important;padding: 0 6.59rpx !important; } ::v-deep .uni-input-input{height:50%;font-s…...
使用 Datadog 和 Slack Alerts 监控 AWS EC2
监控是大多数 IT 专业人员的关键职责之一。如果您最近正在寻找新工作,您可能已经注意到“监控”一词几乎出现在许多组织发布的每份职位描述中。 您可以找到各种监控工具,它们提供一些卓越的功能来简化您的工程工作。然而,Datadog 是大多数组…...
grafana/loki 部署搜集 k8s 集群日志
grafana/loki 和 grafana/loki-stack 的区别 Grafana 提供了多个 Helm Chart 用于在 Kubernetes 集群中部署 Loki 及相关组件,其中主要包括 grafana/loki 和 grafana/loki-stack。它们的主要区别如下: 1.grafana/loki Helm Chart: 专注于 Loki 部署: 该 Chart 专门…...
【ESP32S3】GATT Server service table传送数据到调试助手
前言 在初步学习esp32蓝牙的过程中,借鉴了官方的GATT Server Service Table Example,可以在readme中看到,此demo是采用低功耗蓝牙的通用属性服务器来创建订阅服务和特性。如果你接触过MQTT,你会发现GATT Server这一特性和MQTT的订…...
《Vue Router实战教程》5.嵌套路由
欢迎观看《Vue Router 实战(第4版)》视频课程 嵌套路由 一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如: 通过 Vue Router,你可以使用嵌套路由配置…...
小白学习java第12天:IO流之转换流
我们可能会遇到这样情况就是:你在读取那个文件编码类型是GBK,而是进行读取的的时候使用的UTF-8,这就会导致乱码,因为你没办法保证别人是用什么类型进行编写的,因此我们就需要转换流进行处理这种情况! 下面…...
BERT - 直接调用transformers.BertModel, BertTokenizerAPI不进行任何微调
本节代码将使用 transformers 库加载预训练的BERT模型和分词器(Tokenizer),并处理文本输入。 1. 加载预训练模型和分词器 from transformers import BertTokenizer, BertModelmodel_path "/Users/azen/Desktop/llm/models/bert-base-…...
如何在 Spring Boot 项目中使用 MyBatis 进行批量操作以提升性能?
MyBatis 提供了 ExecutorType.BATCH 类型,允许将多个 SQL 语句进行组合,最后统一执行,从而减少数据库的访问频率,提升性能。 以下是如何在 Spring Boot 项目中使用 MyBatis 进行批量操作的关键点: 1. 配置 MyBatis 使…...
传统门店VS智慧门店:电能物联网平台在连锁行业的节能应用
前言 随着连锁零售行业门店的规模化发展,能源消耗成为企业成本管控与可持续发展的重要课题。在当今快节奏的商业环境中,连锁门店的管理和运营变得越来越具有挑战性。能源数据是连锁门店的管理中重要组成部分,为了提高门店的能源利用效率和管…...
[ctfshow web入门] RCE 或(or)、异或(xor)、非(not)绕过
代码 这是一个python语言的,使用或(or)、异或(xor)、非(not)防火墙 这将根据命令提供加密后的指令,用法 rce_xor(list_cmd)、rce_or(list_cmd)、rce_not(list_cmd) 用来生成加密后的指令,这个指令是类如下面这样的,这些指令可以用…...
C++ 虚函数:深入理解多态的核心机制
C 虚函数:深入理解多态的核心机制 在 C 里,虚函数是实现 多态(Polymorphism) 的关键机制之一。透彻理解虚函数的概念、实现方式以及使用场景,对编写高效且可扩展的 C 代码起着至关重要的作用。本文会详细介绍 C 虚函数…...
速盾:高防CDN节点对收录有影响吗?
引言 搜索引擎收录是网站运营中至关重要的环节,它直接影响着网站的曝光度和流量。近年来,随着网络安全威胁的增加,许多企业开始采用高防CDN(内容分发网络)来保护其网站免受DDoS攻击和其他形式的网络攻击。然而&#x…...
按规则批量修改文件扩展名、删除扩展名或添加扩展名
文件的扩展名是多种多样的,有些不同文件的扩展名之间相互是可以直接转换的。我们工作当中最常见的就是 doc 与 docx、xls 与 xlsx、jpg 与 jpeg、html 与 htm 等等,这些格式在大部分场景下都是可以相互转换 能直接兼容的。我们今天要介绍的就是如何按照一…...
在Java项目中,引入【全局异常处理器】
目录 一.为什么引入全局异常处理器(目前项目碰到了什么问题)? 1.问题描述 2.与预期的差别 3.解决方案 二.解决上述问题 1.定义【业务异常类】 2.在serviceImpl层,手动抛出【违反唯一性约束】这个异常 3.定义【全局异常处理…...
计算机网络-TCP协议详解
TCP协议详解 2. TCP协议详解2.1 TCP协议概述2.1.1 TCP的历史背景2.1.2 TCP的设计目标2.1.3 TCP的基本特性2.1.4 TCP与其他传输协议的比较2.1.5 TCP的应用场景 2.2 TCP头部结构2.2.1 TCP头部格式2.2.2 TCP头部字段详解源端口号和目的端口号(各16位)序列号…...
[蓝桥杯 2023 省 A] 平方差
P9231 [蓝桥杯 2023 省 A] 平方差 题目描述 给定 L , R L,R L,R,问 L ≤ x ≤ R L \leq x \leq R L≤x≤R 中有多少个数 x x x 满足存在整数 y , z y,z y,z 使得 x y 2 − z 2 xy^2-z^2 xy2−z2。 输入格式 输入一行包含两个整数 L , R L,R L,Rÿ…...
隐私通信新时代:磐石云AXB平台如何重塑企业安全防线?
在数据泄露频发的当下,企业如何守护用户隐私?磐石云AXB隐私号平台以四大技术革新,构建通信安全堡垒。 技术突破: 动态号码隔离,隐私0泄露 AXB模式下,A与B的真实号码全程隐藏,仅通过虚拟号X中转…...
什么是八步工作法?
八步工作法,顾名思义,就是把一项工作拆分成八个步骤来完成。它的核心目的是让工作变得更有条理,更高效,避免忙而无序,做到事事有着落,件件有结果。这个方法在很多企业和单位中都有应用,尤其适合…...
日事清团队协作软件:智能制定计划,实时追踪任务进展,文件共享无缝协作,知识库一键沉淀成果
我们总是有微细目标,日事清可以帮助团队轻松共同制定计划、同步工作进展、共享工作资料、沉淀工作成果。 日事清具体如何帮助团队?你可以先了解以下这些基本功能模块。 从【计划】开始 在日事清中,【计划】是协同办公的开始,邀请…...
全球变暖(蓝桥杯 2018 年第九届省赛)
题目描述 你有一张某海域 NN 像素的照片,. 表示海洋、 # 表示陆地,如下所示: ....... .##.... .##.... ....##. ..####. ...###. .......其中 "上下左右" 四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座岛屿。 由…...
国际物流怎么找客户?选择适合自己的企业拓客平台
在国际物流行业,获客一直是企业发展的核心难题。无论是跨境电商、传统外贸,还是国际货代,找到精准的客户资源并高效转化,是决定企业能否抢占市场蓝海的关键。今天,我们就来聊聊如何选择一个真正适合的国际物流拓客平台…...
驱动-内核空间和用户空间数据交换
内核空间与用户控件数据交换 前面了解的字符设备中对 file_operations 结构体的进行了填充, 该 结构体的每一个成员都对应着一个系统调用, 例如 read、 write 等, 在字符设备相关的文章中有实验过对 调用函数进行了标志打印, 并没…...
智膳优选 | AI赋能的智慧食堂管理专家 —— 基于飞书多维表格和扣子(Coze)的智能解决方案
智膳优选 | AI赋能的智慧食堂管理专家 基于飞书多维表格和扣子(Coze)的智能解决方案 数据驱动餐饮管理,让每一餐都是营养与经济的完美平衡! “智膳优选”通过整合飞书与Coze,将数据智能引入校园餐饮管理࿰…...
FCOS目标检测
一、模型框架 FCOS采用的网络架构和RetinaNet一样,都是采用FPN架构,如图2所示,每个特征图后是检测器,检测器包含3个分支:classification,regression和center-ness。 对于特征图Fi∈RHWC,其相对…...
Linux中动态加载两个同名so(dlopen动态链接库)
// 当前路径下 ./test1.c int Func1(int a, int b) { return ab; } //编译生成so gcc -fPIC -shared -o libTest.so test1.c // 当前路径的test2文件夹中 ./test2/test2.c int Func1(int a, int b) { return a-b; } //编译生成同名so gcc -fPIC -shared -o …...
直播电商革命:东南亚市场的“人货场”重构方程式
一、人设经济3.0:从流量收割到情感基建 东南亚直播战场正经历从"叫卖式促销"到"沉浸式信任"的质变,新加坡市场成为最佳观察样本: 数据印证趋势:Shopee直播用户日均停留28分钟,超短视频平台&#…...
【CF】Day30——Codeforces Round 824 (Div. 2) C + Codeforces Round 825 (Div. 2) BC1
C. Phase Shift 题目: 思路: 好题,值得多看 这题我们看题目就能想到一个很显然的做法,那就是贪心地把每一个字母换成最前面的没使用过的字母 但是这样直接写是有问题的,因为题目说了最后要让所有的字母成一个换&…...
STM32 模块化开发指南 · 第 2 篇 如何编写高复用的外设驱动模块(以 UART 为例)
本文是《STM32 模块化开发实战指南》的第 2 篇,聚焦于“串口驱动模块的设计与封装”。我们将从一个最基础的裸机 UART 初始化开始,逐步实现:中断支持、环形缓冲收发、模块接口抽象与测试策略,构建一个可移植、可扩展、可复用的 UART 驱动模块。 一、模块化 UART 的设计目标…...
SSRF打靶总结
文章目录 一. PortSwigger1、本地服务器的基本SSRF2、基本的目标不是漏洞机3、Referer标头的外带SSRF4、简单黑名单的SSRF黑名单绕过思路: 5、重定向的SSRF6. 简单的白名单SSRF白名单绕过思路: 二、BWAPP1. SSRF 文件包含漏洞 | 内网探测2. XXE -> S…...
第五章:5.1 ESP32物联网应用 - MQTT协议深度教程
一、MQTT协议简介 1.1 发布/订阅模式 MQTT(Message Queuing Telemetry Transport)是一种轻量级物联网通信协议,采用发布/订阅模式: 发布者(Publisher):发送消息到指定主题(如&…...
c++知识点
高级模板技术45: 模板元编程:这是一种在编译期进行计算和代码生成的技术。通过模板的递归展开、特化等操作,可以实现一些复杂的功能,例如编译期的计算、类型安全的容器等。例如,使用模板元编程可以实现一个编译期计算斐…...
【ChCore Lab 01】Bomb Lab 拆炸弹实验(ARM汇编逆向工程)
文章目录 1. 前言2. 实验代码版本问题3. 关于使用问题4. 宏观分析5. read_line 函数介绍6. phase_0 函数6.1. read_int 函数6.2. 回到 phase_0 函数继续分析6.3. 验证结果 7. phase_1 函数7.2. 验证结果 8. phase_2 函数8.1. read_8_numbers 函数8.2. 回到 phase_2 函数继续分析…...
QStackedWidget讲解
简介 QStackedWidget 类在一次仅显示1个窗口的地方提供一个窗口栈。 头文件:#include qmake:QT widgets 基类:QFrame 属性 count : const int currentIndex : int 公有槽函数 void setCurrentIndex(int index) void setCurrentWidget(QWidget *widget)信号 void current…...
宝马集团加速 ERP 转型和上云之旅
宝马集团(BMW Group)作为全球领先的豪华汽车和摩托车制造商,致力于构建更加智能、绿色、人性化的出行体验。为了支持其全球化、数字化业务战略,宝马集团正在进行大规模的 IT 体系升级和 ERP 云转型。该项目以“RISE with SAP S/4H…...
AutoEval:现实世界中通才机器人操作策略的自主评估
25年3月来自 UC Berkeley 和 Nvidia 的论文“AutoEval: Autonomous Evaluation of Generalist Robot Manipulation Policies in the Real World”。 可规模化且可复现的策略评估一直是机器人学习领域长期存在的挑战。评估对于评估进展和构建更优策略至关重要,但在现…...
ARM Cortex M内存屏障指令__dsb( )和__isb( )
ARM Cortex-M 系列处理器中的 __dsb() 和 __isb() 是内存屏障指令,用于确保内存操作的顺序性和可见性,尤其在涉及外设、多核/多线程、自修改代码或关键系统配置时至关重要。 一,详细说明和典型应用场景 1. __dsb()(Data Synchron…...
deepseek热度已过?
DeepSeek的热度并没有消退,以下是具体表现: 用户使用量和下载量方面 • 日活跃用户量增长:DeepSeek已经成为目前最快突破3000万日活跃用户量的应用程序。 • 应用商店下载量:1月26日,DeepSeek最新推出的AI聊天机器人…...
使用 Datadog 和 Slack Alerts 监控 minikube
为什么要监控 minikube 集群?这是一个不错的练习,可以让你了解 DataDog 的设置过程并探索 K8s 指标产品。 本文将分享我的以下经验: 设置最新的 minikube部署示例应用程序创建 DataDog(试用)帐户使用 Helm 安装 Data…...
深入 Redis 持久化:从原理到企业级应用的全景图
🧠 什么是 Redis 持久化?为什么需要? Redis 是内存型数据库,默认所有数据都存在内存中,一旦断电,数据就会消失。为了避免重要数据丢失,Redis 提供了持久化机制,用于将内存中的数据保…...
NET模式下如何配置虚拟机的IP地址为静态的
1.查看网关: 2.找到虚拟机的网络配置文件 cd ./etc/sysconfig/network-scripts/ vim ifcfg-ens33 3.修改配置 BROWSER_ONLY"no" IPADDR192.168.122.120 NETMASK255.255.255.0 GATEWAY192.168.122.2 DNS18.8.8.8 4.重启网路服务 sudo systemctl rest…...
VMWare Workstation Pro17.6最新版虚拟机详细安装教程(附安装包教程)
目录 前言 一、VMWare虚拟机下载 二、VMWare虚拟机安装 三、运行虚拟机 前言 VMware 是全球领先的虚拟化技术与云计算解决方案提供商,通过软件模拟计算机硬件环境,允许用户在一台物理设备上运行多个独立的虚拟操作系统或应用。其核心技术可提升硬件…...
磐石云智能语音客服系统——技术革新引领服务新体验
在人工智能技术飞速发展的今天,企业对于智能化客户服务的需求日益增长。磐石云智能语音客服系统凭借其前沿技术架构与深度场景适配能力,正在重新定义人机交互的边界。本文将深入解析该系统如何通过技术创新实现服务效率与体验的双重突破。 一、意图识别…...
什么是iPaaS?
在当今数字化时代,企业面临着日益复杂的IT环境和不断增长的业务需求。随着云计算、微服务、物联网等技术的快速发展,企业需要更加高效、灵活且安全的方式来进行数据集成和应用集成。集成平台即服务(iPaaS)应运而生,成为…...
Vue3 中 Pinia 持久化的全面解析和最佳实践
Vue3 中 Pinia 持久化的全面解析 一、Pinia 简介 Pinia 是 Vue 的新一代状态管理库,它提供了简洁的 API,支持 Composition API,并且拥有良好的代码拆分和热更新能力。相比于 Vuex,Pinia 的代码结构更加扁平,易于理…...
蓝桥杯最后一天警告!!!
1.万能头文件 #include <bits/stdc.h> 2.一道题实在一点都不会,直接碰运气骗分 #include <bits/stdc.h> using namespace std;int main() {srand(time(0));printf("%d",rand()%101);//生成一个1到10之间的随机整数,并输出print…...