Android之APP更新(通过接口更新)
文章目录
- 前言
- 一、效果图
- 二、实现步骤
- 1.AndroidManifest权限申请
- 2.activity实现
- 3.有版本更新弹框UpdateappUtilDialog
- 4.下载弹框DownloadAppUtils
- 5.弹框背景图
- 总结
前言
对于做Android的朋友来说,APP更新功能再常见不过了,因为平台更新审核时间较长,所以现在很多都会通过接口更新,这里就记录一下吧,欢迎各位讨论。
一、效果图


二、实现步骤
1.AndroidManifest权限申请
<!--外置存储卡写入权限--><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!--请求安装APK的权限--><uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /><!--读取删除SD卡权限--><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!--修改删除SD卡权限--><uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"tools:ignore="ProtectedPermissions" /><uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />//application标签下加如下代码<!-- 安卓7.0安装时需要,拍照需要的临时权限 --><providerandroid:name="androidx.core.content.FileProvider"android:authorities="这里是applicationId也就是包名.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/provider_paths" /></provider>//这里的provider_paths文件放在xml文件下,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<paths><!--拍照需要的路径--><external-pathname="comxf.activity.provider.download"path="." /><external-files-path name="extfiles" path="autoupdatecache/" /><external-cache-path name="extcachs" path="autoupdatecache/" /><cache-path name="intcachs" path="autoupdatecache/" /><paths><external-path path="" name="download"/></paths></paths>
2.activity实现
1.通过接口获取Javabean对象
public Integer id;public String version_name;//App版本名public Integer version_code;//版本编号public String content;//版本更新内容public String is_must_update;//是否需要强更新(0:否,1:是)public String file_url;//app包的下载地址@Overridepublic String toString() {return "VersionUpgradeBean{" +"id=" + id +", version_name='" + version_name + '\'' +", version_code=" + version_code +", content='" + content + '\'' +", is_must_update='" + is_must_update + '\'' +", file_url='" + file_url + '\'' +'}';}
2.获取到版本号后判断是否高于当前版本
if (versionbean.version_code > MyApplication.getVersionCode(this@SetUpActivity)) {val myDialog = UpdateappUtilDialog()myDialog.initDialog(this@SetUpActivity, versionbean)myDialog.buttonClickEvent(object : UpdateappUtilDialog.DialogButtonClick {override fun cilckComfirmButton(view: View?) {myDialog.Dismiss()//6.0才用动态权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(this@SetUpActivity,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {// 申请读写内存卡内容的权限ActivityCompat.requestPermissions(this@SetUpActivity, arrayOf(Manifest.permission.`WRITE_EXTERNAL_STORAGE`), 123)} else {//授权成功if (FileUtils.createOrExistsDir(NetConst.baseFileName)) {val mUpdateManger = DownloadAppUtils(this@SetUpActivity, versionbean.file_url, versionbean)mUpdateManger.checkUpdateInfo()}}} else {//授权成功if (FileUtils.createOrExistsDir(NetConst.baseFileName)) {val mUpdateManger = DownloadAppUtils(this@SetUpActivity, versionbean.file_url, versionbean)mUpdateManger.checkUpdateInfo()}}}override fun cilckCancleButton(view: View?) {//点击取消按钮myDialog.Dismiss()}})}
3.用户权限结果处理
/*** todo 对用户权限授予结果处理** @param requestCode 权限要求码,即我们申请权限时传入的常量 如: TAKE_PHOTO_PERMISSION_REQUEST_CODE* @param permissions 保存权限名称的 String 数组,可以同时申请一个以上的权限* @param grantResults 每一个申请的权限的用户处理结果数组(是否授权)*/override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<String?>,grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)when (requestCode) {123 -> {//授权成功if (FileUtils.createOrExistsDir(NetConst.baseFileName)) {val mUpdateManger = DownloadAppUtils(this@SetUpActivity, versionbean.file_url, versionbean)mUpdateManger.checkUpdateInfo()}}}}
3.有版本更新弹框UpdateappUtilDialog
1.util代码
/*** Created by :caoliulang* ❤* Creation time :2025/2/24* ❤* Function :更新app的Dialog*/
public class UpdateappUtilDialog {private TextView secondBtn, textvs;private ImageView tv_cancel;private AlertDialog alertDialog;private DialogButtonClick mClick;private TextView tv_desc;public interface DialogButtonClick {void cilckComfirmButton(View view);void cilckCancleButton(View view);}public void buttonClickEvent(DialogButtonClick bc) {if (bc != null) {mClick = bc;cilckEvent();}}public void initDialog(Context context, VersionUpgradeBean upbean) {alertDialog = new AlertDialog.Builder(context).create();alertDialog.show();alertDialog.setCancelable(false);//调用这个方法时,按对话框以外的地方不起作用。返回键 不作用
// alertDialog.setCanceledOnTouchOutside(false);//调用这个方法时,按对话框以外的地方不起作用。返回键 有作用Window window = alertDialog.getWindow();window.setContentView(R.layout.fragment_update_app);window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));tv_desc = window.findViewById(R.id.tv_desc);tv_desc.setText(upbean.content);secondBtn = window.findViewById(R.id.tv_ok);textvs = window.findViewById(R.id.textvs);textvs.setText(upbean.version_name);tv_cancel = window.findViewById(R.id.tv_cancel);//1不强制更新 2 强制更新
// if(upbean.getUpdateType().equals("2")){
// firstBtn.setVisibility(View.GONE);
// }// //不关闭弹窗也能点击外部事件
// alertDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);String isqg = upbean.is_must_update + "";if (isqg.equals("true")) {tv_cancel.setVisibility(View.GONE);} else {tv_cancel.setVisibility(View.VISIBLE);}}public void cilckEvent() {
// if (firstBtn != null) {
// firstBtn.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// alertDialog.dismiss();
// mClick.cilckCancleButton(v);
// }
// });secondBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {
// alertDialog.dismiss();mClick.cilckComfirmButton(v);}});tv_cancel.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {mClick.cilckCancleButton(view);}});
// }}public void Dismiss() {if (null != alertDialog) {alertDialog.dismiss();}}}
2.xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#01000000"android:gravity="center"android:orientation="vertical"><RelativeLayoutandroid:layout_width="301dp"android:layout_height="400dp"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_top"android:layout_width="match_parent"android:layout_height="match_parent"android:src="@mipmap/lib_update_app_top_bg" /><TextViewandroid:id="@+id/textname"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="16dp"android:layout_marginTop="55dp"android:text="@string/Newversionfound"android:textColor="#2e2e2e"android:textSize="18dp"android:textStyle="bold" /><TextViewandroid:id="@+id/textvs"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/textname"android:layout_marginLeft="16dp"android:layout_marginTop="5dp"android:text="1.0.0"android:textColor="#2e2e2e"android:textSize="16dp"android:textStyle="bold" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="210dp"android:layout_marginTop="180dp"android:orientation="vertical"><!--这个地方需要设置可以滚动--><ScrollViewandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:paddingTop="18dp"android:paddingBottom="5dp"android:scrollbars="none"><TextViewandroid:id="@+id/tv_desc"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:layout_marginRight="20dp"android:lineSpacingExtra="5dp"android:text="1.已知bug修复;\n2.新功能增加;\n3.性能优化;"android:textColor="@android:color/black"android:textSize="14dp" /></ScrollView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:layout_marginRight="20dp"android:layout_marginBottom="20dp"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_ok"android:layout_width="match_parent"android:layout_height="44dp"android:background="@drawable/jianbianlanse"android:gravity="center"android:text="@string/UPDATENOW"android:textColor="#ffffff"android:textSize="18dp" /></LinearLayout></LinearLayout></RelativeLayout><ImageViewandroid:id="@+id/tv_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="15dp"android:src="@mipmap/ico_sjgb" /></LinearLayout>
4.下载弹框DownloadAppUtils
1.util代码如下
*** Created by :caoliulang* ❤* Creation time :2024/2/24* ❤* Function :APP更新下载*/
public class DownloadAppUtils {// 应用程序Contextpublic static Activity mContext;private static final String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "tdzr/Download/";// 保存apk的文件夹///storage/emulated/0/tdzr/Download/aidigital1.0.4.apkprivate static final String saveFileName = savePath + "aidigital" + MyApplication.versionname + ".apk";// 进度条与通知UI刷新的handler和msg常量private ProgressBar mProgress;private TextView text_progress, textvs;private static final int DOWN_UPDATE = 1;private static final int DOWN_OVER = 2;private static final int INT_NOT = 9;private String downlogdurl;//下载地址private int progress = 0;// 当前进度private Thread downLoadThread; // 下载线程private boolean interceptFlag = false;// 用户取消下载private AlertDialog dialog;private VersionUpgradeBean upbean;// 通知处理刷新界面的handler@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {@SuppressLint("HandlerLeak")@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case DOWN_UPDATE:mProgress.setProgress(progress); //设置第一进度text_progress.setText(progress + "%");break;case DOWN_OVER:
// //1不强制更新 2 强制更新
// if(upbean.getUpdateType().equals("1")){
// dialog.dismiss();
// }dialog.dismiss();installApk();break;case INT_NOT:dialog.dismiss();FileUtils.deleteFile(saveFileName);//删除文件ToastUtils.showToast(mContext.getResources().getString(R.string.Networkconnectionfailed));break;}super.handleMessage(msg);}};public DownloadAppUtils(Activity context, String downlogdurl, VersionUpgradeBean upbean) {this.mContext = context;this.downlogdurl = downlogdurl;this.upbean = upbean;System.out.println("过来了--1");}// 显示更新程序对话框,供主程序调用public void checkUpdateInfo() {//判断本地是否存在已下载的apk(有bug)
// if (FileUtils.isFileExists(saveFileName) == true) {
// //安装
// installApk();
// } else {
// //下载
// showDownloadDialog();
// }//判断本地是否存在已下载的apkif (FileUtils.isFileExists(saveFileName) == true) {//删除DeletFile.delete(savePath);}//下载showDownloadDialog();}//弹出更新进度条private void showDownloadDialog() {dialog = new AlertDialog.Builder(mContext).create();dialog.show();dialog.setCancelable(false);View viewt = View.inflate(mContext, R.layout.xiazai_two_dialog, null);Window window = dialog.getWindow();window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));dialog.setContentView(viewt);mProgress = viewt.findViewById(R.id.upprogressBar);text_progress = viewt.findViewById(R.id.text_progress);text_progress.setText("0%");textvs = viewt.findViewById(R.id.textvs);textvs.setText(upbean.version_name);ImageView tv_cancel = viewt.findViewById(R.id.tv_cancel);String isqg = upbean.is_must_update + "";if (isqg.equals("true")) {tv_cancel.setVisibility(View.GONE);} else {tv_cancel.setVisibility(View.VISIBLE);}tv_cancel.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {FileUtils.deleteFile(saveFileName);//删除文件dialog.dismiss();interceptFlag = true;}});downloadApk();}//安装apkprivate static void installApk() {File apkfile = new File(saveFileName);if (!apkfile.exists()) {return;}Intent intent = new Intent(Intent.ACTION_VIEW);//版本在7.0以上是不能直接通过uri访问的if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {// 由于没有在Activity环境下启动Activity,设置下面的标签intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致 参数3 共享的文件Uri apkUri = FileProvider.getUriForFile(mContext, "这里是applicationId也就是包名.fileprovider", apkfile);//添加这一句表示对目标应用临时授权该Uri所代表的文件intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.setDataAndType(apkUri, "application/vnd.android.package-archive");} else {intent.setDataAndType(Uri.fromFile(new File(saveFileName)),"application/vnd.android.package-archive");}mContext.startActivity(intent);}//下载apkprivate void downloadApk() {System.out.println("url打印:" + downlogdurl);downLoadThread = new Thread(mdownApkRunnable);downLoadThread.start();}private Runnable mdownApkRunnable = new Runnable() {@Overridepublic void run() {System.out.println("打印路径:" + saveFileName);URL url;try {url = new URL(downlogdurl);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setConnectTimeout(15000); //设置连接超时为15sconn.setReadTimeout(15000); //读取数据超时也是15sint code = conn.getResponseCode();System.out.println("code打印:" + code);if (code == 200) {conn.connect();int length = conn.getContentLength();InputStream ins = conn.getInputStream();if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {Toast.makeText(mContext, "SD卡不可用~", Toast.LENGTH_SHORT).show();return;}File file = new File(savePath);if (!file.exists()) {file.mkdir();}String apkFile = saveFileName;File ApkFile = new File(apkFile);if (!ApkFile.exists()) {ApkFile.createNewFile();}FileOutputStream outStream = new FileOutputStream(ApkFile);int count = 0;byte buf[] = new byte[1024];do {int numread = ins.read(buf);count += numread;int s = (int) (((float) count / length) * 100);if (progress != s) {progress = (int) (((float) count / length) * 100);// 下载进度mHandler.sendEmptyMessage(DOWN_UPDATE);}if (numread <= 0) {// 下载完成通知安装mHandler.sendEmptyMessage(DOWN_OVER);break;}outStream.write(buf, 0, numread);} while (!interceptFlag);// 点击取消停止下载outStream.close();ins.close();} else {mHandler.sendEmptyMessage(INT_NOT);}} catch (Exception e) {//这里报错因为路径不对,正确路径storage/emulated/0/tdzr/Download/aidigital1.0.4.apkSystem.out.println("code打印:---" + e.toString());mHandler.sendEmptyMessage(INT_NOT);}}};
2.下载弹框xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#01000000"android:gravity="center"android:orientation="vertical"><RelativeLayoutandroid:layout_width="301dp"android:layout_height="400dp"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><ImageViewandroid:id="@+id/topimg"android:layout_width="match_parent"android:layout_height="match_parent"android:src="@mipmap/lib_update_app_top_bg" /><TextViewandroid:id="@+id/textname"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="16dp"android:layout_marginTop="55dp"android:text="@string/Newversionfound"android:textColor="#2E2E2E"android:textSize="18dp"android:textStyle="bold" /><TextViewandroid:id="@+id/textvs"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/textname"android:layout_marginLeft="16dp"android:layout_marginTop="5dp"android:text="1.0.0"android:textColor="#2E2E2E"android:textSize="16dp"android:textStyle="bold" /></RelativeLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="250dp"android:gravity="center_horizontal"android:orientation="vertical"><TextViewandroid:id="@+id/text_progress"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="0%"android:textColor="#2e2e2e"android:textSize="16dp"android:textStyle="bold" /><ProgressBarandroid:id="@+id/upprogressBar"style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"android:layout_width="match_parent"android:layout_height="18dp"android:layout_marginStart="15dp"android:layout_marginTop="15dp"android:layout_marginEnd="15dp"android:layout_marginBottom="15dp"android:max="100"android:progress="0"android:progressDrawable="@drawable/progressbar_h" /></LinearLayout></RelativeLayout><ImageViewandroid:id="@+id/tv_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="15dp"android:src="@mipmap/ico_sjgb" />
</LinearLayout>
3.progressbar_h(在drawable下新建文件)
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@android:id/background"android:gravity="center_vertical|fill_horizontal"><shape android:shape="rectangle"><size android:height="20dp" /><solid android:color="#E4E4E4" /><corners android:radius="10dp" /></shape></item><!--第二进度条--><itemandroid:id="@android:id/secondaryProgress"android:gravity="center_vertical|fill_horizontal"><scale android:scaleWidth="100%"><shape android:shape="rectangle"><size android:height="20dp" /><solid android:color="#E4E4E4" /><corners android:radius="10dp" /></shape></scale></item><!--第一进度条--><itemandroid:id="@android:id/progress"android:gravity="center_vertical|fill_horizontal"><scale android:scaleWidth="100%"><shape android:shape="rectangle"><size android:height="20dp" /><solid android:color="#217FFD" /><corners android:radius="10dp" /></shape></scale></item></layer-list>
5.弹框背景图

总结
其实这功能挺简单的,就是里面细节太多,首先AndroidManifest加权限,还要加provider,provider里面记得更改包名,下载util里面的报名也是一样。其次判断版本是否更新,最后更新下载安装即可,得吃。
相关文章:
Android之APP更新(通过接口更新)
文章目录 前言一、效果图二、实现步骤1.AndroidManifest权限申请2.activity实现3.有版本更新弹框UpdateappUtilDialog4.下载弹框DownloadAppUtils5.弹框背景图 总结 前言 对于做Android的朋友来说,APP更新功能再常见不过了,因为平台更新审核时间较长&am…...
JVM生产环境问题定位与解决实战(二):JConsole、VisualVM到MAT的高级应用
生产问题定位指南:几款必备的可视化工具 引言 在上一篇文章中,详细的介绍了JDK自带的一系列命令行工具,,如jps、jmap、jstat、jstack以及jcmd等,这些工具为排查和诊断Java虚拟机(JVM)问题提供…...
wsl2安装的ext4.vhdx瘦身、打包、导入
1.清理APT缓存: Ubuntu使用APT进行软件包管理,它会在安装过程中保留下载的软件包。清理这些缓存可以释放空间: sudo apt-get clean2.删除不必要的软件包: 删除不再需要的软件包和它们的依赖项: sudo apt-get autoremove3.压缩磁盘空间 ex…...
力扣3102.最小化曼哈顿距离
力扣3102.最小化曼哈顿距离 题目 题目解析及思路 题目要求返回移除一个点后的最小的最大曼哈顿距离 最大最小值的题一般直接想到二分 本题有一个简单办法就是利用切比雪夫距离 当正方形转45,即边上点**( x , y ) -> (x y , y - x)时,两点间max(…...
国标28181协议在智联视频超融合平台中的接入方法
一. 国标28181介绍 国标 28181 协议全称是《安全防范视频监控联网系统信息传输、交换、控制技术要求》,是国内视频行业最重要的国家标准,目前有三个版本: 2011 年:推出 GB/T 28181-2011 版本,为安防行业的前端设备、平…...
【学习笔记】LLM+RL
文章目录 1 合成数据与模型坍缩(model collapse),1.1 递归生成数据与模型坍缩1.2 三种错误1.3 理论直觉1.4 PPL指标 2 基于开源 LLM 实现 O1-like step by step 慢思考(slow thinking),ollama,streamlit2.1…...
Linux故障排查和性能优化面试题及参考答案
目录 如何查看 Linux 系统中的 CPU、内存、磁盘等资源使用情况? 什么是 Linux 中的负载(Load Average)?如何解读它? 如何通过 top 和 htop 命令监控系统性能? 如何使用 mpstat 命令来查看 CPU 的利用情况? 如何分析系统 CPU 瓶颈? 如何分析 CPU 瓶颈?如何优化 CP…...
【论文精读】YOLO-World:实时开放词汇目标检测
论文地址: YOLO-World: Real-Time Open-Vocabulary Object Detection 源代码:YOLO-World 摘要 YOLO系列检测器因其高效性和实用性而被广泛认可。然而,它们依赖于预定义和训练过的物体类别,这限制了其在开放场景中的适用性。为了…...
【AI时代】可视化训练模型工具LLaMA-Factory安装与使用
文章目录 安装训练使用 安装 官方地址:https://github.com/hiyouga/LLaMA-Factory 创建虚拟环境 conda create -n llama-factory conda activate llama-factory安装 git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip in…...
Docker 部署 OnlyOffice 文档服务器
Docker 部署 OnlyOffice 文档服务器 前言一、准备工作二、设置变量和目录结构三、创建并运行 OnlyOffice 容器四、访问 OnlyOffice 文档服务器五、配置和管理总结 前言 OnlyOffice 是一个强大的开源文档编辑平台,支持文档、表格、演示文稿等文件格式的编辑。通过 D…...
将产品照片(form.productPhotos)转为 JSON 字符串发送给后端
文章目录 1. 前端 form.productPhotos 的当前处理a. 组件绑定b. 当前发送逻辑 2. 如何将 form.productPhotos 转为 JSON 字符串发送给后端a. 修改前端 save() 方法b. 确保 esave API 支持接收字符串 基于你提供的 identify-form.vue 代码,我将分析如何将产品照片&a…...
【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin scatter plot Venn)
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载画图1画图2画图3画图4画图5画图6画图7参考介绍 【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin & scatter plot & Venn) 加载R包 library…...
kotlin 知识点一 变量和函数
在Kotlin中定义变量的方式和Java 区别很大,在Java 中如果想要定义一个变 量,需要在变量前面声明这个变量的类型,比如说int a表示a是一个整型变量,String b表 示b是一个字符串变量。而Kotlin中定义一个变量,只允许在变量…...
科普:你的笔记本电脑中有三个IP:127.0.0.1、无线网 IP 和局域网 IP;两个域名:localhost和host.docker.internal
三个IP 你的笔记本电脑中有三个IP:127.0.0.1、无线网 IP 和局域网 IP。 在不同的场景下,需要选用不同的 IP 地址,如下为各自的特点及适用场景: 127.0.0.1(回环地址) 特点 127.0.0.1 是一个特殊的 IP 地…...
solidity之Foundry安装配置(一)
一门面向合约的高级编程语言,主要用来编写以太坊只能合约。 Solidity受C语言,Python和js影响,但为编译成为以太坊虚拟机字节码在EVM上执行,很多特性和限制都和EVM相关。 Solidity 是静态类型语言,支持继承、库、自定义…...
爬虫解析库:parsel的详细使用
文章目录 1. 安装 Parsel2. 基本用法3. 使用 CSS 选择器提取数据4. 使用 XPath 提取数据5. 链式调用6. 正则表达式提取7. 处理嵌套元素8. 处理默认值9. 结合 Requests 使用10. 处理复杂 HTML11. 性能优化12. 注意事项 引言:本博客详细介绍爬虫解析库parser的详细使用…...
PHP-create_function
[题目信息]: 题目名称题目难度PHP-create_function2 [题目考点]: create_function ( string args , string args , string code )[Flag格式]: SangFor{wWx5dEGHHhDUwmST4bpXwfjSzq43I6cz}[环境部署]: docker-compose.yml文件或者docker …...
从工程师到系统架构设计师
在技术领域,从一名初出茅庐的工程师成长为独当一面的系统架构设计师,是一条需要长期积累、持续突破的路径。这一过程不仅需要扎实的技术功底,更需要思维的升级和视野的拓展。以下将结合不同阶段的特征,为你梳理一条清晰的成长路线…...
FFmpeg 是什么?为什么?怎么用?
摘要:本文介绍了 FFmpeg,一个功能强大的开源多媒体处理工具,广泛应用于视频和音频文件的处理。FFmpeg 支持多种多媒体格式,能够实现视频编码/解码、格式转换、裁剪、合并、音频提取、流媒体处理等功能。本文详细阐述了 FFmpeg 的主…...
云计算及其他计算
云计算知识思维导图:https://kdocs.cn/l/cpl2Kizx7IyC 云计算的核心判断标准通常基于美国国家标准与技术研究院(NIST)的定义,并结合实际应用场景。以下是判断一个服务是否为云计算的关键标准,以及对应的服务类型&#…...
前端Toast提示快速入门
White graces:个人主页 🙉专栏推荐:Java入门知识🙉 🐹今日诗词:十年一觉扬州梦,赢得青楼薄幸名🐹 ⛳️点赞 ☀️收藏⭐️关注💬卑微小博主🙏 ⛳️点赞 ☀️收藏⭐️关注Ǵ…...
体育电竞比分网开发流程
开发一个体育电竞比分网的流程可以分为以下几个主要步骤: 1. 需求分析 目标用户:确定网站的主要用户群体,如体育迷、电竞爱好者等。 功能需求:列出网站需要实现的功能,如实时比分更新、赛事日程、新闻资讯、用户评论…...
垂类大模型微调(一):认识LLaMA-Factory
LlamaFactory 是一个专注于 高效微调大型语言模型(LLMs) 的开源工具框架,尤其以支持 LLaMA(Meta 的大型语言模型系列)及其衍生模型(如 Chinese-LLaMA、Alpaca 等)而闻名。它的目标是简化模型微调流程,降低用户使用门槛; 官方文档 一、介绍 高效微调支持 支持多种微调…...
Opengl常用缓冲对象功能介绍及使用示例(C++实现)
本文整理了常用的opengl缓冲区对象并安排了使用示例 名称英文全称作用简述顶点数组对象Vertex Array Object (VAO)管理 VBO 和 EBO 的配置,存储顶点属性设置,简化渲染流程,避免重复设置状态顶点缓冲区对象Vertex Buffer Object (VBO)存储顶点…...
【量化策略】均值回归策略
【量化策略】均值回归策略 🚀量化软件开通 🚀量化实战教程 技术背景与应用场景 在金融市场中,均值回归策略是一种基于统计学原理的量化交易策略。该策略的核心思想是,资产价格和收益率最终都会回归到其长期平均值或趋势线。这…...
【CS285】高斯策略对数概率公式的学习笔记
公式介绍 在【CS285】中提到了高斯策略对数概率公式的公式如下: log π θ ( a t ∣ s t ) − 1 2 ∥ f ( s t ) − a t ∥ Σ 2 const \log \pi_{\theta}(\mathbf{a}_t | \mathbf{s}_t) -\frac{1}{2} \left\| f(\mathbf{s}_t) - \mathbf{a}_t \right\|_{\S…...
C++双指针:算法优化的“左右互搏术”与高效问题破解全指南
C双指针:算法优化的“左右互搏术”与高效问题破解全指南 开篇故事:迷宫中的“双人探路策略” 想象两名探险者在迷宫中寻找出口: 快慢指针:一人快速探索死路,另一人稳步记录正确路径。左右指针:两人从两端…...
高级SQL技术在Python项目中的应用:ORM与深度性能优化
引言 在现代Python项目开发中,数据库交互远不止是数据的简单存取,它已成为构建高性能、可维护应用的核心瓶颈和关键能力所在。 仅仅依赖基础SQL查询,虽然入门简单,却难以应对日益增长的应用挑战。这些挑战主要体现在以下几个方面: 性能瓶颈: 数据量剧增: 从百万到数十亿乃…...
Pytorch实现论文:基于多尺度融合生成对抗网络的水下图像增强
简介 简介:提出了一种新型的水下图像增强算法,基于多尺度融合生成对抗网络,名为UMSGAN,以解决低对比度和颜色失真的问题。首先经过亮度的处理,将处理后的图像输入设计的MFFEM模块和RM模块生成图像。该算法旨在适应各种水下场景,提供颜色校正和细节增强。 论文题目:Und…...
从单片机的启动说起一个单片机到点灯发生了什么下——使用GPIO点一个灯
目录 前言 HAL库对GPIO的抽象 核心分析:HAL_GPIO_Init 前言 我们终于到达了熟悉的地方,对GPIO的初始化。经过漫长的铺垫,我们终于历经千辛万苦,来到了这里。关于GPIO的八种模式等更加详细的细节,由于只是点个灯&am…...
