Android之APP更新(通过接口更新)

news2025/4/5 18:20:42

文章目录

  • 前言
  • 一、效果图
  • 二、实现步骤
    • 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-permission
        android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
        tools:ignore="ProtectedPermissions" />
    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
    //application标签下加如下代码
     <!-- 安卓7.0安装时需要,拍照需要的临时权限 -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="这里是applicationId也就是包名.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

//这里的provider_paths文件放在xml文件下,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!--拍照需要的路径-->
    <external-path
        name="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包的下载地址

    @Override
    public 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() {
            @Override
            public void onClick(View v) {
//                    alertDialog.dismiss();
                mClick.cilckComfirmButton(v);
            }
        });
        tv_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public 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">


    <RelativeLayout
        android:layout_width="301dp"
        android:layout_height="400dp"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/iv_top"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@mipmap/lib_update_app_top_bg" />

        <TextView
            android: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" />

        <TextView
            android: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" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="210dp"
            android:layout_marginTop="180dp"
            android:orientation="vertical">


            <!--这个地方需要设置可以滚动-->
            <ScrollView
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:paddingTop="18dp"
                android:paddingBottom="5dp"
                android:scrollbars="none">

                <TextView
                    android: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>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:layout_marginRight="20dp"
                android:layout_marginBottom="20dp"
                android:orientation="horizontal">

                <TextView
                    android: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>

    <ImageView
        android: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
 ** FunctionAPP更新下载
 */
public class DownloadAppUtils {
    // 应用程序Context
    public static Activity mContext;
    private static final String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "tdzr/Download/";// 保存apk的文件夹
    ///storage/emulated/0/tdzr/Download/aidigital1.0.4.apk
    private 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")
        @Override
        public 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();
//        }

        //判断本地是否存在已下载的apk
        if (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() {
            @Override
            public void onClick(View v) {
                FileUtils.deleteFile(saveFileName);//删除文件
                dialog.dismiss();
                interceptFlag = true;
            }
        });
        downloadApk();
    }

    //安装apk
    private 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);
    }


    //下载apk
    private void downloadApk() {
        System.out.println("url打印:" + downlogdurl);
        downLoadThread = new Thread(mdownApkRunnable);
        downLoadThread.start();
    }

    private Runnable mdownApkRunnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("打印路径:" + saveFileName);
            URL url;
            try {
                url = new URL(downlogdurl);
                HttpURLConnection conn = (HttpURLConnection) url
                        .openConnection();
                conn.setConnectTimeout(15000);  //设置连接超时为15s
                conn.setReadTimeout(15000);     //读取数据超时也是15s
                int 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.apk
                System.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">

    <RelativeLayout
        android:layout_width="301dp"
        android:layout_height="400dp"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/topimg"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@mipmap/lib_update_app_top_bg" />

            <TextView
                android: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" />

            <TextView
                android: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>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="250dp"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android: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" />

            <ProgressBar
                android: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>

    <ImageView
        android: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">

    <item
        android: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>

<!--第二进度条-->
    <item
        android: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>
    <!--第一进度条-->
    <item
        android: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里面的报名也是一样。其次判断版本是否更新,最后更新下载安装即可,得吃。

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

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

相关文章

JVM生产环境问题定位与解决实战(二):JConsole、VisualVM到MAT的高级应用

生产问题定位指南&#xff1a;几款必备的可视化工具 引言 在上一篇文章中&#xff0c;详细的介绍了JDK自带的一系列命令行工具&#xff0c;&#xff0c;如jps、jmap、jstat、jstack以及jcmd等&#xff0c;这些工具为排查和诊断Java虚拟机&#xff08;JVM&#xff09;问题提供…

力扣3102.最小化曼哈顿距离

力扣3102.最小化曼哈顿距离 题目 题目解析及思路 题目要求返回移除一个点后的最小的最大曼哈顿距离 最大最小值的题一般直接想到二分 本题有一个简单办法就是利用切比雪夫距离 当正方形转45&#xff0c;即边上点**( x , y ) -> (x y , y - x)时&#xff0c;两点间max(…

国标28181协议在智联视频超融合平台中的接入方法

一. 国标28181介绍 国标 28181 协议全称是《安全防范视频监控联网系统信息传输、交换、控制技术要求》&#xff0c;是国内视频行业最重要的国家标准&#xff0c;目前有三个版本&#xff1a; 2011 年&#xff1a;推出 GB/T 28181-2011 版本&#xff0c;为安防行业的前端设备、平…

【学习笔记】LLM+RL

文章目录 1 合成数据与模型坍缩&#xff08;model collapse&#xff09;,1.1 递归生成数据与模型坍缩1.2 三种错误1.3 理论直觉1.4 PPL指标 2 基于开源 LLM 实现 O1-like step by step 慢思考&#xff08;slow thinking&#xff09;&#xff0c;ollama&#xff0c;streamlit2.1…

【论文精读】YOLO-World:实时开放词汇目标检测

论文地址&#xff1a; YOLO-World: Real-Time Open-Vocabulary Object Detection 源代码&#xff1a;YOLO-World 摘要 YOLO系列检测器因其高效性和实用性而被广泛认可。然而&#xff0c;它们依赖于预定义和训练过的物体类别&#xff0c;这限制了其在开放场景中的适用性。为了…

【AI时代】可视化训练模型工具LLaMA-Factory安装与使用

文章目录 安装训练使用 安装 官方地址&#xff1a;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…

将产品照片(form.productPhotos)转为 JSON 字符串发送给后端

文章目录 1. 前端 form.productPhotos 的当前处理a. 组件绑定b. 当前发送逻辑 2. 如何将 form.productPhotos 转为 JSON 字符串发送给后端a. 修改前端 save() 方法b. 确保 esave API 支持接收字符串 基于你提供的 identify-form.vue 代码&#xff0c;我将分析如何将产品照片&a…

【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin scatter plot Venn)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载画图1画图2画图3画图4画图5画图6画图7参考介绍 【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin & scatter plot & Venn) 加载R包 library…

