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

Android 10.0 截屏流程

通常未通过特殊定制的 Android 系统,截屏都是经过同时按住音量下键和电源键来截屏。本篇文章就只讨论使用这些特殊按键来进行截屏。
这里我们就要明白事件是在哪里进行分发拦截的。通过源码的分析,我们发现是在PhoneWindowManager.java 中。
PhoneWindowManager#interceptKeyBeforeQueueing()
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    @Overridepublic int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {if (!mSystemBooted) {// If we have not yet booted, don't let key events do anything.return 0;}// 省略部分代码......// Handle special keys.switch (keyCode) {......case KeyEvent.KEYCODE_VOLUME_DOWN:case KeyEvent.KEYCODE_VOLUME_UP:case KeyEvent.KEYCODE_VOLUME_MUTE: {// 按下音量键调用handleVolumeKey(event, policyFlags);......break;}......case KeyEvent.KEYCODE_POWER: {......if (down) {// 按下电源键将调用interceptPowerKeyDown(event, interactive);} else {          interceptPowerKeyUp(event, interactive, canceled);}break;}}return result;}

1、电源键处理

PhoneWindowManager#interceptPowerKeyDown()
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {// 省略部分代码......// Latch power key state to detect screenshot chord.if (interactive && !mScreenshotChordPowerKeyTriggered&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {// power键按下的标志mScreenshotChordPowerKeyTriggered = true;// 获取 Power 键的触发时间mScreenshotChordPowerKeyTime = event.getDownTime();// 处理屏幕截图事件interceptScreenshotChord();// 这个方法应该是消耗、拦截事件的,避免改变音量、铃声等。interceptRingerToggleChord();}// 省略部分代码......}

interceptScreenshotChord()该方法下面再说,先介绍电源按键、音量按键的处理。

2、音量键处理

PhoneWindowManager#handleVolumeKey()
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    public void handleVolumeKey(KeyEvent event, int policyFlags) {final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;final int keyCode = event.getKeyCode();final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {if (down) {// Any activity on the vol down button stops the ringer toggle shortcutcancelPendingRingerToggleChordAction();if (interactive && !mScreenshotChordVolumeDownKeyTriggered&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {// Volume键按下的标志mScreenshotChordVolumeDownKeyTriggered = true;// 获取 Volume 键的触发时间mScreenshotChordVolumeDownKeyTime = event.getDownTime();// 赋值  false 该属性为了防止截屏的时候音量下键生效出现调节音量的 dialog 状态值mScreenshotChordVolumeDownKeyConsumed = false;// 防止触发 Power  键长按功能cancelPendingPowerKeyAction();//处理屏幕截图事件interceptScreenshotChord();// 拦截相关快捷键interceptAccessibilityShortcutChord();}} else {// 省略部分代码......}} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {// 省略部分代码......}return;}

3、截屏事件处理 interceptScreenshotChord()

PhoneWindowManager#interceptScreenshotChord()
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    private void interceptScreenshotChord() {/** if 判断参数介绍* mScreenshotChordEnabled 其值为mContext.getResources().getBoolean(com.android.internal.R.bool.config_enableScreenshotChord);* mScreenshotChordVolumeDownKeyTriggered 音量下键按下时值为true* mScreenshotChordPowerKeyTriggered  电源键按下时值为true* mA11yShortcutChordVolumeUpKeyTriggered 音量上(加)键抬起时为false , 按下时为true**/if (mScreenshotChordEnabled&& mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered&& !mA11yShortcutChordVolumeUpKeyTriggered) {// 获取当前时间final long now = SystemClock.uptimeMillis();// 当前时间小于 音量下键按下时间 + 150ms// 当前时间小于 power键按下时间 + 150msif (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS&& now <= mScreenshotChordPowerKeyTime+ SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {boolean inLongScreenshot = Settings.System.getIntForUser(mContext.getContentResolver(),LONGSCREENSHOT_SETTING, 0, UserHandle.USER_CURRENT_OR_SELF) == 1;if (hasInPowerUtrlSavingMode() || inLongScreenshot) {return;}// 长按音量下键,达到截屏条件,将该事件消费掉。mScreenshotChordVolumeDownKeyConsumed = true;// 防止触发 Power  键长按功能cancelPendingPowerKeyAction();// 设置截图的类型,TAKE_SCREENSHOT_FULLSCREEN 为全屏mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);// 截图的方式,(例如:按键、三指下滑 等等)mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_CHORD);//执行 mScreenshotRunnablemHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());}}}

继续查看ScreenshotRunnable,此时会一步步向下调用,最终到SystemUI。
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    private class ScreenshotRunnable implements Runnable {private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;private int mScreenshotSource = SCREENSHOT_KEY_OTHER;public void setScreenshotType(int screenshotType) {mScreenshotType = screenshotType;}public void setScreenshotSource(int screenshotSource) {mScreenshotSource = screenshotSource;}@Overridepublic void run() {// 回调到 DisplayPolicy.javamDefaultDisplayPolicy.takeScreenshot(mScreenshotType, mScreenshotSource);}}

DisplayPolicy#takeScreenshot()
frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java

    // 请求截取屏幕截图public void takeScreenshot(int screenshotType, int source) {if (mScreenshotHelper != null) {mScreenshotHelper.takeScreenshot(screenshotType,mStatusBar != null && mStatusBar.isVisibleLw(),mNavigationBar != null && mNavigationBar.isVisibleLw(),source, mHandler, null /* completionConsumer */);}}

继续往下看ScreenshotHelper#takeScreenshot()
frameworks/base/core/java/com/android/internal/util/ScreenshotHelper.java

    // 请求截取屏幕截图public void takeScreenshot(final int screenshotType, final boolean hasStatus,final boolean hasNav, int source, @NonNull Handler handler,@Nullable Consumer<Uri> completionConsumer) {ScreenshotRequest screenshotRequest = new ScreenshotRequest(source, hasStatus, hasNav);takeScreenshot(screenshotType, SCREENSHOT_TIMEOUT_MS, handler, screenshotRequest,completionConsumer);}//到了 Binder调用环节, 此为客户端, 服务端为SystemUI中的 TakeScreenshotServiceprivate void takeScreenshot(final int screenshotType, long timeoutMs, @NonNull Handler handler,ScreenshotRequest screenshotRequest, @Nullable Consumer<Uri> completionConsumer) {synchronized (mScreenshotLock) {final Runnable mScreenshotTimeout = () -> {synchronized (mScreenshotLock) {if (mScreenshotConnection != null) {// 在获取屏幕截图捕获响应之前超时Log.e(TAG, "Timed out before getting screenshot capture response");// 重置连接resetConnection();// 通知截屏错误notifyScreenshotError();}}if (completionConsumer != null) {completionConsumer.accept(null);}};Message msg = Message.obtain(null, screenshotType, screenshotRequest);Handler h = new Handler(handler.getLooper()) {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case SCREENSHOT_MSG_URI:if (completionConsumer != null) {completionConsumer.accept((Uri) msg.obj);}handler.removeCallbacks(mScreenshotTimeout);break;case SCREENSHOT_MSG_PROCESS_COMPLETE:synchronized (mScreenshotLock) {resetConnection();}break;}}};msg.replyTo = new Messenger(h);if (mScreenshotConnection == null || mScreenshotService == null) {// 一个标准的Service连接// config_screenshotServiceComponent == com.android.systemui/com.android.systemui.screenshot.TakeScreenshotServicefinal ComponentName serviceComponent = ComponentName.unflattenFromString(mContext.getResources().getString(com.android.internal.R.string.config_screenshotServiceComponent));final Intent serviceIntent = new Intent();serviceIntent.setComponent(serviceComponent);ServiceConnection conn = new ServiceConnection() {@Override// 当Service连接成功之后public void onServiceConnected(ComponentName name, IBinder service) {synchronized (mScreenshotLock) {if (mScreenshotConnection != this) {return;}mScreenshotService = service;Messenger messenger = new Messenger(mScreenshotService);try {messenger.send(msg);} catch (RemoteException e) {Log.e(TAG, "Couldn't take screenshot: " + e);if (completionConsumer != null) {completionConsumer.accept(null);}}}}@Override// 当Service断开连接时public void onServiceDisconnected(ComponentName name) {synchronized (mScreenshotLock) {if (mScreenshotConnection != null) {resetConnection();// only log an error if we're still within the timeout periodif (handler.hasCallbacks(mScreenshotTimeout)) {handler.removeCallbacks(mScreenshotTimeout);notifyScreenshotError();}}}}};// bindServiceif (mContext.bindServiceAsUser(serviceIntent, conn,Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,UserHandle.CURRENT)) {mScreenshotConnection = conn;handler.postDelayed(mScreenshotTimeout, timeoutMs);}} else {// 如果已经连接则直接发送MessageMessenger messenger = new Messenger(mScreenshotService);try {messenger.send(msg);} catch (RemoteException e) {Log.e(TAG, "Couldn't take screenshot: " + e);if (completionConsumer != null) {completionConsumer.accept(null);}}handler.postDelayed(mScreenshotTimeout, timeoutMs);}}}

客户端通过向服务端发送 message 来将截屏任务交给 service,由 service 处理后面的操作。
frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java

    private Handler mHandler = new Handler(Looper.myLooper()) {@Overridepublic void handleMessage(Message msg) {// 获取客户端传的 Messenger 对象final Messenger callback = msg.replyTo;Consumer<Uri> uriConsumer = uri -> {Message reply = Message.obtain(null, SCREENSHOT_MSG_URI, uri);try {/ /Messenger 双向通信,在服务端用远程客户端的 Messenger 对象给客户端发送信息callback.send(reply);} catch (RemoteException e) {}};Runnable onComplete = () -> {Message reply = Message.obtain(null, SCREENSHOT_MSG_PROCESS_COMPLETE);try {callback.send(reply);} catch (RemoteException e) {}};// 判断用户的设备是否为解锁状态// 如果用户的存储被锁定,我们没有地方存储截图,所以跳过它,而不是显示一个误导性的动画和错误通知。if (!mUserManager.isUserUnlocked()) {Log.w(TAG, "Skipping screenshot because storage is locked!");post(() -> uriConsumer.accept(null));post(onComplete);return;}ScreenshotHelper.ScreenshotRequest screenshotRequest =(ScreenshotHelper.ScreenshotRequest) msg.obj;mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(screenshotRequest.getSource()));switch (msg.what) {case WindowManager.TAKE_SCREENSHOT_FULLSCREEN:  // 全屏截图// 我们在PhoneWindowManager传入的type为全屏截图,所以需要执行全屏截图流程mScreenshot.takeScreenshot(uriConsumer, onComplete);break;case WindowManager.TAKE_SCREENSHOT_SELECTED_REGION:  // 区域截图mScreenshot.takeScreenshot(uriConsumer, onComplete);break;case WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE:Bitmap screenshot = BitmapUtil.bundleToHardwareBitmap(screenshotRequest.getBitmapBundle());Rect screenBounds = screenshotRequest.getBoundsInScreen();Insets insets = screenshotRequest.getInsets();int taskId = screenshotRequest.getTaskId();int userId = screenshotRequest.getUserId();ComponentName topComponent = screenshotRequest.getTopComponent();mScreenshot.handleImageAsScreenshot(screenshot, screenBounds, insets,taskId, userId, topComponent, uriConsumer, onComplete);break;default:Log.d(TAG, "Invalid screenshot option: " + msg.what);}}};

TakeScreenshotService调用GlobalScreenshot.java的takeScreenshot();
GlobalScreenshot#takeScreenshot()

// GlobalScreenshot.java/***截取当前显示的屏幕截图并显示动画。.*/private void takeScreenshot(Consumer<Uri> finisher, Rect crop) {// copy the input Rect, since SurfaceControl.screenshot can mutate itRect screenRect = new Rect(crop);int rot = mDisplay.getRotation();int width = crop.width();int height = crop.height();takeScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, screenRect,Insets.NONE, true);}private void takeScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,Insets screenInsets, boolean showFlash) {// 此方法会清除上一次的截图信息--连续截图行为dismissScreenshot("new screenshot requested", true);mScreenBitmap = screenshot;if (mScreenBitmap == null) {// 如果没有Bitmap则报告错误信息mNotificationsController.notifyScreenshotError(R.string.screenshot_failed_to_capture_text);finisher.accept(null);mOnCompleteRunnable.run();return;}if (!isUserSetupComplete()) {// 用户设置尚未完成,不应该向用户展示 分享和编辑 , 只显示一个Toast并保存图片saveScreenshotAndToast(finisher);return;}// OptimizationsmScreenBitmap.setHasAlpha(false);mScreenBitmap.prepareToDraw();onConfigChanged(mContext.getResources().getConfiguration());if (mDismissAnimation != null && mDismissAnimation.isRunning()) {mDismissAnimation.cancel();}// 获取焦点setWindowFocusable(true);// 开始截图后动画startAnimation(finisher, screenRect, screenInsets, showFlash);}/*** 截屏后开始动画*/private void startAnimation(final Consumer<Uri> finisher, Rect screenRect, Insets screenInsets,boolean showFlash) {if (mScreenshotIng == false) {//unisoc: Modify for bug1360276mScreenshotIng = true;// 如果开启了省电模式,显示 toast,以便有一些视觉提示已截取屏幕截图PowerManager powerManager =(PowerManager) mContext . getSystemService (Context.POWER_SERVICE);if (powerManager.isPowerSaveMode()) {Toast.makeText(mContext, R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show();}mScreenshotHandler.post(() -> {if (!mScreenshotLayout.isAttachedToWindow()) {// mScreenshotLayout是截屏的缩略图的父View// mScreenshotLayout 在 GlobalScreenshot.java 的构造方法中初始化。对应布局文件:global_screenshot.xmlmWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);}// 动画相关的ViewmScreenshotAnimatedView.setImageDrawable(createScreenDrawable(mScreenBitmap, screenInsets));setAnimatedViewSize(screenRect.width(), screenRect.height());// 显示动画何时开始mScreenshotAnimatedView.setVisibility(View.GONE);//缩略图显示的View,将native层返回的Bitmap加载到此View上mScreenshotPreview.setImageDrawable(createScreenDrawable(mScreenBitmap, screenInsets));// 使静态预览不可见(消失),以便我们可以在屏幕上查询其位置mScreenshotPreview.setVisibility(View.INVISIBLE);mScreenshotHandler.post(() -> {mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this);// 创建动画mScreenshotAnimation =createScreenshotDropInAnimation(screenRect, showFlash);// 保存截图saveScreenshotInWorkerThread(finisher, new ActionsReadyListener () {@Overridevoid onActionsReady (SavedImageData imageData) {showUiOnActionsReady(imageData);mScreenshotIng = false;}});// 播放快门声音以通知我们已截屏mCameraSound.play(MediaActionSound.SHUTTER_CLICK);if (mScreenshotPreview.isAttachedToWindow()) {mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);mScreenshotPreview.buildLayer();}// 开始执行动画mScreenshotAnimation.start();});});}}/*** 创建一个新的工作线程并将屏幕截图保存到媒体存储*/private void saveScreenshotInWorkerThread(Consumer<Uri> finisher, @Nullable ActionsReadyListener actionsReadyListener) {SaveImageInBackgroundData data = new SaveImageInBackgroundData();data.image = mScreenBitmap;  // native 层返回的 Bitmapdata.finisher = finisher;data.mActionsReadyListener = actionsReadyListener;if (mSaveInBgTask != null) {// just log success/failure for the pre-existing screenshot// 只需记录预先存在的屏幕截图的成功失败mSaveInBgTask.setActionsReadyListener(new ActionsReadyListener() {@Overridevoid onActionsReady(SavedImageData imageData) {logSuccessOnActionsReady(imageData);}});}// 截图的一些信息存储在 SaveImageInBackgroundTask 中构建mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data);mSaveInBgTask.execute();}

到此截屏流程完毕,可以查看下截图的View的xml文件:global_screenshot.xml
frameworks/base/packages/SystemUI/res/layout/global_screenshot.xml

<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/global_screenshot_frame"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid:id="@+id/global_screenshot_actions_background"android:layout_height="@dimen/screenshot_bg_protection_height"android:layout_width="match_parent"android:layout_gravity="bottom"android:alpha="0.0"android:src="@drawable/screenshot_actions_background_protection"/><!--截屏动画相关的View --><ImageViewandroid:id="@+id/global_screenshot_animated_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="top|start"android:visibility="gone"android:elevation="@dimen/screenshot_preview_elevation"android:background="@drawable/screenshot_rounded_corners" /><ImageViewandroid:id="@+id/global_screenshot_flash"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone"android:elevation="@dimen/screenshot_preview_elevation"android:src="@android:color/white"/><com.android.systemui.screenshot.ScreenshotSelectorViewandroid:id="@+id/global_screenshot_selector"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone"android:pointerIcon="crosshair"/><!-- 此处包含了一个layout, 而缩略图的View就在此layout中,截屏右上角的关闭缩略图按钮 也在此layout中 --><include layout="@layout/global_screenshot_static"/>
</FrameLayout>

相关文章:

Android 10.0 截屏流程

通常未通过特殊定制的 Android 系统&#xff0c;截屏都是经过同时按住音量下键和电源键来截屏。本篇文章就只讨论使用这些特殊按键来进行截屏。 这里我们就要明白事件是在哪里进行分发拦截的。通过源码的分析&#xff0c;我们发现是在PhoneWindowManager.java 中。 PhoneWindow…...

Axure零基础深入浅出的讲解

在当今的互联网产品设计领域&#xff0c;原型设计已经成为了产品经理、设计师和开发者之间沟通的桥梁。而Axure作为一款功能强大、灵活易用的原型设计工具&#xff0c;正是很多产品经理的得力助手。无论你是产品经理新手&#xff0c;还是资深设计师&#xff0c;Axure都能帮助你…...

PyTorch求导相关

PyTorch是动态图&#xff0c;即计算图的搭建和运算是同时的&#xff0c;随时可以输出结果&#xff1b;而TensorFlow是静态图。 在pytorch的计算图里只有两种元素&#xff1a;数据&#xff08;tensor&#xff09;和 运算&#xff08;operation&#xff09; 运算包括了&#xf…...

Halcon基础-瓶盖带角度的OCR批量识别

Halcon基础-OCR识别 1、OCR识别素材2、创建路径文件3、Halcon代码实现4、运行效果5、资源获取 1、OCR识别素材 这里我准备了7张不同角度的OCR图片&#xff0c;如下所示&#xff1a; 2、创建路径文件 按照下图所示创建全部文件夹和文件&#xff1a; 01用来存放OCR识别原图 c…...

php语法学习

启动php 进入软件 打开文件&#xff1a;编写代码 $php true; $java false; var_dump($php);//输出变量细节 var_dump($java) 字符串 注意可以使用双引号也可以使用单引号 测试 $php "最好学web语言"; $java 脱胎于c语言; var_dump($php);//输出变量细节 var…...

JavaWeb合集22-Apache POI

二十二、Apache POI Apache POI是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用POI在Java 序中对Miscrosoft Office各种文件进行读写操作。一般情况下&#xff0c;POI都是用于操作Excel文件。 使用场景&#xff1a;银行网银系统导出…...

DDD重构-实体与限界上下文重构

DDD重构-实体与限界上下文重构 概述 DDD 方法需要不同类型的类元素&#xff0c;例如实体或值对象&#xff0c;并且几乎所有这些类元素都可以看作是常规的 Java 类。它们的总体结构是 Name: 类的唯一名称 Properties&#xff1a;属性 Methods: 控制变量的变化和添加行为 一…...

MATLAB Simulink (二)高速跳频通信系统

MATLAB & Simulink &#xff08;二&#xff09;高速跳频通信系统 写在前面1 系统原理1.1 扩频通信系统理论基础1.1.1 基本原理1.1.2 扩频通信系统处理增益和干扰容限1.1.3 各种干扰模式下抗干扰性能 1.2 高速跳频通信系统理论基础1.2.1 基本原理1.2.2 物理模型 2 方案设计2…...

智能合约分享

智能合约练习 一、solidity初学者经典示例代码&#xff1a; 1.存储和检索数据&#xff1a; // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 声明 Solidity 编译器版本// 定义一个名为 SimpleStorage 的合约 contract SimpleStorage {// 声明一个公共状态变量 d…...

【MR开发】在Pico设备上接入MRTK3(二)——在Unity中配置Pico SDK

上一篇文档介绍了 【MR开发】在Pico设备上接入MRTK3&#xff08;一&#xff09;在Unity中导入MRTK3依赖 下面将介绍在Unity中导入Pcio SDK的具体步骤 在Unity中导入Pico SDK 当前Pico SDK版本 Unity交互SDK git仓库&#xff1a; https://github.com/Pico-Developer/PICO-Un…...

【Java】探秘正则表达式:深度解析与精妙运用

目录 引言 一、基本概念 1.1 元字符 1.2 预定义字符类 1.3 边界匹配符 1.4 数量标识符 1.5 捕获与非捕获分组 二、Java中的正则表达式支持 三、正则表达式的使用示例 3.1 匹配字符串 3.2 替换字符串 3.3 分割字符串 3.4 使用Pattern和Matcher 3.5 捕获组和后向…...

2.6.ReactOS系统中从内核中发起系统调用

2.6.ReactOS系统中从内核中发起系统调用 2.6.ReactOS系统中从内核中发起系统调用 文章目录 2.6.ReactOS系统中从内核中发起系统调用前言 前言 上面我们已经可以看到用户空间&#xff08;R3&#xff09;进行系统调用的全过程即两种方法的具体实现。 系统调用一般时从R3发起的…...

chat_gpt回答:python获取当前utc时间,将xml里时间tag里的值修改为当前时间

你可以使用 lxml 库来读取、修改 XML 文件中的某个标签的值&#xff0c;并将其保存为新的 XML 文件。以下是一个示例代码&#xff0c;展示如何获取当前的 UTC 时间&#xff0c;并将 XML 文件中的某个时间标签修改为当前时间。 示例代码&#xff1a; from lxml import etree f…...

机器学习-语言分析

机器学习 1.1人工智能概述 1.2.1 机器学习与人工智能&#xff0c;深度学习 深度学习->机器学习->人工智能&#xff1b; 人工智能&#xff1a;1950&#xff0c;实现自动下棋&#xff0c;人机对弈&#xff0c;达特茅斯会议->人工智能的起点&#xff0c;1956年8月。克劳…...

Oracle 常见索引扫描方式概述,哪种索引扫描最快!

一.常见的索引扫描方式 INDEX RANGE SCANINDEX FAST FULL SCANINDEX FULL SCAN(MIN/MAX)INDEX FULL SCAN 二.分别模拟使用这些索引的场景 1.INDEX RANGE SCAN create table t1 as select rownum as id, rownum/2 as id2 from dual connect by level<500000; create inde…...

字符串(3)_二进制求和_高精度加法

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 字符串(3)_二进制求和_高精度加法 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目…...

《神经网络:智能时代的核心技术》

《神经网络&#xff1a;智能时代的核心技术》 一、神经网络的诞生与发展二、神经网络的结构与工作原理&#xff08;一&#xff09;神经元模型&#xff08;二&#xff09;神经网络训练过程 三、神经网络的应用领域&#xff08;一&#xff09;信息领域&#xff08;二&#xff09;…...

pdf内容三张以上转图片,使用spire.pdf.free

一、依赖 <spire.pdf.free.version>9.13.0</spire.pdf.free.version><itextpdf.version>5.5.13</itextpdf.version><dependency><groupId>e-iceblue</groupId><artifactId>spire.pdf.free</artifactId><version>$…...

游戏、软件、开源项目和资讯

游戏 标题链接【白嫖正版游戏】IT之家喜加一website 软件 标题链接【白嫖正版软件】反斗限免website 开源项目 标题链接【Luxirty Search】基于Google搜索结果&#xff0c;屏蔽内容农场Github【Video2X】图片/视频超分工具Github 新闻资讯 标题链接分享10个 Claude 3.5 …...

Acrel-1000变电站综合自动化系统及微机在化工企业中的应用方案

文&#xff1a;安科瑞郑桐 摘要&#xff1a;大型化工企业供配电具有的集约型特点&#xff0c;化工企业内35kV变电站和10kV变电所数量大、分布广&#xff0c;对于老的大多大型及中型化工企业而言&#xff0c;其变电站或变电所内高压电气设备为旧式继电保护装置&#xff0c;可靠…...

OBS多路推流插件技术深度解析:构建分布式直播分发系统的架构实践

OBS多路推流插件技术深度解析&#xff1a;构建分布式直播分发系统的架构实践 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 技术现状分析与行业痛点 在当前的实时流媒体生态中&#x…...

本地代码解释器:基于LLM与Docker沙箱的AI编程助手实现

1. 项目概述&#xff1a;一个本地化的代码解释器最近在GitHub上看到一个挺有意思的项目&#xff0c;叫Allen091080/local-code-interpreter。光看名字&#xff0c;很多开发者可能就会心一笑&#xff0c;这不就是想在本地复现类似ChatGPT Code Interpreter那种“对话式代码执行”…...

ESXi 6.7 能直接升级到 8.0 吗?正确升级路径一次讲清

很多运维新手在服务器虚拟化运维中&#xff0c;想把老旧的 ESXi 6.7 主机直接跨版本升级到 ESXi 8.0&#xff0c;省去中间步骤、节约时间成本&#xff0c;但实际操作中总会出现升级报错、镜像不兼容、引导失败等问题。其实官方明确规定&#xff1a;ESXi 6.7 不能直接越级升级到…...

Perplexity无法解析Springer LaTeX公式?2024.06最新MathJax兼容补丁+3类数学文献精准摘要生成术

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Perplexity解析Springer文献的底层机制与失效归因 Perplexity 作为衡量语言模型预测能力的关键指标&#xff0c;在学术文献解析场景中常被误用为“质量代理”&#xff0c;尤其在处理 Springer 出版集团…...

为什么92%的AI团队误用DeepSeek Serverless?——基于37家客户架构审计报告的5大认知断层与重构路径

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;为什么92%的AI团队误用DeepSeek Serverless&#xff1f; DeepSeek Serverless 本为轻量推理与函数即服务&#xff08;FaaS&#xff09;场景设计&#xff0c;但大量团队将其当作通用模型托管平台使用&am…...

iOS设备支持文件管理解决方案:如何解决Xcode开发环境兼容性问题

iOS设备支持文件管理解决方案&#xff1a;如何解决Xcode开发环境兼容性问题 【免费下载链接】iOSDeviceSupport All versions of iOS Device Support 项目地址: https://gitcode.com/gh_mirrors/ios/iOSDeviceSupport iOSDeviceSupport项目为iOS开发者提供了全面的设备支…...

模块二-数据选择与索引——06. 列选择与操作

06. 列选择与操作 1. 概述 数据选择是 Pandas 最常用的操作之一。掌握列选择与操作&#xff0c;可以高效地提取、添加、修改和删除数据列。 import pandas as pd import numpy as np# 创建示例数据 df pd.DataFrame({姓名: [张三, 李四, 王五, 赵六, 钱七],年龄: [25, 30, 28,…...

Git Conflict Resolution

1. 这篇文章解决什么问题&#xff1f; Git 冲突不是异常情况&#xff0c;而是多人协作和分支开发里的正常现象。 常见问题包括&#xff1a; 1. 为什么会产生冲突&#xff1f; 2. 冲突文件里的 <<<<<<<、、>>>>>>> 是什么&#xff1f…...

照片去背景的方法有哪些?2026年最全工具推荐与实用指南

前两天有个朋友问我&#xff0c;怎样能快速把证件照的底色换掉&#xff0c;还有电商卖家想给商品图去背景。我才意识到&#xff0c;现在还有很多人不知道照片去背景有这么多方便的办法。与其逐个讲解&#xff0c;我决定写篇文章&#xff0c;把我这些年试过的各种照片去背景的方…...

基于LLM的多智能体协作框架:从原理到实践构建自主开发团队

1. 项目概述与核心价值最近在开源社区里&#xff0c;一个名为zxkane/autonomous-dev-team的项目引起了我的注意。乍一看这个标题&#xff0c;你可能会联想到科幻电影里的全自动机器人编程&#xff0c;或者是一些过于理想化的“AI接管开发”的噱头。但在我花时间深入研究和实践之…...