android版本更新全程解析

2024-05-07 03:38

本文主要是介绍android版本更新全程解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

随时随地技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666)

版本更新是每个项目必备的功能,思路大概都差不多,首先获取到客户端的版本号与服务器上最新的版本进行比较,如果需要进行更新,则返回下载的链接,进行下载安装,直接上代码:

MainActivity:

package com.home.update;import android.os.Bundle;
import android.app.Activity;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);UpdateManager um = new UpdateManager(MainActivity.this);um.checkUpdateInfo();}}

版本更新工具类:

package com.home.update;import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;public class UpdateManager {private Context context;// 发起版本检测的urlprivate final static String CHECKURL = "http://....";// 服务器返回的apk安装包下载路径private static String downloadUrl = "";private Dialog noticeDialog;private ProgressBar mProgress;private boolean interceptFlag = false;private Dialog downloadDialog;private static final int DOWN_UPDATE = 1;private static final int DOWN_OVER = 2;private int progress;// 下载包安装本地存放路径private static final String savePath = Environment.getExternalStorageDirectory() + "/guyun/update/";private static final String saveFileName = savePath + "sport.apk";public UpdateManager(Context context) {this.context = context;}/*** 更新UI的Handler*/private Handler handler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case DOWN_UPDATE:mProgress.setProgress(progress);break;case DOWN_OVER:if (downloadDialog != null)downloadDialog.dismiss();installApk();break;default:break;}};};/*** 版本更新接口*/public void checkUpdateInfo() {// 向服务器发出检查请求,如果需要更新则弹出提示对话框if (isNeedUpdate()) {// 显示提示对话框showNoticeDialog();}}/*** 检查当前版本是否需要更新* * @return*/private boolean isNeedUpdate() {String versionName = getVersionName(context);boolean isNeedUpdate = testVersion(versionName);return isNeedUpdate;}/*** 获取本地版本名称* * @param context* @return*/private String getVersionName(Context context) {String versionName = "";try {// 包名改为自己应用的包名即可versionName = context.getPackageManager().getPackageInfo("com.home.update", 1).versionName;} catch (NameNotFoundException e) {e.printStackTrace();}return versionName;}/*** 向服务器发起版本检测请求,服务器根据提交的版本参数和服务器上的当前版本进行比较 如果符合更新要求,返回最新版本号和下载URL* * @param versionName* @return*/private boolean testVersion(String version) {boolean isNeedUpdate = false;// 这里的url具体拼装方式应根据服务器需要的格式而定String url = CHECKURL + "?version=" + version;String result = get(url);try {// 这里的具体解析方式应根据自己服务器返回的数据而定JSONObject jsonObj = new JSONObject(result);int code = jsonObj.getInt("code");if (code == 0) {JSONObject valueObj = jsonObj.getJSONObject("value");String lastVersion = valueObj.getString("version");downloadUrl = valueObj.getString("url");if (version.equals(lastVersion)) {isNeedUpdate = false;} else {isNeedUpdate = true;}} else {isNeedUpdate = false;}} catch (JSONException e) {e.printStackTrace();}return isNeedUpdate;}/*** 以get方式发送请求* * @param url* @return*/private String get(String url) {BufferedReader reader = null;StringBuffer sb = null;String result = "";HttpClient client = new DefaultHttpClient();HttpGet request = new HttpGet(url);request.addHeader("Content-Type", " text/json");try {// 发送请求,得到响应HttpResponse response = client.execute(request);// 如果请求成功if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));sb = new StringBuffer();String line = "";while ((line = reader.readLine()) != null) {sb.append(line);}} else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE) {result = "维护或繁忙";}} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if (reader != null) {reader.close();reader = null;}} catch (IOException e) {result = "维护或繁忙";e.printStackTrace();}}if (sb != null) {result = sb.toString();}return result;}/*** 弹出更新提示对话框*/private void showNoticeDialog() {AlertDialog.Builder builder = new Builder(context);builder.setTitle("软件版本更新");builder.setMessage("版本可以更新哦");builder.setPositiveButton("下载", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();showDownloadDialog();}});builder.setNegativeButton("以后再说", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}});noticeDialog = builder.create();noticeDialog.show();// 设置弹出对话框大小属性WindowManager.LayoutParams lp = noticeDialog.getWindow().getAttributes();lp.width = 400;lp.height = 500;noticeDialog.getWindow().setAttributes(lp);}/*** 下载进度对话框*/private void showDownloadDialog() {AlertDialog.Builder builder = new Builder(context);builder.setTitle("正在下载,请稍后...");final LayoutInflater inflater = LayoutInflater.from(context);View v = inflater.inflate(R.layout.progress, null);mProgress = (ProgressBar) v.findViewById(R.id.progress);builder.setView(v);builder.setNegativeButton("取消", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();interceptFlag = true;}});downloadDialog = builder.create();downloadDialog.show();downloadApk();}/*** 启动线程下载apk*/private void downloadApk() {Thread downLoadThread = new Thread(downApkRunnable);downLoadThread.start();}/*** 安装包下载线程*/private Runnable downApkRunnable = new Runnable() {@Overridepublic void run() {try {URL url = new URL(downloadUrl);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.connect();int length = conn.getContentLength();InputStream is = conn.getInputStream();File file = new File(savePath);if (!file.exists()) {file.mkdir();}String apkFile = saveFileName;File ApkFile = new File(apkFile);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);// 更新进度handler.sendEmptyMessage(DOWN_UPDATE);if (numread <= 0) {// 下载完成通知安装handler.sendEmptyMessage(DOWN_OVER);break;}fos.write(buf, 0, numread);} while (!interceptFlag);// 点击取消就停止下载.fos.close();is.close();} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}};/*** 安装APK*/private void installApk() {File apkfile = new File(saveFileName);if (!apkfile.exists()) {return;}Intent i = new Intent(Intent.ACTION_VIEW);i.setDataAndType(Uri.parse("file://" + apkfile.toString()),"application/vnd.android.package-archive");context.startActivity(i);}
}

