Android 一个相对完整的自动升级功能实现代码
由于项目的需要最近做了一个关于Android自动升级的功能,下面将贴出Android手机客户端的完整代码。这段代码参考别的代码居多,由于不满足需求,所以自己仅仅改了一些需要变动的内容,其他功能都是按照原作者的代码来写的。希望能够给大家提供帮助。
package com.example.myapi; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.List; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ProgressBar; import android.widget.Toast; public class UpdateManager { /* 下载中 */ private static final int DOWNLOAD = 1; /* 下载结束 */ private static final int DOWNLOAD_FINISH = 2; /* 下载保存路径 */ private String mSavePath; /* 记录进度条数量 */ private int progress; /* 是否取消更新 */ private boolean cancelUpdate = false; private Context mContext; /* 更新进度条 */ private ProgressBar mProgress; private Dialog mDownloadDialog; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { // 正在下载 case DOWNLOAD: // 设置进度条位置 mProgress.setProgress(progress); break; case DOWNLOAD_FINISH: // 安装文件 installApk(); break; case 200://服务端信息 //如果有新版本 checkUpdate();//更新信息 break; case 101: Toast.makeText(mContext, "手机中没有内存卡,无法安装!", Toast.LENGTH_LONG).show(); break; default: break; } }; }; public UpdateManager(Context context) { this.mContext = context; /** * 此段代码是用于检测版本是否有升级 * 如果有升级则向handler发送200 */ mHandler.sendEmptyMessage(200); } /** * 检测软件更新 */ public void checkUpdate() { showNoticeDialog(); } /** * 检查软件是否有更新版本 * * @return */ private boolean isUpdate(){ return false; } /** * 获取软件版本号 * * @param context * @return */ private int getVersionCode(Context context) { int versionCode = 0; try { // 获取软件版本号,对应AndroidManifest.xml下android:versionCode versionCode = context.getPackageManager().getPackageInfo("com.szy.update", 0).versionCode; } catch (NameNotFoundException e) { e.printStackTrace(); } return versionCode; } /** * 显示软件更新对话框 */ private void showNoticeDialog() { // 构造对话框 AlertDialog.Builder builder = new Builder(mContext); builder.setTitle("提示"); builder.setMessage("已检测到软件更新"); // 更新 builder.setPositiveButton("立即更新", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); // 显示下载对话框 showDownloadDialog(); } }); // 稍后更新 builder.setNegativeButton("稍后更新", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); Dialog noticeDialog = builder.create(); noticeDialog.setCanceledOnTouchOutside(false); noticeDialog.show(); } /** * 显示软件下载对话框 */ private void showDownloadDialog() { // 构造软件下载对话框 AlertDialog.Builder builder = new Builder(mContext); builder.setTitle("提示"); // 给下载对话框增加进度条 final LayoutInflater inflater = LayoutInflater.from(mContext); View v = inflater.inflate(R.layout.softupdate_progress, null); mProgress = (ProgressBar) v.findViewById(R.id.update_progress); builder.setView(v); // 取消更新 builder.setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); // 设置取消状态 cancelUpdate = true; } }); mDownloadDialog = builder.create(); mDownloadDialog.setCanceledOnTouchOutside(false); mDownloadDialog.show(); // 现在文件 downloadApk(); } /** * 下载apk文件 */ private void downloadApk() { // 启动新线程下载软件 new downloadApkThread().start(); } /** * 下载文件线程 * * */ private class downloadApkThread extends Thread { @Override public void run() { try { // 判断SD卡是否存在,并且是否具有读写权限 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { // 获得存储卡的路径 String sdpath = Environment.getExternalStorageDirectory() + "/"; mSavePath = sdpath + "fortrundownload"; URL url = new URL(/*此处填写下载文件的路径*/""); // 创建连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.connect(); // 获取文件大小 int length = conn.getContentLength(); // 创建输入流 InputStream is = conn.getInputStream(); File file = new File(mSavePath); // 判断文件目录是否存在 if (!file.exists()) { file.mkdir(); } File apkFile = new File(mSavePath, "此处填写文件的名称(apk名称)"); FileOutputStream fos = new FileOutputStream(apkFile); int count = 0; // 缓存 byte buf[] = new byte[1024]; // 写入到文件中 do { int numread = is.read(buf); count += numread; // 计算进度条位置 progress = (int) (((float) count / length) * 100); // 更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if (numread <= 0) { // 下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } // 写入文件 fos.write(buf, 0, numread); } while (!cancelUpdate);// 点击取消就停止下载. fos.close(); is.close(); }else{//////如果不存在内存卡,则将下载下来的apk文件存入手机内存 mSavePath = "/data/data/com.fortrun.quickrecieve/files"; File file = new File(mSavePath); Log.e("savepath", mSavePath); URL url = new URL("apk文件下载路径"); // 创建连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.connect(); // 获取文件大小 int length = conn.getContentLength(); Log.e("startlength", length+""); // 创建输入流 InputStream is = conn.getInputStream(); // 判断文件目录是否存在 if(file.exists()){ file.delete(); } if (!file.exists()) { boolean flag = file.mkdir(); Log.e("flag", flag+""); } /* // 设置权限 String command = "chmod 666" + file.getAbsolutePath();; Runtime runtime = Runtime.getRuntime(); runtime.exec(command); // ContextWrapper cw = new ContextWrapper(mContext); // File directory = cw.getDir("media", Context.MODE_PRIVATE); // File apkFile = cw.getDir(mSavePath+"/"+msg9902.getFileName(), Context.MODE_PRIVATE); File apkFile = new File(mSavePath,msg9902.getFileName()); String commandFile = "chmod 666" + apkFile.getAbsolutePath(); Log.e("apkfile", apkFile.getAbsolutePath()); Runtime runtimeFile = Runtime.getRuntime(); runtimeFile.exec(commandFile);*/ // FileOutputStream fos = new FileOutputStream(apkFile); //644标记改程序有读、写、运行权限 /* String command = "chmod 644 " + mSavePath+"/"+msg9902.getFileName(); String command2 = "chmod 777 " + mSavePath; Runtime runtime = Runtime.getRuntime(); try { runtime.exec(command2); runtime.exec(command); } catch (IOException e) { e.printStackTrace(); }*/ FileOutputStream fos=(FileOutputStream)mContext.openFileOutput( "apk文件名称", mContext.MODE_WORLD_READABLE|mContext.MODE_WORLD_WRITEABLE); int count = 0; // 缓存 byte buf[] = new byte[1024]; // 写入到文件中 do { int numread = is.read(buf); count += numread; // 计算进度条位置 progress = (int) (((float) count / length) * 100); // 更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if (numread <= 0) { // 下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } // 写入文件 fos.write(buf, 0, numread); } while (!cancelUpdate);// 点击取消就停止下载. fos.flush(); fos.close(); is.close(); } } catch (MalformedURLException e) { Log.e("downloadApkThread", e.getMessage()); } catch (IOException e) { Log.e("downloadApkThread", e.getMessage()); } // 取消下载对话框显示 mDownloadDialog.dismiss(); } }; /** * 安装APK文件 */ private void installApk() { //之前是604,705/*标注拥有最高权限*/ /* String command = "chmod 644 " + mSavePath+"/"+msg9902.getFileName(); String command2 = "chmod 777 " + mSavePath; Runtime runtime = Runtime.getRuntime(); try { runtime.exec(command2); runtime.exec(command); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }*/ File apkfile = new File(mSavePath,"apk文件名称"); if (!apkfile.exists()) { return; } Intent i = new Intent(Intent.ACTION_VIEW); /** * i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); *这段代码在Android4.0一下的系统中没必要写, * 但是如果是在Android4.0以上的系统中进行安装,就必须要写上了。因为如果你不写上就会 * 出现在安装的过程中莫名其妙的关掉,并且不会提示安装完成。 */ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android.package-archive"); mContext.startActivity(i); } }
分类:
Android
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探