kotlin 知识点一 变量和函数

在Kotlin中定义变量的方式和Java 区别很大&#xff0c;在Java 中如果想要定义一个变 量&#xff0c;需要在变量前面声明这个变量的类型&#xff0c;比如说int a表示a是一个整型变量&#xff0c;String b表 示b是一个字符串变量。而Kotlin中定义一个变量&#xff0c;只允许在变量…

solidity之Foundry安装配置(一)

一门面向合约的高级编程语言&#xff0c;主要用来编写以太坊只能合约。 Solidity受C语言&#xff0c;Python和js影响&#xff0c;但为编译成为以太坊虚拟机字节码在EVM上执行&#xff0c;很多特性和限制都和EVM相关。 Solidity 是静态类型语言&#xff0c;支持继承、库、自定义…

PHP-create_function

[题目信息]&#xff1a; 题目名称题目难度PHP-create_function2 [题目考点]&#xff1a; create_function ( string args , string args , string code )[Flag格式]: SangFor{wWx5dEGHHhDUwmST4bpXwfjSzq43I6cz}[环境部署]&#xff1a; docker-compose.yml文件或者docker …

FFmpeg 是什么?为什么?怎么用?

摘要&#xff1a;本文介绍了 FFmpeg&#xff0c;一个功能强大的开源多媒体处理工具&#xff0c;广泛应用于视频和音频文件的处理。FFmpeg 支持多种多媒体格式&#xff0c;能够实现视频编码/解码、格式转换、裁剪、合并、音频提取、流媒体处理等功能。本文详细阐述了 FFmpeg 的主…

云计算及其他计算

云计算知识思维导图&#xff1a;https://kdocs.cn/l/cpl2Kizx7IyC 云计算的核心判断标准通常基于美国国家标准与技术研究院&#xff08;NIST&#xff09;的定义&#xff0c;并结合实际应用场景。以下是判断一个服务是否为云计算的关键标准&#xff0c;以及对应的服务类型&#…

前端Toast提示快速入门

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f439;今日诗词:十年一觉扬州梦&#xff0c;赢得青楼薄幸名&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&#x1f64f; ⛳️点赞 ☀️收藏⭐️关注&#x1f4…

垂类大模型微调(一):认识LLaMA-Factory

LlamaFactory 是一个专注于 高效微调大型语言模型(LLMs) 的开源工具框架,尤其以支持 LLaMA(Meta 的大型语言模型系列)及其衍生模型(如 Chinese-LLaMA、Alpaca 等)而闻名。它的目标是简化模型微调流程,降低用户使用门槛; 官方文档 一、介绍 高效微调支持 支持多种微调…

Pytorch实现论文:基于多尺度融合生成对抗网络的水下图像增强

简介 简介:提出了一种新型的水下图像增强算法,基于多尺度融合生成对抗网络,名为UMSGAN,以解决低对比度和颜色失真的问题。首先经过亮度的处理,将处理后的图像输入设计的MFFEM模块和RM模块生成图像。该算法旨在适应各种水下场景,提供颜色校正和细节增强。 论文题目:Und…

从单片机的启动说起一个单片机到点灯发生了什么下——使用GPIO点一个灯

目录 前言 HAL库对GPIO的抽象 核心分析&#xff1a;HAL_GPIO_Init 前言 我们终于到达了熟悉的地方&#xff0c;对GPIO的初始化。经过漫长的铺垫&#xff0c;我们终于历经千辛万苦&#xff0c;来到了这里。关于GPIO的八种模式等更加详细的细节&#xff0c;由于只是点个灯&am…

基于大语言模型的推荐系统(1)

推荐系统&#xff08;recommendation system&#xff09;非常重要。事实上&#xff0c;搜索引擎&#xff0c;电子商务&#xff0c;视频&#xff0c;音乐平台&#xff0c;社交网络等等&#xff0c;几乎所有互联网应用的核心就是向用户推荐内容&#xff0c;商品&#xff0c;电影&…

计算机毕业设计SpringBoot+Vue.js新闻推荐系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Android 布局系列(一):LinearLayout 使用指南

引言 在 Android 开发中&#xff0c;布局是每个应用的基础&#xff0c;而 LinearLayout 无疑是最常见、最简单的布局之一。它允许我们将多个视图按顺序排列&#xff0c;可以选择水平方向&#xff08;horizontal&#xff09;或垂直方向&#xff08;vertical&#xff09;。 Line…