安卓版本升级功能

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

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");

相关推荐
行稳方能走远18 小时前
Android java 学习笔记 1
android·java
zhimingwen18 小时前
【開發筆記】修復 macOS 上 JADX 啟動崩潰並實現快速啟動
android·macos·反編譯
longxibo19 小时前
mysql数据快速导入doris
android·大数据·python·mysql
十六年开源服务商19 小时前
WordPress网站模板设计完整指南
android
summerkissyou198719 小时前
Android13-Bluetooth-代码目录介绍
android·蓝牙
曾帅16819 小时前
uniapp安卓启动图
android·opencv·uni-app
_李小白20 小时前
【Android 美颜相机】第一天:认识Android-GPUImage项目
android·数码相机
Mr -老鬼20 小时前
谷歌安卓文档查询建议:优先使用英语页面的原因及实践指南
android
2501_9151063220 小时前
常见 iOS 抓包工具的使用方式与组合思路
android·ios·小程序·https·uni-app·iphone·webview
鹏程十八少20 小时前
1.Android 3分钟跑通腾讯 Shadow 插件化官方Demo:零反射、手把手实战(基于源码依赖)
android·前端·面试