Android 系统应用重名install安装失败分析解决

Android 系统应用重名install安装失败分析解决

文章目录

  • Android 系统应用重名install安装失败分析解决
    • 一、前言
      • 1、Android Persistent apps 简单介绍
    • 二、系统 persistent 应用直接安装需求分析解决
      • 1、系统应用安装报错返回的信息
      • 2、分析解决
    • 三、其他
      • 1、persistent系统应用install安装调试小结
      • 2、安装persistent系统应用报错在系统源码中简要分析
        • (1)logcat 过滤查看安装apk相关日志:
        • (2)安装失败报错的具体代码位置
      • 3、Android Studio 直接安装persistent系统应用报错分析处理
        • (1) Android Studio 中弹框显示的错误
      • (2)app\build.gradle 适配
        • (3)修改 applicationId
        • (4)dumpsys package 验证安装的apk
      • 4、Android14 Bluetooth系统蓝牙应用调试
        • (1)查看蓝牙应用的安装目录
        • (2)apex目录apk 无法直接替换!
        • (4)蓝牙应用可以直接install 安装成功
        • (5)dumpsys 查看蓝牙应用安装替换情况
      • 5、系统应用设置 persistent="true" 的作用
      • 5、判断应用是否是persistent类型的系统应用
        • (1)AndroidManifest.xml 代码判断签名和属性
        • (2)应用apk文件反编译分析
        • (3)运行环境dumpsys package分析
      • 6、普通应用设置 persistent="true" 有用吗?

一、前言

系统开发过程中,你会发现一些系统应用编译后无法直接安装成功,为啥?
具体是为啥导致无法正常安装?如果要正常安装需要怎么处理?

刚开始我以为是系统应用重名不能直接安装,但是发现有些系统应用是可以直接安装的;
所以还是要研究看看。

本文简单分析解决一下这个问题!

后面复现关键就是 Android 的 persistent 属性,
persistent(翻译:持久的) 属性是系统应用用来保活的应用和服务的。

声明了 android:persistent="true"的系统应用就表示该应用是持久的,无法进行安装。

这种持久系统应用情况,除了替换apk重启或者编译系统大包,如何才能直接替换安装apk调试呢?

下面进行分析一下。这个对系统应用的调试有一定的帮助作用。

1、Android Persistent apps 简单介绍

Persistent apps(持久化应用)是指那些被标记为具有android:persistent="true"属性的应用;
这个属性是定义的AndroidManifest.xml 的 application 标签中;
这种应用一般是系统应用,该进程在系统运行过程中会被特殊对待,kill掉后马上会被系统拉起;

目前系统一些Persistent apps 应用:

系统核心服务应用:SystemUI,输入法框架
关键通信和同步应用:电话应用,短信应用,同步服务应用
还有一些自定义的关键应用

简单的定义 persistent 属性的代码:

    <applicationandroid:name=".base.MyApplication"...android:persistent="true" //持久化android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/SettingsDialog"tools:replace="android:appComponentFactory">

如果未定义persistent属性,就是默认的false。普通应用都是未定义这个属性的。

如果普通应用定义这个属性为true,会发生什么呢?最后结论有揭晓。

二、系统 persistent 应用直接安装需求分析解决

并不是Android的所有系统应用都是无法install 安装,
有部分应用是可以直接install安装的,
无法直接install安装的应用,除了 persistent 这种情况,
可能还有其他情况,比如版本兼容,版本号定义等情况,下面只是针对persistent这种情况进行分析处理。

1、系统应用安装报错返回的信息

C:\Users\As11040>adb install E:\Android14\311D2\apk\DebugSystemUI\DebugSystemUI.apk
Performing Streamed Install
adb: failed to install E:\Android14\311D2\apk\DebugSystemUI\DebugSystemUI.apk: 
Failure [INSTALL_FAILED_INVALID_APK: Package com.debug.SystemUI is a persistent app. Persistent apps are not updateable.]C:\Users\As11040>

这里可以看到报错提示是:Persistent apps 无法更新。

那咋搞?下面就提供一些调试persistent应用的思路。

2、分析解决

下面给出三种解决方案:

