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

【软件干货】Android应用进程如何保活?

​1.Android 应用进程保活方法介绍

在Android应用程序中,为了保证应用的正常运行和稳定性,有时需要对应用进程进行保活。以下是一些实现进程保活的方法:

1、使用前台服务(Foreground Service):将服务调用startForeground()方法,并传入一个通知对象,将该服务置于前台运行状态。这样可以使得该服务的优先级更高,从而减少被系统杀死的概率。

2、使用JobScheduler:使用setPeriodic()方法可以让应用程序周期性地执行任务,从而避免长时间占用CPU资源,setPersisted(true)方法则表示当设备重启后,该任务仍然需要继续执行。

3、使用AlarmManager:使用这个API可以让应用程序在指定的时间间隔内执行任务。例如,可以设置一个闹钟,每隔一段时间唤醒应用程序并执行一些操作。

4、使用守护进程:启动一个后台守护进程,监控应用程序的状态并在应用程序被杀死时重新启动它,使用守护进程需要申请额外的权限。

5、使用双进程保活:启动两个相互绑定的进程,在其中一个进程被杀死时,另一个进程可以重新启动它。

6、使用WorkManger: 这是目前比较新的保活机制,用于取代JobScheduler。

需要注意的是,为了避免滥用和浪费系统资源,Android系统不断升级后,已经严格限制应用程序使用过多的后台资源和保活机制。

2.JobScheduler 用法简介

JobScheduler 是系统服务,由系统负责调度第三方应用注册的JobScheduler ,定时完成指定任务。

在应用中创建一个 JobService 服务,JobService 需要 API Level 21以上才可以使用,该服务注册时必须声明 android.permission.BIND_JOB_SERVICE 权限:

<!-- JobScheduler 拉活 --><serviceandroid:name=".jobscheduler.KeepAliveJobService"android:enabled="true"android:exported="true"android:permission="android.permission.BIND_JOB_SERVICE"></service>

通常使用JobScheduler需要以下几个步骤:

1、获取 JobScheduler 对象:通过Binder机制获取该JobScheduler系统服务;

// 创建 JobSchedulerJobScheduler jobScheduler =(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);

2、指定 JobScheduler 任务信息 JobInfo:绑定任务 ID,指定任务的运行组件,也就是之前创建并注册的 JobService, 最后要设置该任务在重启后也要执行;

// 第一个参数指定任务 ID// 第二个参数指定任务在哪个组件中执行// setPersisted 方法需要 android.permission.RECEIVE_BOOT_COMPLETED 权限// setPersisted 方法作用是设备重启后 , 依然执行 JobScheduler 定时任务JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(10,new ComponentName(context.getPackageName(), KeepAliveJobService.class.getName())).setPersisted(true);

3、设置时间信息:7.0 以下的系统可以设置间隔, 7.0 以上的版本需要设置延迟执行,否则无法启动;

// 7.0 以下的版本, 可以每隔 5000 毫秒执行一次任务if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N){jobInfoBuilder.setPeriodic(5_000);}else{// 7.0 以上的版本 , 设置延迟 5 秒执行// 该时间不能小于 JobInfo.getMinLatencyMillis 方法获取的最小值jobInfoBuilder.setMinimumLatency(5_000);}

4、开启定时任务;

// 开启定时任务jobScheduler.schedule(jobInfoBuilder.build());

5、7.0 以上的特殊处理,由于在7.0 以上的系统中设置了延迟执行,需要在JobService 的 onStartJob 方法中再次开启一次 JobScheduler 任务执行,也就是重复上述1 ~ 4执行, 这样就实现了周期性执行的目的;

