Android屏幕录制

这里使用Java语言编写实现,完整代码如下:

文件 AndroidMainfest.xml 的主要配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.demoapp"><!-- for 屏幕录制 --><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".ScreenRecordingActivity"android:exported="false"android:launchMode="singleTask"></activity><serviceandroid:name=".ScreenRecordingService"android:enabled="true"android:exported="true"android:foregroundServiceType="mediaProjection" /></application></manifest>

文件ScreenRecordingActivity.java的完整代码

package com.example.demoapp;import android.Manifest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;/*** @Function: 屏幕录制。* @Author: ChengJh。* @Date: 2023/09/06。* @Description: https://blog.csdn.net/qq_46546793/article/details/123279152 和 https://blog.csdn.net/weixin_42602900/article/details/128340037 。*/
public class ScreenRecordingActivity extends AppCompatActivity {private static final String TAG = ScreenRecordingActivity.class.getSimpleName();//录屏服务private ScreenRecordingService mService;private int mServiceStatus = ScreenRecordingService.statusInit;private boolean clickedStart = false;private ActivityResultLauncher activityLauncher;private TextView textViewStatus;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_screen_recording);ActionBar actionBar = getSupportActionBar();if (actionBar != null) {actionBar.setHomeButtonEnabled(true);actionBar.setDisplayHomeAsUpEnabled(true);actionBar.setTitle("录屏管理页面");}textViewStatus = findViewById(R.id.textview_recording_status);Button btnStart = (Button) findViewById(R.id.btn_recording_start);btnStart.setOnClickListener(view -> {startRecord();});Button btnStop = (Button) findViewById(R.id.btn_recording_stop);btnStop.setOnClickListener(view -> {stopRecord();});//注: registerForActivityResult()方法, 只能在onCreate()中注册, onStart()之后就不能注册了。。activityLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), o -> {System.out.println(TAG + "_registerForActivityResult_callback_" + o.getResultCode());if (o.getResultCode() == Activity.RESULT_OK) {actionAfterConfirmAgreed(o.getResultCode(), o.getData());}});}@Overridepublic void onStart() {super.onStart();checkPermission();}@Overridepublic void onResume() {super.onResume();// checkPermission();}@Overridepublic void onDestroy() {/** 页面销毁的时候, 可以不停止录屏 */// stopRecord();if (mServiceStatus >= ScreenRecordingService.statusServiceConnected) {unbindService(serviceConnection);}super.onDestroy();}// 标题栏返回按钮事件。@Overridepublic boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {case android.R.id.home://this.finish();this.onBackPressed();return true;}return super.onOptionsItemSelected(item);}// @Override// //返回方法, 获取返回的信息。// protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {//   super.onActivityResult(requestCode, resultCode, data);//   System.out.println(TAG + "_onActivityResult");//   //首先判断请求码是否一致, 结果是否ok 。//   if (requestCode == ScreenRecordingService.requestCode && resultCode == RESULT_OK) {//     actionAfterUserAgree(resultCode, data);//   }// }@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);System.out.println(TAG + "_onRequestPermissionsResult");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && requestCode == ScreenRecordingService.requestCodeForPermisssion) {for (int i = 0; i < permissions.length; i++) {if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {return;}}connectService();}}/*** 权限申请*/private void checkPermission() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {String[] permissions = new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE};for (String permission : permissions) {if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, permissions, ScreenRecordingService.requestCodeForPermisssion);return;}}}connectService();}//连接服务。public void connectService() {System.out.println(TAG + "_connectService");//通过intent为中介绑定Service, 会自动创建。Intent intent = new Intent(this, ScreenRecordingService.class);//绑定过程连接, 选择绑定模式。bindService(intent, serviceConnection, BIND_AUTO_CREATE);}//连接服务成功与否, 具体连接过程。//调用连接接口, 实现连接, 回调连接结果。private final ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {System.out.println(TAG + "_ServiceConnection_onServiceConnected");//服务连接成功, 需要通过Binder获取服务, 达到Activity和Service通信的目的ScreenRecordingService.ScreenRecordBinder binder = (ScreenRecordingService.ScreenRecordBinder) iBinder;//通过Binder获取ServicemService = binder.getScreenRecordService();mService.setPrepareCompleteCallback(() -> {if (clickedStart && mService.startRecord()) {textViewStatus.setText("正在录屏");}});if (mService.isRunning()) {System.out.println(TAG + "_ServiceConnection_RunAlready");mServiceStatus = ScreenRecordingService.statusConfirmAgreed;textViewStatus.setText("正在录屏");if (clickedStart) {Toast.makeText(ScreenRecordingActivity.this, "已在录屏服务中", Toast.LENGTH_SHORT).show();}return;}mServiceStatus = ScreenRecordingService.statusServiceConnected;if (clickedStart) {actionAfterServiceConnected();}}@Overridepublic void onServiceDisconnected(ComponentName componentName) {//连接失败。Toast.makeText(ScreenRecordingActivity.this, "录屏服务未连接成功", Toast.LENGTH_SHORT).show();}};private void actionAfterConfirmAgreed(int resultCode, @Nullable Intent data) {mServiceStatus = ScreenRecordingService.statusConfirmAgreed;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {if (mService != null) {//获取录屏屏幕范围参数。DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);mService.setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);Intent intent = new Intent(this, ScreenRecordingService.class);intent.putExtra("code", resultCode);intent.putExtra("data", data);startForegroundService(intent);} else {System.out.println(TAG + "_onActivityResult_exception");}}}private void actionAfterServiceConnected() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//获取到服务, 初始化录屏管理者。MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);//通过管理者, 创建录屏请求, 通过Intent。Intent captureIntent = projectionManager.createScreenCaptureIntent();//将请求码作为标识一起发送, 调用该接口, 需有返回方法。//startActivityForResult(captureIntent, ScreenRecordingService.requestCode);activityLauncher.launch(captureIntent);}}private void nextActionByStatus() {switch (mServiceStatus) {case ScreenRecordingService.statusInit://点击请求录屏时, 第一件事, 检查权限。checkPermission();break;case ScreenRecordingService.statusPermissionOK:connectService();break;case ScreenRecordingService.statusServiceConnected:actionAfterServiceConnected();break;default:if (mService != null) {if (mService.startRecord()) {textViewStatus.setText("正在录屏");}}break;}}private void startRecord() {System.out.println(TAG + "_startRecord_" + (null == mService));clickedStart = true;if (mService != null && mService.isRunning()) {//如果在录制, 弹出提示。Toast.makeText(ScreenRecordingActivity.this, "当前正在录屏, 请不要重复点击哦", Toast.LENGTH_SHORT).show();} else {//如果不在录制, 就开启录制。nextActionByStatus();}}private void stopRecord() {clickedStart = false;if (null == mService || !mService.isRunning()) {//没有录屏, 无需停止, 弹出提示。Toast.makeText(ScreenRecordingActivity.this, "还没有录屏, 无需停止", Toast.LENGTH_SHORT).show();} else {//停止录屏。mService.stopRecord();textViewStatus.setText("已停止录屏");}}}

文件 ScreenRecordingService.java 的完整代码

package com.example.demoapp;import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Binder;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;import androidx.annotation.Nullable;import java.io.File;
import java.io.IOException;
import java.util.Objects;public class ScreenRecordingService extends Service {private static final String TAG = ScreenRecordingService.class.getSimpleName();public static final int statusInit = 0;public static final int statusPermissionOK = 1;public static final int statusServiceConnected = 2;public static final int statusConfirmAgreed = 3;public static final int requestCodeForPermisssion = 110;public static final int requestCode = 111;private MediaProjectionManager mediaProjectionManager;//录屏工具MediaProjection。private MediaProjection mediaProjection;//录像机MediaRecorder。private MediaRecorder mediaRecorder;//用于录屏的虚拟屏幕。private VirtualDisplay virtualDisplay;//录制屏幕的宽高像素。private int mWidth = 1280;private int mHeight = 1080;private int mDpi = 1;//标志, 判断是否正在录屏private boolean running = false;//声明视频存储路径private String videoPath = "";// 回调接口, 以及接口中要做的事。public interface PrepareCompleteCallback {void action();}private PrepareCompleteCallback prepareCompleteCallback;@Overridepublic void onCreate() {super.onCreate();// HandlerThread serviceThread = new HandlerThread("service_thread", android.os.Process.THREAD_PRIORITY_BACKGROUND);// serviceThread.start();// running = false;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 注: 生成mediaProjection必须在services中进行。createNotificationChannel();int resultCode = intent.getIntExtra("code", -1);Intent resultData = intent.getParcelableExtra("data");Log.i(TAG, "onStartCommand_resultCode=" + resultCode);Log.i(TAG, "onStartCommand_resultData=" + resultData);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {if (null == mediaProjectionManager) {mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);}mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, Objects.requireNonNull(resultData));//mediaProjection = ((MediaProjectionManager) Objects.requireNonNull(getSystemService(Context.MEDIA_PROJECTION_SERVICE))).getMediaProjection(resultCode, resultData);Log.i(TAG, "mediaProjection_created");}if (prepareCompleteCallback != null) {prepareCompleteCallback.action();}return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {super.onDestroy();}@Overridepublic boolean onUnbind(Intent intent) {return super.onUnbind(intent);}//返回的Binder。public class ScreenRecordBinder extends Binder {//返回Service的方法。public ScreenRecordingService getScreenRecordService() {return ScreenRecordingService.this;}}@Nullable@Override//返回一个Binder用于通信, 需要一个获取Service的方法。public IBinder onBind(Intent intent) {return new ScreenRecordBinder();}//设置需要录制的屏幕参数。public void setConfig(int width, int height, int dpi) {mWidth = width;mHeight = height;mDpi = dpi;}public void setMediaProjectionManager(MediaProjectionManager projectionManager) {mediaProjectionManager = projectionManager;}public void setPrepareCompleteCallback(PrepareCompleteCallback callback) {prepareCompleteCallback = callback;}//返回判断, 判断其是否在录屏。public boolean isRunning() {return running;}//服务的两个主要逻辑之一 ~ 开始录屏。public boolean startRecord() {Log.i(TAG, "startRecord");//首先判断是否有录屏工具以及是否在录屏if (null == mediaProjection || running) {return false;}//初始化录像机, 录音机Recorder。createRecorder();//根据获取的屏幕参数创建虚拟的录屏屏幕。createVirtualDisplay();//本来不加异常也可以, 但是这样就不知道是否start成功。//万一start没有成功, 但是running置为true了, 就产生了错误也无提示。//提示开始录屏了, 但是并没有工作。try {//准备工作都完成了, 可以开始录屏了。mediaRecorder.start();//标志位改为正在录屏。running = true;Toast.makeText(this, "录屏开启成功", Toast.LENGTH_SHORT).show();return true;} catch (Exception e) {e.printStackTrace();//有异常, start出错, 没有开始录屏。Toast.makeText(this, "录屏开启失败", Toast.LENGTH_SHORT).show();//标志位变回没有录屏的状态。running = false;return false;}}//服务的两个主要逻辑之一 ~ 停止录屏。public boolean stopRecord() {Log.i(TAG, "stopRecord");if (!running) {//没有在录屏, 无法停止。return false;}//无论设备是否还原或者有异常, 但是确实录屏结束, 修改标志位为未录屏。running = false;//本来加不加捕获异常都可以, 但是为了用户体验度, 添加会更好。try {//Recorder停止录像, 重置还原, 以便下一次使用。mediaRecorder.stop();mediaRecorder.reset();//释放virtualDisplay的资源。virtualDisplay.release();} catch (Exception e) {e.printStackTrace();//有异常, 保存失败。Toast.makeText(this, "录屏结束异常", Toast.LENGTH_SHORT).show();return false;}//无异常, 保存成功。Toast.makeText(this, "录屏结束 而且 保存成功", Toast.LENGTH_SHORT).show();return true;}//初始化Recorder录像机。public void createRecorder() {Log.i(TAG, "createRecorder");//创建Recorder。mediaRecorder = new MediaRecorder();//设置音频来源。mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置视频来源。mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);//设置视频格式为mp4。mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//设置视频存储地址。videoPath = getOutputFile().getAbsolutePath();//保存在该位置。mediaRecorder.setOutputFile(videoPath);//设置视频大小, 清晰度。mediaRecorder.setVideoSize(mWidth, mHeight);//设置视频编码为H264。mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);//设置音频编码。mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//设置视频码率。mediaRecorder.setVideoEncodingBitRate(2 * 1920 * 1080);mediaRecorder.setVideoFrameRate(18);//初始化完成, 进入准备阶段, 准备被使用。try {mediaRecorder.prepare();} catch (IOException e) {e.printStackTrace();//异常提示Toast.makeText(this, "Recorder录像机准备失败", Toast.LENGTH_SHORT).show();}}public void createVirtualDisplay() {//虚拟屏幕通过MediaProjection获取, 传入一系列传过来的参数。try {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {virtualDisplay = mediaProjection.createVirtualDisplay("VirtualScreen", mWidth, mHeight, mDpi,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);}} catch (Exception e) {e.printStackTrace();Toast.makeText(this, "virtualDisplay创建异常", Toast.LENGTH_SHORT).show();}}//获取输出存储文件夹的位置。private File getOutputDirectory() {String directoryFilePathName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()+ "/ScreenRecording/";//创建该文件夹。File directoryFile = new File(directoryFilePathName);if (!directoryFile.exists()) {//如果该文件夹不存在。if (!directoryFile.mkdirs()) {//如果没有创建成功。return null;}}//创建成功了, 返回该目录。return directoryFile;}private File getOutputFile() {File directoryFile = getOutputDirectory();File file = new File(directoryFile, "SR" + System.currentTimeMillis() + ".mp4");// if (!file.exists()) {//   try {//     file.createNewFile();//   } catch (Exception e) {//     e.printStackTrace();//   }// }Log.i(TAG, "filePath_" + file.getAbsolutePath());return file;}private void createNotificationChannel() {Notification.Builder builder = new Notification.Builder(this.getApplicationContext()); //获取一个Notification构造器。Intent nIntent = new Intent(this, MainActivity.class); //点击后跳转的界面, 可以设置跳转数据。builder.setContentIntent(PendingIntent.getActivity(this, 0, nIntent, 0)).setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.mipmap.ic_launcher)) // 设置下拉列表中的图标(大图标)//.setContentTitle("ScreenRecording") // 设置下拉列表里的标题.setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标.setContentText("is running......") // 设置上下文内容.setWhen(System.currentTimeMillis()); // 设置该通知发生的时间/** 以下是对Android 8.0的适配 */if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {final String channelId = "MyChannelId";final String channelName = "MyChannelName";//普通notification适配。builder.setChannelId(channelId);//前台服务notification适配。NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);notificationManager.createNotificationChannel(channel);}Notification notification = builder.build(); // 获取构建好的Notification对象。notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音。startForeground(requestCode, notification);}}

特别鸣谢下面链接:

(0)  https://blog.csdn.net/qq_46546793/article/details/123279152

(0)  https://blog.csdn.net/weixin_42602900/article/details/128340037

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

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

相关文章

第5章:传输层

文章目录 一、传输层概述1.传输层功能2.传输层的寻址与端口1.端口2.端口号3.套接字二、UDP协议1.UDP概述2.UDP首部格式3.UDP校验三、TCP协议1.TCP协议的特点2.TCP报文段的首部格式3.TCP连接管理(1)TCP连接的建立 (三次握手)(2)TCP连接的释放 (四次挥手)4.TCP可靠传输5.TCP流量控…

Halcon不改变目标大小尺寸及坐标,放大图像或区域

如果需要检测一张图像中很细小的物体&#xff0c;计算机可能可以观察到&#xff0c;但人的肉眼很难判别。这时候就需要放大图像中目标所在区域进行观测&#xff0c;放大观察可能会导致图像被放大&#xff0c;目标相对原始图像的坐标大小信息会被改变。如下&#xff0c;分割图中…

CloudCompare 二次开发(13)——点云投影到圆柱

目录 一、概述二、代码集成三、结果展示一、概述 不依赖任何第三方点云相关库,使用CloudCompare编程实现点云投影到指定圆柱,具体计算原理见:PCL 点云投影到圆柱 二、代码集成 1、mainwindow.h文件public中添加: void doActionProjectToCylinder(); // 投影到圆柱2、mai…

rt-thread系列文章目录

rt-thread系列文章目录 本文是rt-thread系列文章目录&#xff0c;后续关于rt-thread的更新都会添加到此文内。 实战篇 rt-thread------生成工程模板 rt-thread------fal移植 内核篇 rt-thread-------内存管理&#xff08;内存堆&#xff09; 设备和驱动篇 C语言面向对象…

单例模式(饿汉式单例 VS 懒汉式单例)

所谓的单例模式就是保证某个类在程序中只有一个对象 一、如何控制只产生一个对象&#xff1f; 1.构造方法私有化&#xff08;保证对象的产生个数&#xff09; 创建类的对象&#xff0c;要通过构造方法产生对象 构造方法若是public权限&#xff0c;对于类的外部&#xff0c;可…

JAR will be empty - no content was marked for inclusion!

现象 在对自建pom依赖组件打包时&#xff0c;出现JAR will be empty - no content was marked for inclusion!错误。 方案 在pom中怎么加packaging标签内容为pom&#xff0c;标识只打包pom文件 <?xml version"1.0" encoding"UTF-8"?> ...<grou…

科技互联网领域,怎样才算突破性创新?

在科技互联网领域&#xff0c;一个突破性的创新应该具备以下特征&#xff1a; 革命性&#xff1a;突破性创新应该能够彻底改变行业或市场&#xff0c;引起根本性的变革。前瞻性&#xff1a;突破性创新应该有前瞻性&#xff0c;能够在未来产生重大影响。这意味着创新应该不仅考…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十二:通用详情组件封装实现

一、本章内容 本章实现通用详情组件,自动识别实体配置信息,并自动生成对应组件,填充组件数据,并完成数据自动加载等过程。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 3.1 B站视频地址࿱

对比学习与simclr详解

对比学习&#xff08;Contrastive Learning&#xff09;是一种机器学习方法&#xff0c;旨在通过比较数据样本之间的相似性和差异性来学习有用的表示&#xff08;特征&#xff09;。其核心思想是通过将相似的样本映射到相邻的位置&#xff0c;将不相似的样本映射到远离的位置&a…

微信小程序——简易复制文本

在微信小程序中&#xff0c;可以使用wx.setClipboardData()方法来实现复制文本内容的功能。以下是一个示例代码&#xff1a; // 点击按钮触发复制事件 copyText: function() {var that this;wx.setClipboardData({data: 要复制的文本内容,success: function(res) {wx.showToa…

ARM指令集

CPU是计算机的中央处理器&#xff0c;负责执行组成计算机程序的指令。为此&#xff0c;CPU必须能够解释机器码即计算机程序的最低级别表示形式&#xff0c;以让CPU可以直接执行。机器码是一系列的二进制指令&#xff0c;每个指令都代表CPU可以执行的特定操作。指令由一系列1和0…

微信小程序onReachBottom事件使用

在微信小程序中&#xff0c;onReachBottom事件用于监听页面滚动到页面底部的时候触发的事件。当用户滑动页面到底部时&#xff0c;可以通过监听该事件来执行相应的操作。 要使用onReachBottom事件&#xff0c;需要在对应的页面或组件中定义一个函数&#xff0c;并在Page或Comp…

vue3 将 HTML 网页内容生成为 PDF 文件

使用 html2pdf.js 实现 npmjs 地址&#xff1a;html2pdf.js github 仓库地址&#xff1a;html2pdf.js 使用 html2pdf.js 的方法非常简单&#xff0c;只需要能获取到要生成 PDF 的 HTML 元素即可 安装 npm i html2pdf.js引入 先在需要使用导出的页面引入 import html2pdf fr…

操作系统 --- 计算机系统引论

&#xff08;一&#xff09;操作系统的目的和作用 概念&#xff08;定义&#xff09; 操作系统 &#xff08; Operating System &#xff0c; OS &#xff09;是指控制和 管理 整个计算机系统的 硬件和软件 资源&#xff0c;并合理地组织调度计算机的工作和资源的分配&#…

数据分析面试题(2023.09.08)

数据分析流程 总体分为四层&#xff1a;需求层、数据层、分析层和结论层 一、统计学问题 1、贝叶斯公式复述并解释应用场景 公式&#xff1a;P(A|B) P(B|A)*P(A) / P(B)应用场景&#xff1a;如搜索query纠错&#xff0c;设A为正确的词&#xff0c;B为输入的词&#xff0c;那…

vue-elementPlus自动按需导入和主题定制

elementPlus自动按需导入 装包 -> 配置 1. 装包&#xff08;主包和两个插件包&#xff09; $ npm install element-plus --save npm install -D unplugin-vue-components unplugin-auto-import 2. 配置 在vite.config.js文件中配置&#xff0c;配置完重启&#xff08;n…

Leetcode.664 奇怪的打印机

题目链接 Leetcode.664 奇怪的打印机 hard 题目描述 有台奇怪的打印机有以下两个特殊要求&#xff1a; 打印机每次只能打印由 同一个字符 组成的序列。每次可以在从起始到结束的任意位置打印新字符&#xff0c;并且会覆盖掉原来已有的字符。 给你一个字符串 s &#xff0c;你…

数学建模--Seaborn库绘图基础的Python实现

目录 1.绘图数据导入 2. sns.scatterplot绘制散点图 3.sns.barplot绘制条形图 4.sns.lineplot绘制线性图 5.sns.heatmap绘制热力图 6.sns.distplot绘制直方图 7.sns.pairplot绘制散图 8.sns.catplot绘制直方图 9.sns.countplot绘制直方图 10.sns.lmplot绘回归图 1.绘图数…

React中函数式组件与类组件有何不同?

Function Component 与 Class Component 有何不同 目录 Function Component 与 Class Component 有何不同 文章核心观点&#xff1a; 解释一下&#xff1a; 总结&#xff1a; 文章核心观点&#xff1a; Function components capture the rendered values.函数式组件捕获…

【漏洞复现】深信服科技EDR平台存在任意用户登录漏洞

漏洞描述 深信服终端检测响应平台EDR,通过云网端联动协同、威胁情报共享、多层级响应机制,帮助用户快速处置终端安全问题,构建轻量级、智能化、响应快的下一代终端安全系统。 该EDR系统存在任意用户登录漏洞&#xff0c;攻击者通过漏洞可以登录系统后台并获取服务器的敏感信息…