第一种方法(每次重启):系统remount后,替换DebugSystemUI后,重启就会自动安装替换;
第二种方法(不用重启):Android Studio 修改DebugSystemUI的包名,编译这个 应用,修改包名后,就可以安装调试;
第三种方法(重启一次):去除系统应用代码的persistent属性,重新编译,按照第一种方法替换apk后,后面不用修改应用的包名,就可以直接安装替换apk调试。

上面看起来好像没有一种是非常简单的。实际开发中,调试系统应用可能还会更麻烦。

下面对比一下几种调试手段:

第一种调试方法:比较保守,大部分系统开发的都是这样处理的;这种调试方法适用于次数较少,简单代码修改的调试;每次都要重启比较麻烦耗时。第二种调试方法:Android Studio 中重命名应用包名 applicationId "com.debug.settings2",不用修改其他包名相关的地方,就可以直接安装了;这种调试方法适用于次数较多或者复杂的代码修改的调试;但是这种方法不一定适用于所有应用,自定义开发的应用比较好适配,可以直接用Studio编译;有些系统应用不一定能导入到Android Studio中进行编译,或者要适配过程是非常麻烦的;系统应用还有导入系统签名,系统framework包和其他相关包;如果是非常麻烦的情况就没必要搞了,有些情况不一定能搞得定。第三种调试方法:这种方法比较中和;如果既要多次修改,又无法使用Android Studio 进行编译代码的情况;第三种调试方法没有用到Android Studio,源码编译就行。

具体情况,使用具体方式就行调试吧。怎么方便怎么搞就行。

上面其实就是说了一下persistent系统应用无法直接安装,
具体要怎么调试就看当时的调试条件了。

三、其他

1、persistent系统应用install安装调试小结

系统代码中限制了persistent的系统应用无法进行直接安装调试;
大概是因为persistent是一直运行的,无法stop或者kill;
如果要调试安装persistent系统应用,大概有三种方法:

(1)替换系统应用apk,重启
(2)把apk源码弄到Android Studio中,修改包名后,直接安装
(3)去系统应用的persistent属性,替换重启后,后面安装调试就不用每次重启了

第二种方法看起来比较简单,虽然不用remount设备,但是有些大型应用适配是非常麻烦的;
第一种和第三种方法都是要解锁设备,remount后才能执行的;
第三种方法是比较简单方便多次调试的。

2、安装persistent系统应用报错在系统源码中简要分析

上面是解决了调试问题,但是不妨分析一下系统源代码,加深一下印象。

(1)logcat 过滤查看安装apk相关日志:
//这里过来安装或者应用管理相关日志信息
console:/ # logcat | grep -i -E "install|PackageManager"12-10 18:25:08.591 32730 32730 I abb     : StartCommandInProcess(7061636b61676500696e7374616c6c00 package.install. [truncated])
12-10 18:25:08.794   891   955 E PackageManager: No required verifiers
12-10 18:25:08.815   891   955 I PackageManager: Integrity check passed for file:///data/app/vmdl1963375571.tmp
//源码代码中报错的信息:
12-10 18:25:08.828   891   955 W PackageManager: Package com.skg.SystemUI is a persistent app. Persistent apps are not updateable.
//返回到cmd窗口中打印的信息:
12-10 18:25:08.831   891   955 D PackageInstallerSession: Marking session 1963375571 as failed: 
INSTALL_FAILED_INVALID_APK: Package com.skg.SystemUI is a persistent app. Persistent apps are not updateable.

从上面大致可以看到报错的信息,
然后就可以从源码中看看具体发生错误的具体代码位置。

查找过程就不展开说明了,可以源码中grep找到关键字筛选可能的位置。

(2)安装失败报错的具体代码位置

Android14 源码:

framework/base/services/core/java/com/android/server/pm/InstallPackageHelper.java


