Android11 framework 禁止三方应用开机自启动
Android11应用自启动限制
大纲
- Android11应用自启动限制
- 分析
- 验证猜想:Android11 AOSP是否自带禁止三方应用监听`BOOT_COMPLETED`
- 方案
- 禁止执行非系统应用监听到`BOOT_COMPLETED`后的代码逻辑
- 在执行启动时判断其启动的广播接收器
- 一棍子打死方案(慎用)
- 补充!!!!!!!
分析
按理说三方应用应该收不到开机启动广播(后文会证实这个说法是假的),但是很神奇的是还是有应用能自启动,体现为比如秋秋,启动后通过ps命令能看到其进程存活,但是静置后进程会启动失败,从而导致被清理
07-18 05:59:02.132367 938 967 I ActivityManager: Start proc 1930:com.tencent.mobileqq:MSF/u0a110 for broadcast {com.tencent.mobileqq/com.tencent.mobileqq.msf.core.NetConnInfoCenter}
log如上
参照这篇博客Android系统层面限制应用开机自启动详解,此时通过Android Studio查看其apk的manifest,其NetConnInfoCenter
内容如下
可以看到其监听了开机广播外,还监听了各种各样的广播,比如TIMEZONE_CHANGED
,看起来是时区变换的广播,这边尝试了一下在没有启动秋秋的情况下,去切换时区,果然打印了启动秋秋的log,虽然没有启动成功,但是之前在这个项目中,自己遇到过秋秋启动成功的情况,所以还是要处理
<receiverandroid:name="com.tencent.mobileqq.msf.core.NetConnInfoCenter"android:exported="false"android:process=":MSF"><intent-filterandroid:priority="2147483647"><actionandroid:name="android.intent.action.BOOT_COMPLETED" /></intent-filter><intent-filter><actionandroid:name="android.intent.action.MY_PACKAGE_REPLACED" /></intent-filter><intent-filter><actionandroid:name="android.net.conn.CONNECTIVITY_CHANGE" /></intent-filter><intent-filter><actionandroid:name="android.intent.action.TIME_SET" /></intent-filter><intent-filter><actionandroid:name="android.intent.action.TIMEZONE_CHANGED" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.rdm.report" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.receiveofflinepush" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.offlinepushclearall" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.receiveofflinepushav" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.offlinepushclearallav" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.startmsf" /></intent-filter><intent-filter><actionandroid:name="android.intent.action.MEDIA_BAD_REMOVAL" /><actionandroid:name="android.intent.action.MEDIA_EJECT" /><actionandroid:name="android.intent.action.MEDIA_MOUNTED" /><actionandroid:name="android.intent.action.MEDIA_REMOVED" /><actionandroid:name="android.intent.action.MEDIA_SCANNER_FINISHED" /><actionandroid:name="android.intent.action.MEDIA_SCANNER_STARTED" /><actionandroid:name="android.intent.action.MEDIA_SHARED" /><actionandroid:name="android.intent.action.MEDIA_UNMOUNTED" /><dataandroid:scheme="file" /></intent-filter><intent-filter><actionandroid:name="android.net.wifi.WIFI_STATE_CHANGED" /></intent-filter></receiver>
验证猜想:Android11 AOSP是否自带禁止三方应用监听BOOT_COMPLETED
因为前面提到Android11三方应用到底能不能监听开机广播,这边写了个demo,仅监听BOOT_COMPLETED
,重启后验证,进程会正常被创建,所以Android11并没有原生的禁止三方监听BOOT_COMPLETED
的策略。至少AOSP没有,国内手机带此功能是手机厂商自己实现的
public class BootReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {Intent mIntent = new Intent(context, MainActivity.class);mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(mIntent); // 启动你的应用程序}}
}<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED" /><receiver android:name=".BootReceiver"android:exported="false"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter>
</receiver>
结论:Android11上普通三方应用是可以接收到开机广播的,此时如果应用去自启动,后台会有进程存活,因此需要做处理
方案
禁止执行非系统应用监听到BOOT_COMPLETED
后的代码逻辑
在处理广播的地方 过滤掉所有的三方应用,并预留白名单
在AMS的broadcastIntentLocked
方法中
diff --git a/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java b/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
index f26ae929ef..6b906ced4f 100644
--- a/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16736,7 +16736,30 @@ public class ActivityManagerService extends IActivityManager.Stubfinal int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,@Nullable String callerFeatureId, Intent intent, String resolvedType,IIntentReceiver resultTo, int resultCode, String resultData,Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,int realCallingPid, int userId, boolean allowBackgroundActivityStarts,@Nullable int[] broadcastWhitelist) {...if (receivers != null) {String skipPackages[] = null;if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())|| Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())|| Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {Uri data = intent.getData();if (data != null) {String pkgName = data.getSchemeSpecificPart();if (pkgName != null) {skipPackages = new String[] { pkgName };}}} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- }
+ // add by xumaoxin start
+ } else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
+ //Resources res = mContext.getResources();
+ //String[] blacklist = res.getStringArray(com.android.internal.R.array.blacklist_boot_receiver);
+ List<String> skipList = new ArrayList<>();
+ Set<String> whitelist = new ArraySet<>();
+ whitelist.add("com.example.test11");
+
+ for (int i = 0, j = receivers.size(); i < j; i++) {
+ ResolveInfo curt = (ResolveInfo) receivers.get(i);
+ String curPkgName = curt.activityInfo.packageName;
+ if ((curt.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ //Slog.i("ActivityManager", "xumaoxin: " + curPkgName + " is system app, allow!");
+ } else if (!whitelist.contains(curPkgName)) {
+ Slog.i("ActivityManager", "xumaoxin: " + curPkgName + " is not system app and not whitelist, not allow!");
+ skipList.add(curPkgName);
+ }else {
+ Slog.i("ActivityManager", "xumaoxin: " + curPkgName + " is not system app but is whitelist, allow!");
+ }
+ }
+ skipPackages = skipList.toArray(new String[0]);
+ Slog.i("ActivityManager", "xumaoxin: skipPackages= " + Arrays.toString(skipPackages));
+ //add by xumaoxin end
+ } if (skipPackages != null && (skipPackages.length > 0)) {for (String skipPackage : skipPackages) {if (skipPackage != null) {
判断是不是系统应用
curt.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 //是系统应用
注意:此处只能禁止执行skipPackages中的应用去监听到
BOOT_COMPLETED
后的执行逻辑,如果应用只做了这一个监听来自启,比如我前面写的demo,这样就足够了,但是国内三方app一般会想方设法地自启动,这边验证了秋秋还是会启动起来,会有进程存在,继续处理。
在执行启动时判断其启动的广播接收器
注意:同样需要处理秋秋的同学请一定看到最后,这一节的方案不完善
基于log
ActivityManager: Start proc 2962:com.tencent.mobileqq:MSF/u0a112 for broadcast {com.tencent.mobileqq/com.tencent.mobileqq.msf.core.NetConnInfoCenter}
这里秋秋自己的广播接收器叫com.tencent.mobileqq/com.tencent.mobileqq.msf.core.NetConnInfoCenter
,我们先找到这行log打印的地方
ActivityManager为tag的,在server/am下去grep就好,找到其文件
frameworks\base\services\core\java\com\android\server\am\ProcessList.java
boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,long expectedStartSeq, boolean procAttached) {mPendingStarts.remove(expectedStartSeq);final String reason = isProcStartValidLocked(app, expectedStartSeq);if (reason != null) {Slog.w(TAG_PROCESSES, app + " start not valid, killing pid=" +pid+ ", " + reason);app.pendingStart = false;killProcessQuiet(pid);Process.killProcessGroup(app.uid, app.pid);noteAppKill(app, ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_INVALID_START, reason);return false;}......StringBuilder buf = mStringBuilder;buf.setLength(0);buf.append("Start proc ");buf.append(pid);buf.append(':');buf.append(app.processName);buf.append('/');UserHandle.formatUid(buf, app.startUid);if (app.isolatedEntryPoint != null) {buf.append(" [");buf.append(app.isolatedEntryPoint);buf.append("]");}buf.append(" for ");buf.append(app.hostingRecord.getType());if (app.hostingRecord.getName() != null) {buf.append(" ");buf.append(app.hostingRecord.getName());}
能看到buf.append("Start proc ");
这里开始的buf记录和我们log是一样的,所以后面的app.hostingRecord.getType()
对应log中的广播接收器broadcast
,而app.hostingRecord.getName()
对应log中的{com.tencent.mobileqq/com.tencent.mobileqq.msf.core.NetConnInfoCenter}
那就好处理了,判断其name,如果是NetConnInfoCenter
,那就不允许启动。
代码往前,能看到原生有一个退出的逻辑,通过final String reason = isProcStartValidLocked(app, expectedStartSeq);
赋值
在isProcStartValidLocked
方法中加入秋秋的判断,返回一个reason,这样此次启动能通过原生的逻辑进行拦截,比较安全
diff --git a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
index 9d4deb4d5b..271f99138f 100644
--- a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@@ -2462,6 +2462,14 @@ public final class ProcessList {@GuardedBy("mService")private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {StringBuilder sb = null;
+ if (app.hostingRecord.getName() != null) {
+ String name = app.hostingRecord.getName();
+ Slog.i("ActivityManager", "xumaoxin: broadcast= " + name);
+ if (name.contains("NetConnInfoCenter")) {
+ if (sb == null) sb = new StringBuilder();
+ sb.append("dont allow qq auto start");
+ }
+ }if (app.killedByAm) {if (sb == null) sb = new StringBuilder();sb.append("killedByAm=true;");
编译push验证,秋秋在设备重启后不会再重启,会被拦截
抑制秋秋自启动成功!同时不会影响用户手动点击图标等方式的启动
应用多了可以写成白名单,并配置到xml中
注意:此方案的弊端就是只能对特定的应用单独加判断逻辑,不能适用于所有应用
一棍子打死方案(慎用)
观察三方应用是否都是通过broadcast
类型进行自启动的,能否判断type
是否是broadcast
来进行通用过滤?风险就是这样一来一棍子打死了,等于不再允许三方应用通过广播方式进行启动
diff --git a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
index 9d4deb4d5b..03a4c1ddb2 100644
--- a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@@ -2462,6 +2462,19 @@ public final class ProcessList {@GuardedBy("mService")private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {StringBuilder sb = null;
+ /*if (app.hostingRecord.getName() != null) {
+ String name = app.hostingRecord.getName();
+ Slog.i("ActivityManager", "xumaoxin: broadcast= " + name);
+ if (name.contains("NetConnInfoCenter")) {
+ if (sb == null) sb = new StringBuilder();
+ sb.append("dont allow qq auto start");
+ }
+ }*/
+ if (((app.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) && "broadcast".equals(app.hostingRecord.getType())) {
+ String name = app.hostingRecord.getName();
+ if (sb == null) sb = new StringBuilder();
+ sb.append("dont allow thirdapp auto start by broadcast: " + name);
+ }if (app.killedByAm) {if (sb == null) sb = new StringBuilder();sb.append("killedByAm=true;");
编译后验证秋秋确实是没有问题,主要不确定其他的广播场景会不会被拦截下来,毕竟一棍子打死的办法杀伤面有点大
尽量还是使用第一种+第二种,不让三方应用执行开机广播逻辑+特殊应用特殊过滤。第三种方案慎用!
补充!!!!!!!
对于秋秋前面通过广播想启动的只是其一个子进程,在登陆的时候会用到,如果一直不让其自动启动,会导致登陆超时。
所以还需要加入判断,启动的时候秋秋主进程是否存活,如果存活,我们认为秋秋不是在后台想自启动,而是通过正常途径启动子进程。
而进行是否存活的判断调用较频繁,而我们的系统应用不需要进行此判断,所以调用前再加入是否系统应用的判断。实现代码diff如下
--- a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@@ -2459,14 +2459,27 @@ public final class ProcessList {return success ? app : null;}+ public boolean isAppRunning(String packageName) {
+ List<ActivityManager.RunningAppProcessInfo> runningProcesses = mService.getRunningAppProcesses();
+ if (runningProcesses.size() > 0) {
+ for (ActivityManager.RunningAppProcessInfo info : runningProcesses) {
+ if (info.processName.equals(packageName)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+@GuardedBy("mService")private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {StringBuilder sb = null;// add by sprocomm start
- if (app.hostingRecord.getName() != null) {
+ //非系统应用执行if中的逻辑
+ if (((app.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) && app.hostingRecord.getName() != null) {String name = app.hostingRecord.getName();
- Slog.i("ActivityManager", "xumaoxin: broadcast= " + name);
- if (name.contains("NetConnInfoCenter")) {
+ //秋秋是否存活,这个包名,可以动态到白名单中,和NetConnInfoCenter这个组件名放一起
+ boolean isRunning = isAppRunning("com.tencent.mobileqq");
+ Slog.i("ActivityManager", "xumaoxin: com.tencent.mobileqq isRunning= "+ isRunning + ", broadcast= " + name);
+ if (!isRunning && name.contains("NetConnInfoCenter")) {if (sb == null) sb = new StringBuilder();sb.append("dont allow qq auto start");}
相关文章:
Android11 framework 禁止三方应用开机自启动
Android11应用自启动限制 大纲 Android11应用自启动限制分析验证猜想:Android11 AOSP是否自带禁止三方应用监听BOOT_COMPLETED方案禁止执行非系统应用监听到BOOT_COMPLETED后的代码逻辑在执行启动时判断其启动的广播接收器一棍子打死方案(慎用&#…...
Java | Leetcode Java题解之第263题丑数
题目: 题解: class Solution {public boolean isUgly(int n) {if (n < 0) {return false;}int[] factors {2, 3, 5};for (int factor : factors) {while (n % factor 0) {n / factor;}}return n 1;} }...
将AWS RDS MySQL实例从存储未加密改为加密的方案
问题描述: 因为AWS RDS官方文档【1】中已经明确说明,MySQL RDS的存储为EBS卷,用KMS进行RDS加密有如下限制: 您只能在创建RDS的时候,选择加密。对于已经创建的RDS实例,您无法将为加密的实例,直…...
nginx的配置:TLSv1 TLSv1.1 被暴露不安全
要在 Nginx 配置中禁用不安全的 SSL 协议(如 TLSv1 和 TLSv1.1),并仅启用更安全的协议(如 TLSv1.2 和 TLSv1.3),您可以更新您的 Nginx 配置文件。下面是一个示例配置: # 位于 Nginx 配置文件 (…...
揭开黑箱:目标检测中可解释性的重要性与实现
揭开黑箱:目标检测中可解释性的重要性与实现 在深度学习的目标检测任务中,模型的准确性虽然重要,但模型的决策过程是否透明也同样关键。可解释性(Explainability)是指模型能够为其预测结果提供清晰、可理解的解释。本…...
Mysql高价语句
一.高级语法的查询语句 1.排序语法(默认的排序方式就是升序)。 升序ASC:select * from test01 order by name; 降序DESC:select * from test01 order by name desc; 多个列排序:以多个列作为排序,只有第一…...
ArcGIS Pro SDK (九)几何 6 包络
ArcGIS Pro SDK (九)几何 6 包络 文章目录 ArcGIS Pro SDK (九)几何 6 包络1 构造包络2 构造包络 - 从 JSON 字符串3 合并两个包络4 与两个包络相交5 展开包络6 更新包络的坐标 环境:Visual Studio 2022 .NET6 ArcGI…...
单链表<数据结构 C版>
目录 概念 链表的单个结点 链表的打印操作 新结点的申请 尾部插入 头部插入 尾部删除 头部删除 查找 在指定位置之前插入数据 在任意位置之后插入数据 测试运行一下: 删除pos结点 删除pos之后结点 销毁链表 概念 单链表是一种在物理存储结构上非连续、非顺序…...
监控电脑进程,避免程序在打开前就已经在运行
文章目录 一、文章的目的(适用于windows)二、处理方式三、进程查看的内容在窗口端的演示四、附上代码例子四、通过os.kill的方式,再回到原来的表格时,会出现如下错误提示: 一、文章的目的(适用于windows&am…...
【MySQL进阶篇】存储对象:视图、存储过程及触发器
一、视图 1、介绍 视图(view)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来定义视图的查询中使用的表(基表),并且是在使用视图时动态生成的。 通俗的讲,视图只保存了…...
算法day05 master公式估算递归时间复杂度 归并排序 小和问题 堆排序
2.认识O(NlogN)的排序_哔哩哔哩_bilibili master公式 有这样一个数组:【0,4,2,3,3,1,2】;假设实现了这样一个sort()排序方法, 将数组二分成左右两等分,使用so…...
基于jeecgboot-vue3的Flowable流程仿钉钉流程设计器-支持VForm3表单的选择与支持
因为这个项目license问题无法开源,更多技术支持与服务请加入我的知识星球。 1、初始化的时候加载表单 /** 查询表单列表 */ const getFormList () > {listForm().then(res > formOptions.value res.result.records) } 2、开始节点的修改,增加表…...
【刷题汇总 -- 压缩字符串(一)、chika和蜜柑、 01背包】
C日常刷题积累 今日刷题汇总 - day0181、压缩字符串(一)1.1、题目1.2、思路1.3、程序实现 2、chika和蜜柑2.1、题目2.2、思路2.3、程序实现 3、 01背包3.1、题目3.2、思路3.3、程序实现 -- dp 4、题目链接 今日刷题汇总 - day018 1、压缩字符串(一) 1.1、题目 1.2、思路 读完…...
《Exploring Aligned Complementary Image Pair for Blind Motion Deblurring》
这篇论文的标题《Exploring Aligned Complementary Image Pair for Blind Motion Deblurring》可以翻译为《探索对齐的互补图像对用于盲运动去模糊》。从标题可以推断,论文的焦点在于开发一种算法或技术,利用成对的图像来解决运动模糊问题,特别是在不知道模糊核(即造成模糊…...
vue2学习笔记9 - 通过观察vue实例中的data,理解Vue中的数据代理
接着上一节,学一学vue中的数据代理。学vue这几天,最大的感受就是,名词众多,听得发懵。。不过,深入理解之后,其实说得都是一回事。 在Vue中,数据代理是指在实例化Vue对象时,将data对…...
04 Git与远程仓库
第4章:Git与远程仓库 一、Gitee介绍及创建仓库 一)获取远程仓库 使用在线的代码托管平台,如Gitee(码云)、GitHub等 自行搭建Git代码托管平台,如GitLab 二)Gitee创建仓库 gitee官…...
数据库之表的查询
一.新建表: mysql> create table t_worker(-> department_id int(11) not null comment部门号,-> worker_id int(11) primary key not null comment职工号,-> worker_date date not null comment工作时间,-> wages float(8,2) not null comment工资,…...
String 和StringBuilder字符串操作快慢的举例比较
System.currentTimeMillis(); //当前时间与1970年1月1日午夜UTC之间的毫秒差。public class HelloWorld {public static void main(String[] args) {String s1 "";StringBuilder s2 new StringBuilder("");long time System.currentTimeMillis();long s…...
Java代码基础算法练习-竞猜卡片值-2024.07.22
任务描述: 小米和小王玩竞猜游戏:准备7张卡片包含数字2、3、4、5、6、7、8,从中抽出2张(有 顺序之分,抽2、3跟抽3、2是两种情况),猜2张卡片的和,如果是奇数,则猜对。小米…...
Python爬虫-淘宝搜索热词数据
前言 本文是该专栏的第70篇,后面会持续分享python爬虫干货知识,记得关注。 在本专栏之前,笔者有详细针对“亚马逊Amazon搜索热词”数据采集的详细介绍,对此感兴趣的同学,可以往前翻阅《Python爬虫-某跨境电商(AM)搜索热词》进行查看。 而在本文,笔者将以淘宝为例,获取…...
Leetcode二分搜索法浅析
文章目录 1.二分搜索法1.1什么是二分搜索法?1.2解法思路1.3扩展 1.二分搜索法 题目原文: 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值…...
昇思25天学习打卡营第24天|ResNet50迁移学习
课程打卡凭证 迁移学习 迁移学习是机器学习中一个重要的技术,通过在一个任务上训练的模型来改善在另一个相关任务上的表现。在深度学习中,迁移学习通常涉及在一个大型数据集(如ImageNet)上预训练的模型上进行微调,以便…...
Shell 构建flutter + Navtive 生成IPA
具体实现: #1. 在工程的根目录下,建立文件夹build_iOS文件,在此文件下建立build_iOS.sh的文件,把以下内容copy进sh文件;build_iOS.sh 就是第5步之后整个的脚本内容。 #2. 进入build_iOS.sh 文件的目录; #3. 在build_iOS 文件夹配置打包的DEVELOPExportOptionsPlist…...
python gradio 的输出展示组件
HTML:展示HTML内容,适用于富文本或网页布局。JSON:以JSON格式展示数据,便于查看结构化数据。KeyValues:以键值对形式展示数据。Label:展示文本标签,适用于简单的文本输出。Markdown:…...
SwiftUI 6.0(Xcode 16)新 PreviewModifier 协议让预览调试如虎添翼
概览 用 SwiftUI 框架开发过应用的小伙伴们都知道,SwiftUI 中的视图由各种属性和绑定“扑朔迷离”的缠绕在一起,自成体系。 想要在 Xcode 预览中泰然处之的调试 SwiftUI 视图有时并不是件容易的事。其中,最让人秃头码农们头疼的恐怕就要数如…...
STM32被拔网线 LWIP的TCP无法重连解决方案
目录 一、问题描述 二、项目构成 三、问题解决 1.问题代码 2.解决思路 3.核心代码: 四、完整代码 1.监测网口插入拔出任务 2.TCP任务 3.创建tcp任务 4.删除tcp任务 五、总结 一、问题描述 最近遇到一个问题,就是我的stm32设备作为tcp客户端…...
Linux下开放指定端口
比如需要开放82端口: #查询是否开通 firewall-cmd --query-port82/tcp#开放端口82 firewall-cmd --zonepublic --add-port82/tcp --permanent#重新加载防火墙 firewall-cmd --reload...
亚马逊测评行为的识别与防范:教你如何搭建安全的测评环境
亚马逊平台以其严格的内部系统和精密的买家信息对比机制而闻名。一旦发现买家存在不当评价行为,系统会立即展开深入的调查,追溯其所有的购买和评价记录。如果确认该买家存在补评价的行为,那么他/她之前留下的所有评价都可能会被系统自动删除。…...
如何通过成熟的外发平台,实现文档安全外发管理?
文档安全外发管理是企业信息安全管理的重要组成部分,它涉及到企业向外发送的文件,需要进行严格的控制和管理,防止敏感或机密信息的泄露。以下是一些关键考虑因素: 文件外发的挑战:企业在文件外发时面临的主要挑战包括…...
SCI一区级 | Matlab实现SSA-CNN-GRU-Multihead-Attention多变量时间序列预测
目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【SCI一区级】Matlab实现SSA-CNN-GRU-Multihead-Attention麻雀算法优化卷积门控循环单元融合多头注意力机制多变量时间序列预测,要求Matlab2023版以上; 2.输入多个特征,输出单个…...
discuz可以做商城网站吗/百度下载正版
本文实例讲述了Python多线程及其基本使用方法。分享给大家供大家参考,具体如下: 1.Python中的多线程 执行一个程序,即在操作系统中开启了一个进程,在某一时刻,一个CPU内核只能进行一个进程的任务,现在的计算…...
人民日报客户端跟人民日报的区别/前端seo主要优化哪些
您可插入连续的数字、显式值或重置在 SERIAL、BIGSERIAL 或 SERIAL8 列中值的显式值: 要插入连续的串行值 为 INSERT 语句中的串行列指定零(0)。在此情况下,数据库服务器指定下一最高值。 要插入显式值 首先验证在表中没有重复…...
浙江建设职业学校网站/seo推广培训资料
大家好,这是我的第一篇blog,以前并未发表过相关的文章,那么今天我为什么要写点东西呢?自己也不是很清楚,就是想写点大实话,写日记对于coder一族我想太过于老土了,有那个时间不如去阅读几本好书&…...
集团网站设计案例/宁波seo排名外包
一、内存与线程 1、内存结构 内存是计算机的重要部件之一,它是外存与CPU进行沟通的桥梁,计算机中所有程序的运行都在内存中进行,内存性能的强弱影响计算机整体发挥的水平。JVM的内存结构规定Java程序在执行时内存的申请、划分、使用、回收的管理策略&a…...
用asp.net做的 购物网站视频/营销推广软文案例
水! 判断一下中间部分是否有相邻的,行列边界是否有一样的 【代码】 /* *********************************************** Author :angon************************************************ */ #include <stdio.h> #include <string.h…...
外贸网站模板免费下载/徐汇网站建设
解 决 无 法 修 改 my .ini 文 件 的 问 题 my. i ni —— 》 右 键 “ 属 性 ” —— 》 “ 安 全 ” —— 》 点 击 “ 编 辑 ” —— 》 选 择 你 现 在 登录的账号 —— 》 修 改 你 的 操 作 权 限 ,其 中 包 括 :完 全 控 制 ,修 改 &a…...