如果是在4.0以上版本,不能在主线程访问网络,部分功能需要作相应调整开启异步子线程。
 

这篇关于android版本更新全程解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/966215

相关文章

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

全面解析Golang 中的 Gorilla CORS 中间件正确用法

《全面解析Golang中的GorillaCORS中间件正确用法》Golang中使用gorilla/mux路由器配合rs/cors中间件库可以优雅地解决这个问题,然而,很多人刚开始使用时会遇到配... 目录如何让 golang 中的 Gorilla CORS 中间件正确工作一、基础依赖二、错误用法(很多人一开

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

在macOS上安装jenv管理JDK版本的详细步骤

《在macOS上安装jenv管理JDK版本的详细步骤》jEnv是一个命令行工具,正如它的官网所宣称的那样,它是来让你忘记怎么配置JAVA_HOME环境变量的神队友,:本文主要介绍在macOS上安装... 目录前言安装 jenv添加 JDK 版本到 jenv切换 JDK 版本总结前言China编程在开发 Java

MySQL CTE (Common Table Expressions)示例全解析

《MySQLCTE(CommonTableExpressions)示例全解析》MySQL8.0引入CTE,支持递归查询,可创建临时命名结果集,提升复杂查询的可读性与维护性,适用于层次结构数据处... 目录基本语法CTE 主要特点非递归 CTE简单 CTE 示例多 CTE 示例递归 CTE基本递归 CTE 结

Spring Boot 3.x 中 WebClient 示例详解析

《SpringBoot3.x中WebClient示例详解析》SpringBoot3.x中WebClient是响应式HTTP客户端,替代RestTemplate,支持异步非阻塞请求,涵盖GET... 目录Spring Boot 3.x 中 WebClient 全面详解及示例1. WebClient 简介2.

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分