final class InstallPackageHelper {private final PackageManagerService mPm;...@GuardedBy("mPm.mInstallLock")private void preparePackageLI(InstallRequest request) throws PrepareFailure {final int installFlags = request.getInstallFlags();final boolean onExternal = request.getVolumeUuid() != null;...// Prevent persistent apps from being updatedif (oldPackage.isPersistent()&& ((installFlags & PackageManager.INSTALL_STAGED) == 0)) {throw new PrepareFailure(PackageManager.INSTALL_FAILED_INVALID_APK,"Package " + oldPackage.getPackageName() + " is a persistent app. "+ "Persistent apps are not updateable.");}...

从上面Java代码确实看到了logcat中的报错信息。
上面逻辑看到是安装应用的时候判断了isPersistent()和 installFlags 后就抛出这个异常错误。

isPersistent() 方法很容易理解就是是否定义了 persistent属性的应用;
installFlags 属性应该是一些列属性相关的值,比如是否系统应用,系统签名都是相关的,
这里不继续进行分析,有兴趣的可以看看。

3、Android Studio 直接安装persistent系统应用报错分析处理

这个相当于接上面第二种调试方法展开说明一下。

(1) Android Studio 中弹框显示的错误
Error running 'app' The application could not be installed:
INSTALL_FAILED_INVALID_APK The APKs are invalid. List of apks: [0]
'E:\Studio\project\Android14_311D2\DebugSettings\app\build\intermediates\apk\debug\app-debug.apk

从上面查看并未发现为啥报错,只显示了apk不可用!
哈哈,这种情况咋分析?

其实还得看logcat日志,同样的过滤install|PackageManager是可以看到persistent应用无法替换的错误提示。

这里介绍一下,修改Android Studio 系统应用包名的处理。

(2)app\build.gradle 适配

原本的包名定义:

android {namespace 'com.debug.settings'compileSdk 34defaultConfig {applicationId "com.debug.settings"minSdk 30targetSdk 34versionCode 1versionName "1.0"}//系统签名、证书信息在这里配置}...

上面可以看到有个namespace 和 applicationId 都是定义的应用包名。
其中 namespace 是跟系统资源绑定的,不能随便改,
如果要修改namespace,Java代码里面的定义都要修改,否则会报错;

applicationId 是一个封装的包名,可以随便修改!

(3)修改 applicationId

如果要重新安装这个系统应用的封装包名,修改applicationId 的包名就行:

applicationId "com.debug.settings2"

安装调试发现,会重新生成另外一个 com.debug.settings2 包名的应用,之前的应用是不影响。

(4)dumpsys package 验证安装的apk

同时dumpsys package 查看也是验证查看这个新的包名:


IWB:/ $ dumpsys package com.debug.settings | grep pathpath: /system/priv-app/DebugSettings/DebugSettings.apk
IWB:/ $
IWB:/ $ dumpsys package com.debug.settings2 | grep pathpath: /data/app/~~w3MWD86p2cPawWc2MJun7A==/com.debug.settings2-S3W73_reyyTmvIiB-Vaggg==/base.apkIWB:/ $ dumpsys package com.debug.settings2 | grep versionversionCode=1 minSdk=30 targetSdk=34versionName=3.0
IWB:/ $

从上面日志看,第一次dumps 这个应用的包名和路径是 system 目录的;
安装系统应用后,重新dumpsys 这个应用的包名和路径是data 目录下的;
说明这个系统应用是安装上去的。还可以查看version 或者time 确认。

另外要注意的是:

在Android Studio编译的apk version版本是在app\build.gradle 里面定义使能的,
AndroidManifest.xml定义是没用的,会被覆盖!

4、Android14 Bluetooth系统蓝牙应用调试

蓝牙应用可能调试的人不多,我之前是偶尔要调试的;
但是发现蓝牙apk应用无法替换,因为Android14 开始有些应用是apex目录下的,无法remount这个目录!
所以一般都是编译整个大包进行调试的;
但是通过上面的知识了解后,发现蓝牙apk是可以直接install的,
以前白走了冤枉路,所以有更多知识储备是很有必要的,虽然有时候不一定马上用得上。

下面就是分析系统蓝牙应用的安装替换过程:

(1)查看蓝牙应用的安装目录
console:/ # dumpsys package com.android.bluetooth | grep pathpath: /apex/com.android.btservices/app/Bluetooth@UP1A.231105.001.B2/Bluetooth.apk

蓝牙apk 居然在apex目录!
这个是从Android14 开发才会这样的,有些模块系统放在了apex目录下;

Android13 或者更低的版本都是放在system或者system_ext目录下的。是可以解锁后替换apk的。

调试发现 apex 目录默认是不开放的,无法解锁替换!

(2)apex目录apk 无法直接替换!
C:\Users\As11040>adb root
restarting adbd as rootC:\Users\As11040>adb remount
Verity is already disabled
Remounted /system as RW
Remounted /system_ext as RW
Remounted /system_dlkm as RW
Remounted /vendor as RW
Remounted /product as RW
Remounted /odm as RW
Remounted /vendor_dlkm as RW
Remounted /odm_dlkm as RW
Remounted /oem as RW
Remount succeededC:\Users\As11040>adb shell
IWB:/ # cd /apex/com.android.btservices/app
IWB:/apex/com.android.btservices/app # mkdir aa
mkdir: 'aa': Read-only file system
1|IWB:/apex/com.android.btservices/app #
1|IWB:/apex/com.android.btservices/app # cd ../../..
IWB:/ # cd system/priv-app/
IWB:/system/priv-app # mkdir aa
IWB:/system/priv-app #

上面执行命令代码可以看到即使root和remount,也是无法获取到apex目录的修改权限。
adb push 是试过的,也是报错提示:Read-only file system
没有其他办法的情况,只能编译大包进行调试了。

但是通过上面的persistent知识,获取到了灵感,
感觉可以试试直接install看看是否报错,即使报错也是可以解决的。

####(3)查看蓝牙应用是否是 persistent 应用

系统蓝牙apk应用声明persistent情况:

release\packages\modules\Bluetooth\android\app\AndroidManifest.xml

   <!-- For PBAP Owner Vcard Info --><uses-permission android:name="android.permission.READ_PROFILE"/><application android:name="com.android.bluetooth.btservice.AdapterApp"android:icon="@mipmap/bt_share"android:persistent="false"android:label="@string/app_name"android:supportsRtl="true"android:usesCleartextTraffic="false"android:directBootAware="true"android:defaultToDeviceProtectedStorage="true"android:memtagMode="async">

这里查看蓝牙应用设置persistent为false,那么应该是可以直接安装的。
如果persistent为true,可以设置为false编译一次,后面就可以一直调试。

尝试直接安装是成功的:

(4)蓝牙应用可以直接install 安装成功
C:\Users\As11040>adb install Bluetooth.apk
Performing Streamed Install
Success

成功了,哈哈。

(5)dumpsys 查看蓝牙应用安装替换情况
console:/ # dumpsys package com.android.bluetooth | grep pathpath: /apex/com.android.btservices/app/Bluetooth@UP1A.231105.001.B2/Bluetooth.apkconsole:/ # dumpsys package com.android.bluetooth | grep pathpath: /data/app/~~zptgNMJxOrNyEASJFt3HKg==/com.android.bluetooth-KHInQ7LVcEAHQhjYOSEcJw==/base.apk
console:/ # 

从上面日志看,蓝牙应用确实是从系统应用,变成一个应该普通的install的应用。

这里蓝牙应用 persistent=“false” 是可以直接install 安装的关键。

这里讲解蓝牙只是一个参考,Android14 后面估计还会有很多系统应用会放到apex目录下,
比如nfc等,所以多学掉调试手段是有用的。

5、系统应用设置 persistent=“true” 的作用

确实起到了保活作用,
am force-stop 不会有反应,pid没变;应该是上层拦截了!但是看不到任何相关日志!

kill pid,后应用马上就又被拉起来了。

下面是一些命令调试验证日志:

130|console:/ # 
//(1)查看应用进程情况,包含进程id,父进程,启动时间,应用包名等信息
130|console:/ # ps -eff | grep com.skg.settings
system        6317  5441 0 11:01:28 ?     00:00:02 com.skg.settings//(2)强制停止应用
console:/ # am force-stop com.skg.settings
console:/ # 
//(3))强制停止后,查看进程信息是没有变化的
console:/ # ps -eff | grep com.skg.settings                                    
system        6317  5441 0 11:01:29 ?     00:00:02 com.skg.settings
console:/ # 
//(4)杀死进程id试试
console:/ # kill 6317
console:/ # 
//(5)杀死进程id后,进程是有重新启动的,会生成新的进程id
console:/ # ps -eff | grep com.skg.settings                       
system       20485  5441 10 11:28:12 ?    00:00:00 com.skg.settings
console:/ # 
//(6)杀死父进程id试试
console:/ # kill 5441
console:/ # 
//(7)杀死进程id后,父进程和进程都会重新生成,系统会黑屏一下,估计是系统上层重启了,
//所以最好不要杀父进程,有可能会导致系统重启,或者无法正常开机,一般断开上电可以恢复
console:/ # ps -eff | grep com.skg.settings
system       24353 23431 41 11:34:08 ?    00:00:01 com.skg.settings
console:/ # 

从上面日志看,
am force-stop 是无法停止应用的;
直接kill进程是可以杀死应用,但是马上就会重启启动新的进程;
所以

如果应用有继承Application,可以看到应用重开拉起来的时候有执行onCreate,可以重新初始化自己需要的东西。

上面说了那么多好像没说怎么从非代码手段判断一个应用是是否是 persistent的系统应用。
其实只要有apk或者运行环境,也是可以判断的。

5、判断应用是否是persistent类型的系统应用

下面从三个维度判断这个应用是否是persistent类型的系统应用,
源码下、应用apk文件、运行环境。

(1)AndroidManifest.xml 代码判断签名和属性
1、查看根目录是否声明了系统签名权限:android:sharedUserId="android.uid.system"
2、查看Application 是否声明了:persistent="true"
(2)应用apk文件反编译分析

apk咋判断?其实就是反编译,查看 AndroidManifest.xml 文件,这个和第一个方式类似。
大部分系统文件都是没有经过复杂混淆的,看AndroidManifest里面的基本信息是没啥问题的。

反编译工具命令就不展示了,其实Android Studio 就可以简单反编译,
把apk拖到一个Studio的项目,就会反编译看到AndroidManifest的内容:

简单示例如下:
uid信息:
在这里插入图片描述

persistent信息:
在这里插入图片描述

上面就相当于看到了源码的整个 AndroidManifest 的信息。
声明的权限、Acitivity和Service那些四大组件信息都是有的,想看啥就看啥。

(3)运行环境dumpsys package分析

dumpsys package 可以看到应用的很多具体信息,
比如签名情况,安装时间,安装路径,版本号,应用获取到的权限等信息,persistent 也是可以看到的。

下面是判断判断过滤appid和persistent的示例日志:

//1、查看系统uid签名的应用appid都是1000;flags里面查看是否有 PERSISTENT 属性
console:/ # 
console:/ # dumpsys package com.dubug.settings | grep -i -E "appid|persistent"appId=1000flags=[ SYSTEM DEBUGGABLE HAS_CODE PERSISTENT ALLOW_CLEAR_USER_DATA UPDATED_SYSTEM_APP TEST_ONLY ALLOW_BACKUP ]pkgFlags=[ SYSTEM DEBUGGABLE HAS_CODE PERSISTENT ALLOW_CLEAR_USER_DATA UPDATED_SYSTEM_APP TEST_ONLY ALLOW_BACKUP ]appId=1000appId=1000
console:/ # //2、查看蓝牙应用,可以看到是不是uid签名,其实是bluetooth签名,也没有PERSISTENT属性
console:/ # dumpsys package com.android.bluetooth | grep -i -E "appid|persistent"appId=1002appId=1002appId=1002
console:/ # 
//3、查看一个普通应用,appId id不是1000,有没有PERSISTENT已经不重要了!
console:/ # dumpsys package com.demo.listdemo | grep -i -E "appid|persistent"appId=10070
console:/ # 
console:/ # 
//后面尝试在普通应用加入persistent="true"声明,在apk的flags里面也是未发现有PERSISTENT属性标签,
//说明PERSISTENT属性生效是有一定条件的,比如需要系统签名权限。

6、普通应用设置 persistent=“true” 有用吗?

其实没啥用,我试过了。可以直接安装,,不会安装失败,也不会保活。
这个应该就是 InstallPackageHelper.java里面判断了是否系统应用,否则这个persistent属性没啥意义。

本文只是想说系统应用声明persistent="true"会导致无法直接安装,没想到附带了这么多小知识。

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

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

相关文章

使用Nexus3搭建npm私有仓库

一、npm介绍 npm的全称是Node Package Manager&#xff0c;它是一个开放源代码的命令行工具&#xff0c;用于安装、更新和管理Node.js模块。npm是Node.js的官方模块管理器&#xff0c;它允许用户从一个集中的仓库中下载和安装公共的Node.js模块&#xff0c;并将这些模块集成到…

【ChatGPT】解锁AI思维链:如何让机器像人类一样思考?

在人工智能领域&#xff0c;我们一直在追求让机器像人类一样思考。然而&#xff0c;即使是最先进的AI&#xff0c;也常常被诟病缺乏“常识”&#xff0c;难以理解复杂问题&#xff0c;更不用说像人类一样进行逻辑推理和解决问题了。最经常的表现就是遇到不会的地方&#xff0c;…

蓝桥杯刷题——day5

蓝桥杯刷题——day5 题目一题干解题思路一代码解题思路二代码 题目二题干解题思路代码 题目一 题干 给定n个整数 a1,a2,⋯ ,an&#xff0c;求它们两两相乘再相加的和&#xff0c;即&#xff1a; 示例一&#xff1a; 输入&#xff1a; 4 1 3 6 9 输出&#xff1a; 117 题目链…

监测预警智能分析中心建设项目方案

随着科技的不断进步&#xff0c;地理信息与遥感技术在国家治理、环境保护、灾害预警等领域发挥着越来越重要的作用。监测预警智能分析中心的建设&#xff0c;旨在通过集成先进的遥感技术、地理信息系统&#xff08;GIS&#xff09;、大数据分析和人工智能&#xff08;AI&#x…

【漫话机器学习系列】009.词袋模型(Bag of Words)

词袋模型&#xff08;Bag of Words, 简称 BoW&#xff09; 词袋模型是一种常见的文本表示方法&#xff0c;主要用于自然语言处理&#xff08;NLP&#xff09;和信息检索领域。它将文本数据转换为特征向量&#xff0c;忽略语序&#xff0c;仅考虑词的出现与否或出现频率。 1. 基…

分治算法(单选题)

2-1 分数 2 下列多少种排序算法用了分治法&#xff1f; 堆排序插入排序归并排序快速排序选择排序希尔排序 A.2 B.3 C.4 D.5 正确答案 A 2-2 分数 2 分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题&#xff0c;分别解决问题&#xff0c;最后将子…

UNIX简史

从1991年Linux出现至今&#xff0c;由于众多IT巨头以及技术社区的推动&#xff0c;Linux已经成为非常成熟、可用于各种关键领域的操作系统&#xff0c;适当了解其发展历史&#xff0c;对于理顺其技术流派、从而更好地学习和使用Linux具有重要意义。由于其基于UNIX系统二十多年的…

C# OpenCV机器视觉:畸变矫正

在一个阳光明媚的早晨&#xff0c;阿强决定去拍照。他拿起相机&#xff0c;穿上他最喜欢的羊毛大衣&#xff0c;准备记录下生活中的美好瞬间。可是&#xff0c;当他兴奋地查看照片时&#xff0c;发现自己拍的每一张都像是被外星人用变形金刚的力量扭曲过一样&#xff01;“这是…

tryhackme——Defensive Security Intro(防御安全简介)

任务一&#xff1a;Introduction to Defensive Security防御安全简介 此room的两个要点&#xff1a; Preventing intrusions from occurring 防止入侵发生Detecting intrusions when they occur and responding properly 检测发生的入侵并正确响应 防御安全还有更多内容。 除上…

使用rust语言创建python模块(pyo3+maturin)

1. 首先使用conda创建python虚拟环境&#xff08;已创建的可省略&#xff09; >conda create --prefixE:\python_envs\rust_python python3.11 2. 激活python虚拟环境 conda activate rust_python 3. 安装maturin pip install maturin 4. 创建rust项目 >cd E:\py…

关于Postgresql旧版本安装

抛出问题 局点项目现场&#xff0c;要求对如下三类资产做安全加固&#xff0c;需要在公司侧搭建测试验证环境&#xff0c;故有此篇。 bclinux 8.2 tomcat-8.5.59 postgrel -11 随着PG迭代&#xff0c;老旧版本仅提供有限维护。如果想安装老版本可能就要费劲儿一些。现在&…

使用echarts实现3d柱状图+折线图

以下代码有问题请直接问国内直连GPT/Claude HTML 需要注意threeDchart一定要设置宽度高度&#xff0c;不然图不显示,然后echarts版本不要太低&#xff0c;不然也不显示 <div id"threeDchart" class"threeDchart"></div>js set3DBarChart2(dat…

2024.1212-02-虚拟私人网(VPN) 虚拟局域网 及隧道技术(四)--GRE47 Etherip97 原理及应用

虚拟局域网 及隧道技术&#xff08;四&#xff09;-GRE47 & Etherip97原理及应用 概述原理及应用EOIP/Etherip概念区别 隧道协议标准EtherIP &#xff08;IP protocol number 97&#xff09;GRE 开源工具katlogic-eoip 验证环境GRE&#xff08;EOIP&#xff09;演示验证Eth…

【从零开始入门unity游戏开发之——C#篇01】理论开篇,理解什么是编程

文章目录 前言前置条件进制什么是十进制、二进制二进制有什么用&#xff1f;为什么计算机用二进制而不用十进制&#xff1f;二进制转十进制十进制转二进制二进制运算 计算机中的数据存储单位什么是编程&#xff1f;什么是代码&#xff1f;什么是编程语言&#xff1f;常见的编程…

黑盒白盒测试

任务1 黑盒测试之等价类划分法 【任务需求】 【问题】例&#xff1a;某报表处理系统要求用户输入处理报表的日期&#xff0c;日期限制在2003年1月至2008年12月&#xff0c;即系统只能对该段期间内的报表进行处理&#xff0c;如日期不在此范围内&#xff0c;则显示输入错误信息…

CSS学习记录11

CSS布局 - display属性 display属性是用于控制布局的最终要的CSS属性。display 属性规定是否/如何显示元素。每个HTML元素都有一个默认的display值&#xff0c;具体取决于它的元素类型。大多数元素的默认display值为block 或 inline。 块级元素&#xff08;block element&…

ByteCTF2024

wp参考&#xff1a; 2024 ByteCTF wp 2024 ByteCTF WP- Nepnep ByteCTF 2024 writeup by Arr3stY0u 五冠王&#xff01;ByteCTF 2024 初赛WriteUp By W&M ByteCTF 2024 By W&M - W&M Team ByteCTF Re WP - 吾爱破解 - 52pojie.cn 2024 ByteCTF - BediveRe_R…

C#,在 C# 语言中将 LaTeX 转换为 PNG 或 JPG 图像

在 C 语言中将 LaTeX 转换为 PNG 或 JPG 图像# 12月 28&#xff0c; 2021 2 分钟 法尔汉拉扎 在 C 语言中将 TeX 转换为 PNG JPG 图像# TeX 格式用于处理技术和科学文件。它通常用于交流或发布此类文档。在某些情况下&#xff0c;您可能需要将 TeX 文件渲染为 PNG 或 JPG 等图像…

AI监控赋能健身馆与游泳馆全方位守护,提升安全效率

一、AI视频监控技术的崛起 随着人工智能技术的不断发展&#xff0c;AI视频监控正成为各行业保障安全、提升效率的关键工具。相比传统监控系统&#xff0c;AI技术赋予监控系统实时分析、智能识别和精准预警的能力&#xff0c;让“被动监视”转变为“主动防控”。 二、AI监控应用…

搭建Tomcat(一)---SocketServerSocket

目录 引入1 引入2--socket 流程 Socket&#xff08;应用程序之间的通讯保障&#xff09; 网卡(计算机之间的通讯保障) 端口 端口号 实例 client端 解析 server端 解析 相关方法 问题1&#xff1a;ServerSocket和Socket有什么关系&#xff1f; ServerSocket Soc…