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 系统,截屏都是经过同时按住音量下键和电源键来截屏。本篇文章就只讨论使用这些特殊按键来进行截屏。 这里我们就要明白事件是在哪里进行分发拦截的。通过源码的分析,我们发现是在PhoneWindowManager.java 中。 PhoneWindow…...
Axure零基础深入浅出的讲解
在当今的互联网产品设计领域,原型设计已经成为了产品经理、设计师和开发者之间沟通的桥梁。而Axure作为一款功能强大、灵活易用的原型设计工具,正是很多产品经理的得力助手。无论你是产品经理新手,还是资深设计师,Axure都能帮助你…...
PyTorch求导相关
PyTorch是动态图,即计算图的搭建和运算是同时的,随时可以输出结果;而TensorFlow是静态图。 在pytorch的计算图里只有两种元素:数据(tensor)和 运算(operation) 运算包括了…...
Halcon基础-瓶盖带角度的OCR批量识别
Halcon基础-OCR识别 1、OCR识别素材2、创建路径文件3、Halcon代码实现4、运行效果5、资源获取 1、OCR识别素材 这里我准备了7张不同角度的OCR图片,如下所示: 2、创建路径文件 按照下图所示创建全部文件夹和文件: 01用来存放OCR识别原图 c…...
php语法学习
启动php 进入软件 打开文件:编写代码 $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各种文件格式的开源项目。简单来说就是,我们可以使用POI在Java 序中对Miscrosoft Office各种文件进行读写操作。一般情况下,POI都是用于操作Excel文件。 使用场景:银行网银系统导出…...
DDD重构-实体与限界上下文重构
DDD重构-实体与限界上下文重构 概述 DDD 方法需要不同类型的类元素,例如实体或值对象,并且几乎所有这些类元素都可以看作是常规的 Java 类。它们的总体结构是 Name: 类的唯一名称 Properties:属性 Methods: 控制变量的变化和添加行为 一…...
MATLAB Simulink (二)高速跳频通信系统
MATLAB & Simulink (二)高速跳频通信系统 写在前面1 系统原理1.1 扩频通信系统理论基础1.1.1 基本原理1.1.2 扩频通信系统处理增益和干扰容限1.1.3 各种干扰模式下抗干扰性能 1.2 高速跳频通信系统理论基础1.2.1 基本原理1.2.2 物理模型 2 方案设计2…...
智能合约分享
智能合约练习 一、solidity初学者经典示例代码: 1.存储和检索数据: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 声明 Solidity 编译器版本// 定义一个名为 SimpleStorage 的合约 contract SimpleStorage {// 声明一个公共状态变量 d…...
【MR开发】在Pico设备上接入MRTK3(二)——在Unity中配置Pico SDK
上一篇文档介绍了 【MR开发】在Pico设备上接入MRTK3(一)在Unity中导入MRTK3依赖 下面将介绍在Unity中导入Pcio SDK的具体步骤 在Unity中导入Pico SDK 当前Pico SDK版本 Unity交互SDK git仓库: 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系统中从内核中发起系统调用前言 前言 上面我们已经可以看到用户空间(R3)进行系统调用的全过程即两种方法的具体实现。 系统调用一般时从R3发起的…...
chat_gpt回答:python获取当前utc时间,将xml里时间tag里的值修改为当前时间
你可以使用 lxml 库来读取、修改 XML 文件中的某个标签的值,并将其保存为新的 XML 文件。以下是一个示例代码,展示如何获取当前的 UTC 时间,并将 XML 文件中的某个时间标签修改为当前时间。 示例代码: from lxml import etree f…...
机器学习-语言分析
机器学习 1.1人工智能概述 1.2.1 机器学习与人工智能,深度学习 深度学习->机器学习->人工智能; 人工智能:1950,实现自动下棋,人机对弈,达特茅斯会议->人工智能的起点,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)_二进制求和_高精度加法
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 字符串(3)_二进制求和_高精度加法 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌 目…...
《神经网络:智能时代的核心技术》
《神经网络:智能时代的核心技术》 一、神经网络的诞生与发展二、神经网络的结构与工作原理(一)神经元模型(二)神经网络训练过程 三、神经网络的应用领域(一)信息领域(二)…...
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搜索结果,屏蔽内容农场Github【Video2X】图片/视频超分工具Github 新闻资讯 标题链接分享10个 Claude 3.5 …...
Acrel-1000变电站综合自动化系统及微机在化工企业中的应用方案
文:安科瑞郑桐 摘要:大型化工企业供配电具有的集约型特点,化工企业内35kV变电站和10kV变电所数量大、分布广,对于老的大多大型及中型化工企业而言,其变电站或变电所内高压电气设备为旧式继电保护装置,可靠…...
[Linux] CentOS7替换yum源为阿里云并安装gcc详细过程(附下载链接)
前言 CentOS7替换yum源为阿里云 yum是CentOS中的一种软件管理器,通过yum安装软件,可以自动解决包依赖的问题,免去手工安装依赖包的麻烦。 yum使用了一个中心仓库来记录和管理软件的依赖关系,默认为mirrorlist.centos.org…...
在Java中创建多线程的三种方式
多线程的创建和启动方式 在Java中,创建多线程主要有以下三种方式: 继承Thread类实现Runnable接口使用Callable接口与Future 下面是这三种方式的简单示例,以及如何在主类中启动它们。 1. 继承Thread类 class MyThread extends Thread {Ov…...
洛谷 AT_abc374_c [ABC374C] Separated Lunch 题解
题目大意 KEYENCE 总部有 N N N 个部门,第 i i i 个部门有 K i K_i Ki 个人。 现在要把所有部门分为 AB 两组,求这两组中人数多的那一组的人数最少为多少。 题目分析 设这些部门共有 x x x 个人,则较多的组的人数肯定大于等于 ⌈ …...
力扣2528.最大化城市的最小电量
力扣2528.最大化城市的最小电量 题目解析及思路 题目要求找到所有城市电量最小值的最大 电量为给城市供电的发电站数量 因此每座城市的电量可以用一段区间和表示,即前缀和 二分最低电量时 如果当前城市电量不够,贪心的想发电站建立的位置,应该是在mi…...
【zookeeper】集群配置
zookeeper 数据结构 zookeeper数据模型结构,就和Linux的文件系统类型,看起来是一颗树,每个节点称为一个znode.每一个Znode默认的存储1MB的数据,每个Znode都有唯一标识,可以通过命令显示节点的信息每当节点有数据变化…...
YOLO11 目标检测 | 导出ONNX模型 | ONNX模型推理
本文分享YOLO11中,从xxx.pt权重文件转为.onnx文件,然后使用.onnx文件,进行目标检测任务的模型推理。 用ONNX模型推理,便于算法到开发板或芯片的部署。 备注:本文是使用Python,编写ONNX模型推理代码的 目…...
PostgreSQL DBA月度检查列表
为了确保数据库系统能够稳定高效运行,DBA 需要定期对数据库进行检查和维护,这是一项非常具有挑战性的工作。 本文给大家推荐一个 PostgreSQL DBA 月度性能检查列表,遵循以下指导原则可以帮助我们实现一个高可用、高性能、低成本、可扩展的数…...
驱动开发系列12 - Linux 编译内核模块的Makefile解释
一:内核模块Makefile #这一行定义了要编译的内核模块目标文件。obj-m表示目标模块对象文件(.o文件), #并指定了两个模块源文件:helloworld-params.c 和 helloworld.c。最终会生成这 #这两个.c文件的.o对象文件。 obj-m := helloworld-params.o helloworld.o#这行定义了内核…...
用js+css实现圆环型的进度条——js+css基础积累
如果用jscss实现圆环型的进度条: 直接上代码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><met…...
TDengine 与北微传感达成合作,解决传统数据库性能瓶颈
在当今物联网(IoT)快速发展的背景下,传感器技术已成为各个行业数字化转型的关键组成部分。随着设备数量的激增和数据生成速度的加快,如何高效地管理和分析这些数据,成为企业实现智能化运营的重要挑战。尤其是在惯性传感…...
台州市城市建设规划局网站/自动优化app
局部变量表 局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。 一个局部变量可以保存一个类型为boolean、byte、char、short、int、float、reference和returnAddress类型的数据。reference类型表示对一个对象…...
网站建设中的主要功能/三只松鼠有趣的软文
在.onInit里面添加如下代码: # 禁止多个安装程序实例 Begin System::Call kernel32::CreateMutexA(i 0, i 0, t "mysetup") i .r1 ?e #注意最后的?e Pop $R0 #保存LastError返回值 ;System::Call kernel32::CloseHandle(i r1) i.s #此处不能关闭…...
南阳网站建设价格/谷歌搜索引擎入口363
集成运放的主要技术参数 评价集成运放好坏的参数很多,它们是描述一个实际运放与理想放大器件接近程度的数据,这里仅介绍其中主要的几种。一、输入参数1.输入失调电压UO 及其温漂在室温及标准电源电压下,为了使静态UO 0࿰…...
衢州集团网站建设/青岛seo网站关键词优化
/*获得当前系统时间,插入到mysql数据库,数据库中的数据类型为datatime,对应于java.sql.Timestamp *时间格式为yyyy-MM-ddHH:mm:ss *pst.setTimestamp(4, new java.sql.Timestamp(new java.util.Date().getTime())); …...
成都网站建设科/seo搜索优化是什么意思
导读: 现在网页设计方面的站点越来越多,究竟哪个才是经典;根据网页设计中牵涉到的:网页制作,平面设计,动画制作,素材安排等,我特地找了些好的站点,发表在这里,…...
广告公司名字简单大气三个字/优化网站排名解析推广
一、25岁之前想做什么就做什么,什么都该尝试一下。不然,25岁以后,你还不知道自己能做什么能担什么责任。 二、25岁之前,爱情可以很纯洁,但不会到永远.花开堪折直须折。25岁以后你很难相信有纯洁的爱情。 三、25岁以前不要怕&#…...