安卓版本升级功能

通用版本升级功能,拿去就能用!

import android.content.Context;

import android.content.Intent;

import android.content.pm.PackageManager;

import android.net.Uri;

import android.os.Build;

import android.os.Bundle;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.Button;

import android.widget.ProgressBar;

import android.widget.TextView;

import android.widget.Toast;

import androidx.annotation.Nullable;

import androidx.core.content.FileProvider;

import androidx.fragment.app.DialogFragment;

import com.htnova.fly.R;

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.URL;

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| public class HtUpdateDialogFragment extends DialogFragment { private ProgressBar progressBar; private TextView tvProgress; private Button btnUpdate, btnSkip, btnCancel; private volatile boolean isCancelled = false; private final String apkUrl = "http://115.190.154.26/app-release.apk"; private final int serverVersionCode = 2; private final int currentVersionCode; public HtUpdateDialogFragment(Context context) { currentVersionCode = getVersionCode(context); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.dialog_update, container, false); initView(view); return view; } private void initView(View view) { progressBar = view.findViewById(R.id.progress_bar); tvProgress = view.findViewById(R.id.tv_progress); btnUpdate = view.findViewById(R.id.btn_update); btnSkip = view.findViewById(R.id.btn_skip); btnCancel = view.findViewById(R.id.btn_cancel); TextView tvInfo = view.findViewById(R.id.tv_update_info); tvInfo.setText("当前版本:" + currentVersionCode + "\n服务器版本:" + serverVersionCode + "\n\n更新内容:\n- 修复问题\n- 优化性能"); btnUpdate.setOnClickListener(v -> { btnUpdate.setVisibility(View.GONE); btnSkip.setVisibility(View.GONE); btnCancel.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE); tvProgress.setVisibility(View.VISIBLE); startDownload(); }); btnSkip.setOnClickListener(v -> dismiss()); btnCancel.setOnClickListener(v -> { isCancelled = true; Toast.makeText(getContext(), "已取消下载", Toast.LENGTH_SHORT).show(); dismiss(); }); } private void startDownload() { new Thread(() -> { HttpURLConnection conn = null; InputStream is = null; BufferedOutputStream bos = null; try { URL url = new URL(apkUrl); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(10000); conn.setReadTimeout(10000); conn.connect(); int length = conn.getContentLength(); if (length <= 0) { showToast("服务器未返回文件大小"); return; } is = new BufferedInputStream(conn.getInputStream()); File apkFile = new File(requireContext().getExternalFilesDir(null), "update.apk"); bos = new BufferedOutputStream(new FileOutputStream(apkFile)); byte[] buffer = new byte[8192]; // 8KB缓冲区 int count = 0; int bytesRead; int lastProgress = 0; while ((bytesRead = is.read(buffer)) != -1 && !isCancelled) { bos.write(buffer, 0, bytesRead); count += bytesRead; int progress = (int) (count * 100L / length); if (progress != lastProgress) { int finalProgress = progress; requireActivity().runOnUiThread(() -> { progressBar.setProgress(finalProgress); tvProgress.setText("下载进度:" + finalProgress + "%"); }); lastProgress = progress; } } bos.flush(); if (!isCancelled) { requireActivity().runOnUiThread(() -> { Toast.makeText(getContext(), "下载完成,准备安装", Toast.LENGTH_SHORT).show(); installApk(apkFile); dismiss(); }); } } catch (Exception e) { Log.e("HtUpdateDialog", "下载出错:" + e.getMessage(), e); showToast("下载失败:" + e.getMessage()); } finally { try { if (is != null) is.close(); if (bos != null) bos.close(); if (conn != null) conn.disconnect(); } catch (Exception ignored) { } } }).start(); } private void installApk(File apkFile) { Context context = requireContext(); Uri apkUri; Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { apkUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", apkFile); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } else { apkUri = Uri.fromFile(apkFile); } intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); context.startActivity(intent); } private int getVersionCode(Context context) { try { return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode; } catch (PackageManager.NameNotFoundException e) { return 0; } } private void showToast(String msg) { requireActivity().runOnUiThread(() -> Toast.makeText(getContext(), msg, Toast.LENGTH_LONG).show()); } } |

R.layout.dialog_update

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="20dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tv_update_info" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发现新版本..." android:textSize="16sp" /> <ProgressBar android:id="@+id/progress_bar" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" android:visibility="gone" /> <TextView android:id="@+id/tv_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下载进度:0%" android:visibility="gone" android:paddingTop="10dp" /> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="20dp"> <Button android:id="@+id/btn_update" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="立即更新" /> <Button android:id="@+id/btn_skip" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="跳过" /> <Button android:id="@+id/btn_cancel" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="取消下载" android:visibility="gone"/> </LinearLayout> </LinearLayout> |

application中添加

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <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/file_paths" /> </provider> |

xml文件夹下新建file_paths.xml

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="update_apk" path="." /> </paths> |

使用new HtUpdateDialogFragment(this).show(getSupportFragmentManager(), "update_dialog");

相关推荐
程序猿陌名!44 分钟前
Android-EDLA RK3576谷歌ATTESTION-KEY从申请到烧录以及验证谷歌认证标志全流程
android
s***35301 小时前
怎么下载安装yarn
android·前端·后端
z***94841 小时前
使用rustDesk搭建私有远程桌面
android·前端·后端
q***06291 小时前
【细如狗】记录一次使用MySQL的Binlog进行数据回滚的完整流程
android·数据库·mysql
0***86331 小时前
图文详述:MySQL的下载、安装、配置、使用
android·mysql·adb
9***44631 小时前
SQLyog安装配置(注册码)连接MySQL
android·mysql·adb
o***11142 小时前
【MySQL】MySQL库的操作
android·数据库·mysql
4***572 小时前
MySQL 数据增删改查
android·数据库·mysql
修炼者6 小时前
Android Studio的技巧
android·android studio