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

相关文章

python常见环境管理工具超全解析

《python常见环境管理工具超全解析》在Python开发中,管理多个项目及其依赖项通常是一个挑战,下面:本文主要介绍python常见环境管理工具的相关资料,文中通过代码介绍的非常详细,需要的朋友... 目录1. conda2. pip3. uvuv 工具自动创建和管理环境的特点4. setup.py5.

全面解析HTML5中Checkbox标签

《全面解析HTML5中Checkbox标签》Checkbox是HTML5中非常重要的表单元素之一,通过合理使用其属性和样式自定义方法,可以为用户提供丰富多样的交互体验,这篇文章给大家介绍HTML5中C... 在html5中,Checkbox(复选框)是一种常用的表单元素,允许用户在一组选项中选择多个项目。本

Python包管理工具核心指令uvx举例详细解析

《Python包管理工具核心指令uvx举例详细解析》:本文主要介绍Python包管理工具核心指令uvx的相关资料,uvx是uv工具链中用于临时运行Python命令行工具的高效执行器,依托Rust实... 目录一、uvx 的定位与核心功能二、uvx 的典型应用场景三、uvx 与传统工具对比四、uvx 的技术实

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析

《Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析》InstantiationAwareBeanPostProcessor是Spring... 目录一、什么是InstantiationAwareBeanPostProcessor?二、核心方法解

深入解析 Java Future 类及代码示例

《深入解析JavaFuture类及代码示例》JavaFuture是java.util.concurrent包中用于表示异步计算结果的核心接口,下面给大家介绍JavaFuture类及实例代码,感兴... 目录一、Future 类概述二、核心工作机制代码示例执行流程2. 状态机模型3. 核心方法解析行为总结:三