public class KeepAliveJobService extends JobService {@Overridepublic boolean onStartJob(JobParameters params) {Log.i("KeepAliveJobService", "JobService onStartJob 开启");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){// 如果当前设备大于 7.0 , 延迟 5 秒 , 再次执行一次startJob(this);}return false;}}

3.WorkManager用法简介

WorkManager是适合用于持久性工作的推荐解决方案,它可处理三种类型的持久性工作:

1、立即执行:必须立即开始且很快就完成的任务,可以加急。

2、长时间运行:运行时间可能较长(有可能超过 10 分钟)的任务。

3、可延期执行:延期开始并且可以定期运行的预定任务。

通常使用WorkManager需要以下几个步骤:

1、将依赖项添加到应用的build.gradle文件中;

2、定义工作:工作使用 Worker 类定义,doWork() 方法在 WorkManager 提供的后台线程上异步运行。如需为 WorkManager 创建一些要运行的工作,则需扩展 Worker 类并替换 doWork() 方法;

public class XxxWorker extends Worker {publicXxxWorker(@NonNull Context context,@NonNull WorkerParameters params) {super(context, params);}@Overridepublic Result doWork() {// Do the work herexxxxx();// Indicate whether the work finished successfully with the Resultreturn Result.success();}}

3、创建 WorkRequest:定义工作后,必须使用WorkManager 服务进行调度该工作才能运行;

WorkRequest xxxWorkRequest =new OneTimeWorkRequest.Builder(XxxWorker.class).build();

4.将 WorkRequest 提交给系统:需要使用enqueue()方法将WorkRequest提交到WorkManager;

WorkManager.getInstance(myContext).enqueue(uploadWorkRequest);

在定义工作时要考虑要考虑下面常见的需求:

1、调度一次性工作还是重复性工作;

2、工作约束条件是怎样的,例如要求连接到 Wi-Fi 网络或正在充电;

3、确保至少延迟一定时间再执行工作;

4、设置重试和退避策略;

5、输入数据如何传递给工作等等。

4.双进程保活

双进程保活的方式就是在运行了一个主进程之外,还运行了一个 “本地前台进程”,并绑定“远程前台进程”, “远程前台进程”与“本地前台进程”实现了相同的功能,代码基本一致,这两个进程都是前台进程,都进行了提权,并且互相绑定,当监听到绑定的另外一个进程突然断开连接,则本进程再次开启前台进程提权,并且重新绑定对方进程,以达到拉活对方进程的目的。

双进程保活的实现步骤如下:

1、定义 AIDL 接口 IMyAidlInterface,每个服务中都需要定义继承 IMyAidlInterface.Stub 的 Binder 类,作为进程间通信的桥梁( 这是个默认的 AIDL 接口 ),监听进程的连接断开;

// Declare any non-default types here with import statementsinterface IMyAidlInterface {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);}

2、实现一个判定服务运行工具:

import android.app.Activity;import android.app.ActivityManager;import android.content.Context;import android.text.TextUtils;import org.w3c.dom.Text;import java.util.List;public class ServiceUtils {/*** 判定 Service 是否在运行* @param context* @return*/public static boolean isServiceRunning(Context context, String serviceName){if(TextUtils.isEmpty(serviceName)) return false;ActivityManager activityManager =(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);// 最多获取 200 个正在运行的 ServiceList<ActivityManager.RunningServiceInfo> infos =activityManager.getRunningServices(200);// 遍历当前运行的 Service 信息, 如果找到相同名称的服务 , 说明某进程正在运行for (ActivityManager.RunningServiceInfo info: infos){if (TextUtils.equals(info.service.getClassName(), serviceName)){return true;}}return false;}}

3、定义一个用于本地与远程连接的类:

class Connection implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// 服务绑定成功时回调}@Overridepublic void onServiceDisconnected(ComponentName name) {// 再次启动前台进程startService();// 绑定另外一个远程进程bindService();}}

4、定义一个本地前台服务类:

import android.app.Notification;import android.app.NotificationChannel;import android.app.NotificationManager;import android.app.Service;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.graphics.Color;import android.os.Build;import android.os.IBinder;import android.os.RemoteException;import androidx.core.app.NotificationCompat;import static androidx.core.app.NotificationCompat.PRIORITY_MIN;/*** 本地前台服务*/public class LocalForegroundService extends Service {/*** 远程调用 Binder 对象*/private MyBinder myBinder;/*** 连接对象*/private Connection connection;/*** AIDL 远程调用接口* 其它进程调与该 RemoteForegroundService 服务进程通信时 , 可以通过 onBind 方法获取该 myBinder 成员* 通过调用该成员的 basicTypes 方法 , 可以与该进程进行数据传递*/class MyBinder extends IMyAidlInterface.Stub {@Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString) throws RemoteException {// 通信内容}}@Overridepublic IBinder onBind(Intent intent) {return myBinder;}@Overridepublic void onCreate() {super.onCreate();// 创建 Binder 对象myBinder = new MyBinder();// 启动前台进程startService();}private void startService(){if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){// startForeground();// 创建通知通道NotificationChannel channel = new NotificationChannel("service","service", NotificationManager.IMPORTANCE_NONE);channel.setLightColor(Color.BLUE);channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// 正式创建service.createNotificationChannel(channel);NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "service");Notification notification = builder.setOngoing(true).setSmallIcon(R.mipmap.ic_launcher).setPriority(PRIORITY_MIN).setCategory(Notification.CATEGORY_SERVICE).build();// 开启前台进程 , API 26 以上无法关闭通知栏startForeground(10, notification);} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){startForeground(10, new Notification());// API 18 ~ 25 以上的设备 , 启动相同 id 的前台服务 , 并关闭 , 可以关闭通知startService(new Intent(this, CancelNotificationService.class));} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){// 将该服务转为前台服务// 需要设置 ID 和 通知// 设置 ID 为 0 , 就不显示已通知了 , 但是 oom_adj 值会变成后台进程 11// 设置 ID 为 1 , 会在通知栏显示该前台服务// 8.0 以上该用法报错startForeground(10, new Notification());}}/*** 绑定 另外一个 服务* LocalForegroundService 与 RemoteForegroundService 两个服务互相绑定*/private void bindService(){// 绑定另外一个 服务// LocalForegroundService 与 RemoteForegroundService 两个服务互相绑定// 创建连接对象connection = new Connection();// 创建本地前台进程组件意图Intent bindIntent = new Intent(this, RemoteForegroundService.class);// 绑定进程操作bindService(bindIntent, connection, BIND_AUTO_CREATE);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 绑定另外一个服务bindService();return super.onStartCommand(intent, flags, startId);}}

5、定义一个远程前台服务类:

import android.app.Notification;import android.app.NotificationChannel;import android.app.NotificationManager;import android.app.Service;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.graphics.Color;import android.os.Build;import android.os.IBinder;import android.os.RemoteException;import androidx.core.app.NotificationCompat;import static androidx.core.app.NotificationCompat.PRIORITY_MIN;/*** 远程前台服务*/public class RemoteForegroundService extends Service {/*** 远程调用 Binder 对象*/private MyBinder myBinder;/*** 连接对象*/private Connection connection;/*** AIDL 远程调用接口* 其它进程调与该 RemoteForegroundService 服务进程通信时 , 可以通过 onBind 方法获取该 myBinder 成员* 通过调用该成员的 basicTypes 方法 , 可以与该进程进行数据传递*/class MyBinder extends IMyAidlInterface.Stub {@Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString) throws RemoteException {// 通信内容}}@Overridepublic IBinder onBind(Intent intent) {return myBinder;}@Overridepublic void onCreate() {super.onCreate();// 创建 Binder 对象myBinder = new MyBinder();// 启动前台进程startService();}private void startService(){if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){// startForeground();// 创建通知通道NotificationChannel channel = new NotificationChannel("service","service", NotificationManager.IMPORTANCE_NONE);channel.setLightColor(Color.BLUE);channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// 正式创建service.createNotificationChannel(channel);NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "service");Notification notification = builder.setOngoing(true).setSmallIcon(R.mipmap.ic_launcher).setPriority(PRIORITY_MIN).setCategory(Notification.CATEGORY_SERVICE).build();// 开启前台进程 , API 26 以上无法关闭通知栏startForeground(10, notification);} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){startForeground(10, new Notification());// API 18 ~ 25 以上的设备 , 启动相同 id 的前台服务 , 并关闭 , 可以关闭通知startService(new Intent(this, CancelNotificationService.class));} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){// 将该服务转为前台服务// 需要设置 ID 和 通知// 设置 ID 为 0 , 就不显示已通知了 , 但是 oom_adj 值会变成后台进程 11// 设置 ID 为 1 , 会在通知栏显示该前台服务// 8.0 以上该用法报错startForeground(10, new Notification());}}/*** 绑定 另外一个 服务* LocalForegroundService 与 RemoteForegroundService 两个服务互相绑定*/private void bindService(){// 绑定 另外一个 服务// LocalForegroundService 与 RemoteForegroundService 两个服务互相绑定// 创建连接对象connection = new Connection();// 创建本地前台进程组件意图Intent bindIntent = new Intent(this, LocalForegroundService.class);// 绑定进程操作bindService(bindIntent, connection, BIND_AUTO_CREATE);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 绑定另外一个服务bindService();return super.onStartCommand(intent, flags, startId);}}

6、启动两个服务:

import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;import android.os.Bundle;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);startService(new Intent(this, LocalForegroundService.class));startService(new Intent(this, RemoteForegroundService.class));}}

5.双进程保活+JobScheduler整合方案

这种方案是在 JobService的onStartJob 方法中判定“双进程保活”中的双进程是否挂了 ,如果这两个进程挂了,就重新将挂掉的进程重启。

这里给出一个双进程保活+JobScheduler整合方案中JobScheduler部分的示意代码,而双进程保活部分保持不变。

public class KeepAliveJobService extends JobService {@Overridepublic boolean onStartJob(JobParameters params) {Log.i("KeepAliveJobService", "JobService onStartJob 开启");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){// 如果当前设备大于 7.0 , 延迟 5 秒 , 再次执行一次startJob(this);}// 判定本地前台进程是否正在运行boolean isLocalServiceRunning =ServiceUtils.isServiceRunning(this, LocalForegroundService.class.getName());if (!isLocalServiceRunning){startService(new Intent(this, LocalForegroundService.class));}// 判定远程前台进程是否正在运行boolean isRemoteServiceRunning =ServiceUtils.isServiceRunning(this, RemoteForegroundService.class.getName());if (!isRemoteServiceRunning){startService(new Intent(this, RemoteForegroundService.class));}return false;}@Overridepublic boolean onStopJob(JobParameters params) {Log.i("KeepAliveJobService", "JobService onStopJob 关闭");return false;}public static void startJob(Context context){// 创建 JobSchedulerJobScheduler jobScheduler =(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);// 第一个参数指定任务 ID// 第二个参数指定任务在哪个组件中执行// setPersisted 方法需要 android.permission.RECEIVE_BOOT_COMPLETED 权限// setPersisted 方法作用是设备重启后 , 依然执行 JobScheduler 定时任务JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(10,new ComponentName(context.getPackageName(), KeepAliveJobService.class.getName())).setPersisted(true);// 7.0 以下的版本, 可以每隔 5000 毫秒执行一次任务if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N){jobInfoBuilder.setPeriodic(5_000);}else{// 7.0 以上的版本 , 设置延迟 5 秒执行// 该时间不能小于 JobInfo.getMinLatencyMillis 方法获取的最小值jobInfoBuilder.setMinimumLatency(5_000);}// 开启定时任务jobScheduler.schedule(jobInfoBuilder.build());}}

参考文献

1、【Android 进程保活】应用进程拉活 ( 双进程守护 + JobScheduler 保活):https://hanshuliang.blog.csdn.net/article/details/115607584

2、【Android 进程保活】应用进程拉活 ( 双进程守护保活 ):https://hanshuliang.blog.csdn.net/article/details/115604667

3、【Android 进程保活】应用进程拉活 ( JobScheduler 拉活):https://hanshuliang.blog.csdn.net/article/details/115584240

4、Android实现进程保活的思路:https://blog.csdn.net/gs12software/article/details/130502312

5、WorkManager 使用入门:https://developer.android.google.cn/develop/background-work/background-tasks/persistent/getting-started

相关文章:

【软件干货】Android应用进程如何保活?

​1.Android 应用进程保活方法介绍 在Android应用程序中&#xff0c;为了保证应用的正常运行和稳定性&#xff0c;有时需要对应用进程进行保活。以下是一些实现进程保活的方法&#xff1a; 1、使用前台服务(Foreground Service)&#xff1a;将服务调用startForeground()方法&…...

neo4j部署保姆级教程

由于公司是基于大数据架构的&#xff0c;让部署neo4j数据库&#xff0c;之前没有接触过&#xff0c;然后紧急学了一下&#xff0c;并且从网上找了一些教程&#xff0c;决定还是记录下来&#xff0c;后续有时间了会在出一篇使用教程 环境准备&#xff08;root用户&#xff09; …...

【STM32CubeMX开发】-2.2-TIM_输出一个PWM信号

目录 1 Tim定时器的时钟源 2 Tim定时器的配置 2.1 PWM配置 2.2 中断配置 3 生成代码 4 测试结果 结尾 1 Tim定时器的时钟源 TIM3的时钟来源自APB1 Timer clocks&#xff0c;时钟树上所有总线频率均设置为了STM32F0能达到的最高频率&#xff0c;此时APB1 Timer clocks …...

Ngx+Lua+Redis 快速存储POST数据

系统几万台设备有windows有安卓还有linux系统&#xff0c;每个设备三分钟就会向服务器post设备的硬件信息&#xff0c;数据格式json&#xff0c;后台管理界面只需要最新的数据&#xff0c;不需要历史数据&#xff0c;业务逻辑非常简单&#xff0c;PHP代码就几行&#xff0c;已经…...

go-delve的使用

go-delve的非交互使用方式&#xff1a; dlv要执行的命令文件&#xff1a;cmd.dlv goroutines exit 执行非交互命令&#xff1a; yes n | dlv --allow-non-terminal-interactivetrue attach $pid --init cmd.dlv --end--...

Python网络爬虫技术详解

Python网络爬虫技术详解 引言 网络爬虫&#xff08;Web Crawler&#xff09;&#xff0c;又称网络蜘蛛&#xff08;Web Spider&#xff09;或网络机器人&#xff08;Web Robot&#xff09;&#xff0c;是一种按照一定规则自动抓取互联网信息的程序或脚本。它们通过遍历网页链…...

Golang | Leetcode Golang题解之第474题一和零

题目&#xff1a; 题解&#xff1a; func findMaxForm(strs []string, m, n int) int {dp : make([][]int, m1)for i : range dp {dp[i] make([]int, n1)}for _, s : range strs {zeros : strings.Count(s, "0")ones : len(s) - zerosfor j : m; j > zeros; j--…...

算法刷题技巧

算法题&#xff1a;https://leetcode.cn/studyplan/top-100-liked/ 哈希表 使用哈希表&#xff0c;增删改查的时间复杂度均为O(1)。何时使用哈希表&#xff1f; 在某个区域内查找一个已知元素&#xff0c;可以使用哈希表作为这个区域根据一个特征对元素进行分类&#xff0c;特征…...

BMS、EMS PCS 简介

1 储能系统的构成 完整的电化学储能系统主要由电池组、电池管理系统&#xff08;BMS&#xff09;、能量管理系统&#xff08;EMS&#xff09;、储能变流器&#xff08;PCS&#xff09;以及其他电气设备构成。 在储能系统中&#xff0c;电池组将状态信息反馈给电池管理系统BMS&…...

spug3发布项目

一、启动spug项目 1.spug代码仓库地址: spug: 开源运维平台&#xff1a;面向中小型企业设计的无 Agent的自动化运维平台&#xff0c;整合了主机管理、主机批量执行、主机在线终端、文件在线上传下载、应用发布、任务计划、配置中心、监控、报警等一系列功能。 - Gitee.com 注…...

鸿蒙HarmonyOS开发:应用权限的基本概念及如何申请应用权限详细介绍

文章目录 一、访问控制二、应用权限1、应用权限管控2、权限使用的基本原则3、授权方式4、权限等级 三、申请应用权限1、选择申请权限的方式2、声明权限3、声明样例4、二次向用户申请授权5、具体实现示例6、效果展示 四、应用权限列表1、system_grant&#xff08;系统授权&#…...

mac 桌面版docker no space left on device

报错信息 docker pull镜像时报&#xff1a; failed to register layer: Error processing tar file(exit status 1): write /home/admin/oceanbase_bak/bin/observer: no space left on device 解决 增加 docker 虚拟磁盘大小。 调整完点击重启即可。...

基于CIM的街镇基层治理统一指挥平台建设方案

1 项目概述 1.1 建设背景 社区作为人民生活的重要区域,往往需要对社区内人员、房屋、基本设施、日常业务进行规范管理,以保证其正常运行,但是传统的社区治理方式已不能满足新时代社会发展的要求,如人工采集录入信息、人员现场巡逻等,这些工作方式不仅工作量大,而且效率…...

PostgreSQL学习笔记三:数据类型和运算符

数据类型和运算符 PostgreSQL 支持多种数据类型和运算符&#xff0c;以下是一些常见的数据类型和运算符的概述&#xff1a; 数据类型 基本数据类型 整数类型&#xff1a; SMALLINT&#xff1a;2 字节&#xff0c;范围 -32,768 到 32,767。INTEGER&#xff1a;4 字节&#xff0…...

ROS理论与实践学习笔记——6 ROS机器人导航(仿真)

在 ROS 中&#xff0c;机器人导航&#xff08;Navigation&#xff09;是由多个功能包组合而成的系统&#xff0c;统称为导航功能包集&#xff08;navigation stack&#xff09;。它提供了一个全面的框架&#xff0c;使得移动机器人能够自主导航到指定目标点&#xff0c;同时避开…...

uniapp开发微信小程序,button的open-type=“share“ 分享给个人跳转到首页问题

当使用button标签带上open-type"share"属性&#xff0c;点击之后可分享当前页面给微信好友&#xff0c;但是分享之后朋友点开跳转到了首页问题。 需要使用 onShareAppMessage 函数 export default {onShareAppMessage(res) {if (res.from button) {// 来自页面内分…...

【jQuery】 jQuery基础及选择器介绍(基本选择器 层次选择器 属性选择器 过滤选择器)

文章目录 jQuery基础1. 优势2. 版本3. 基本语法4. 选择器基本选择器层次选择器属性选择器过滤选择器基本过滤选择器可见性过滤选择器 注意事项 jQuery基础 jQuery 是一个功能强大且易于使用的 JavaScript 库&#xff0c;它极大地简化了前端开发的工作。无论是 DOM 操作、事件处…...

网站在对抗机器人攻击的斗争中失败了

95% 的高级机器人攻击都未被发现&#xff0c;这一发现表明当前的检测和缓解策略存在缺陷。 这表明&#xff0c;虽然一些组织可能拥有基本的防御能力&#xff0c;但他们没有足够的能力应对更复杂的攻击。 例如利用人工智能和机器学习来模仿人类行为的攻击。 这些统计数据强调…...

Centos7 搭建logstash

下载并安装公共签名密钥&#xff1a; sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch 创建一个名为 /etc/yum.repos.d/logstash.repo 的文件&#xff0c;并添加以下内容&#xff1a; [logstash-7.x] nameElastic repository for 7.x packages baseu…...

面试题:Redis(五)

1. 面试题 面试问 记录对集合中的数据进行统计 在移动应用中&#xff0c;需要统计每天的新增用户数和第2天的留存用户数&#xff1b; 在电商网站的商品评论中&#xff0c;需要统计评论列表中的最新评论&#xff1b; 在签到打卡中&#xff0c;需要统计一个月内连续打卡的用户数&…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...

多元隐函数 偏导公式

我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式&#xff0c;给定一个隐函数关系&#xff1a; F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 &#x1f9e0; 目标&#xff1a; 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z​、 …...

2025.6.9总结(利与弊)

凡事都有两面性。在大厂上班也不例外。今天找开发定位问题&#xff0c;从一个接口人不断溯源到另一个 接口人。有时候&#xff0c;不知道是谁的责任填。将工作内容分的很细&#xff0c;每个人负责其中的一小块。我清楚的意识到&#xff0c;自己就是个可以随时替换的螺丝钉&…...