其实这不是什么难事了,都有热更新的技术了,只是记录一下,大神勿嘲笑。

先说下思路,首先要有更新的接口,只要进入app,就监测一下接口,是否更新,更新的话,检测本地版本是否低于接口返回的版本,低的话,就根据返回的路径下载apk更新。接口返回的字段起码有 更新标志、更新版本,更新描述,apk下载地址。

更新标志应该有三种状态,更新,询问更新,强制更新,可以启动一个Service(不要忘记在清单文件中注册)来进行检查更新以及下载的工作;

这下面就是 Service里的全部代码,也不是很难理解,重要的地方都有注释。写好Service后,在代码中 startService()启动就可以了。

这里面弹出了一个讯问框,需要在清单文件中 加入权限,  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />,这是弹出全局讯问框的权限。

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Service;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView; import com.example.sdtz.wenmingweifang.R;
import com.example.sdtz.wenmingweifang.Tool.OkHttpUtil;
import com.example.sdtz.wenmingweifang.Util.App;
import com.example.sdtz.wenmingweifang.Util.MyUrl; import org.json.JSONException;
import org.json.JSONObject; import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; /**
* Created by sdtz on 2017/7/1.
*/
public class UpdateService extends Service {
private ProgressBar mProgressBar;//进度条
private TextView tv1;
private TextView tv2;
private String url = MyUrl.Httpurl;
private String VersionCode;
private String result;
private App app;
private String mSavePath;//apk保存地址
private String mVersion_path;
private String mVersion_name = "app.apk";//apk名
private float length;
private Dialog mDownloadDialog;//对话框
private int mProgress;//进度值
private static final int DOWNLOADING = 1;//apk下载中
private static final int DOWNLOAD_FINISH = 2;//apk下载完毕
private boolean mIsCancel = false;//是否取消下载标示符 @Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
} private Handler mUpdateProgressHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what){
case DOWNLOADING:
// 设置进度条
mProgressBar.setProgress(mProgress);
tv1.setText( mProgress + "/100");
float len = length/1024/1024;//将length转换为M单位
float b = (float)(Math.round(len*100))/100;//保留两位小数点
tv2.setText( b+"M");
break;
case DOWNLOAD_FINISH:
// 隐藏当前下载对话框
mDownloadDialog.dismiss();
// 安装 APK 文件
installAPK();
break;
default:
break;
}
};
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) { try {
VersionCode = getVersionName();
/* getJsonReuslt();*/
new OkHttpUtil().getJson(MyUrl.appdown, new OkHttpUtil.HttpCallBack() {
@Override
public void onSusscess(String data) throws JSONException {
JSONObject jo1 = new JSONObject(data);
app = new App();
app.setVersion(jo1.getString("version").toString());
app.setDescription(jo1.getString("description").toString());
app.setUrl(MyUrl.Httpurl+jo1.getString("url").toString());
app.setUpdate_flag(jo1.getString("update_flag").toString()); mVersion_path = app.getUrl();
//手机当前版本
String phoneVersion = VersionCode.substring(0,VersionCode.lastIndexOf("."));
Double jiekou = Double.parseDouble(app.getVersion());
Double bendi = null;
try {
bendi = Double.parseDouble(getVersionName());
} catch (Exception e) {
e.printStackTrace();
}
Log.d("==","接口:"+jiekou+"本地:"+bendi+"::"+app.toString());
//本地版本 与 接口返回版本 不一致,并且 更新标志为1 ,则更新
if( !VersionCode.equals(app.getVersion()) && (jiekou>bendi) && app.getUpdate_flag().equals("1")){
Log.d("==","::进入");
showDialog(app.getDescription());
}else if( !VersionCode.equals(app.getVersion()) && (jiekou>bendi) && app.getUpdate_flag().equals("2")){
showDownloadDialog();
}
}
});
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable throwable) {
throwable.printStackTrace();
} return super.onStartCommand(intent, flags, startId);
} /*
* 获取当前程序的版本号
*/
private String getVersionName() throws Exception{
//获取packagemanager的实例
PackageManager packageManager = getPackageManager();
//getPackageName()是你当前类的包名,0代表是获取版本信息
PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0);
return packInfo.versionName;
} private void showDialog(String drc) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this,AlertDialog.THEME_HOLO_LIGHT);
builder.setMessage(drc); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
showDownloadDialog();
}
}); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
}); AlertDialog alertDialog = builder.create();
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.setCanceledOnTouchOutside(true); alertDialog.show(); alertDialog.getButton(alertDialog.BUTTON_POSITIVE).setTextColor(Color.GREEN);
alertDialog.getButton(alertDialog.BUTTON_NEGATIVE).setTextColor(Color.RED); } /*
* 开启新线程下载文件
*/
private void downloadAPK() { new Thread(new Runnable() {
@Override
public void run() {
try{//检查sd是否挂载
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
String sdPath = Environment.getExternalStorageDirectory() + "/";
mSavePath = sdPath + "WenmingDownload"; File dir = new File(mSavePath);
if (!dir.exists())
dir.mkdir();
// 下载文件
HttpURLConnection conn = (HttpURLConnection) new URL(mVersion_path).openConnection();
conn.connect();
InputStream is = conn.getInputStream();
length = conn.getContentLength();
File apkFile = new File(mSavePath, mVersion_name);
FileOutputStream fos = new FileOutputStream(apkFile); int count = 0;
byte[] buffer = new byte[1024];
while (!mIsCancel){
int numread = is.read(buffer);
count += numread;
// 计算进度条的当前位置
mProgress = (int) ((count/length) * 100);
// 更新进度条
mUpdateProgressHandler.sendEmptyMessage(DOWNLOADING); // 下载完成
if (numread < 0){
mUpdateProgressHandler.sendEmptyMessage(DOWNLOAD_FINISH);
break;
}
fos.write(buffer, 0, numread);
}
fos.close();
is.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
} /*
* 下载到本地后执行安装
*/
protected void installAPK() {
File apkFile = new File(mSavePath, mVersion_name);
if (!apkFile.exists())
return; Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file://" + apkFile.toString());
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent); }
/*
* 显示正在下载对话框
*/
protected void showDownloadDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("版本更新,下载中。。。");
View view = LayoutInflater.from(this).inflate(R.layout.dialog_progress, null);
mProgressBar = (ProgressBar) view.findViewById(R.id.id_progress);
tv1 = (TextView) view.findViewById(R.id.tv1);
tv2 = (TextView) view.findViewById(R.id.tv2);
builder.setView(view);
mDownloadDialog = builder.create();
mDownloadDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mDownloadDialog.show(); // 下载文件
downloadAPK();
} }

  

android 实现检测版本,下载apk更新(附源码)的更多相关文章

  1. 转载—— android 瀑布流的实现详解,附源码

    介绍 参考自:https://github.com/dodola/android_waterfall,因为原来的代码封装不好,所以,我根据源码的思路,重新写了一遍,所以有了现在这个项目:https:/ ...

  2. [BOT]自己动手实现android 饼状图,PieGraphView,附源码解析

    本文要介绍的是一个参照手机支付宝app里面记账本功能里的"饼状图"实现的控件.通常app中可能的数据展示控件有柱状图,折线图,饼状图等,如果需要一个包含多种View控件的库,那么 ...

  3. wpf 模拟抖音很火的罗盘时钟,附源码,下载就能跑

    wpf 模拟抖音很火的罗盘时钟,附源码 前端时间突然发现,抖音火了个壁纸,就是黑底蕾丝~~~  错错错,黑底白字的罗盘时钟! 作为程序员的我,也觉得很新颖,所以想空了研究下,这不,空下来了就用wpf, ...

  4. Android自动检测版本及自动升级

    步骤: 1.检测当前版本的信息AndroidManifest.xml-->manifest-->android:versionName. 2.从服务器获取版本号(版本号存在于xml文件中) ...

  5. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  6. 【流媒体开发】VLC Media Player - Android 平台源码编译 与 二次开发详解 (提供详细800M下载好的编译源码及eclipse可调试播放器源码下载)

    作者 : 韩曙亮  博客地址 : http://blog.csdn.net/shulianghan/article/details/42707293 转载请注明出处 : http://blog.csd ...

  7. 【转】可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)

    原文地址:http://www.cnblogs.com/justnow/p/3382160.html (最新版本:V6.0,2017.12.11 .即将推出Xamarin移动端版本,包括 Androi ...

  8. 可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)

      (最新版本:V6.2,2019.01.03 .Xamarin移动端版本已经推出,包括 Android 和 iOS) GGTalk开源即时通讯系统(简称GG)是QQ的高仿版,同时支持局域网和广域网, ...

  9. 分享一组很赞的 jQuery 特效【附源码下载】

    作为最优秀的 JavaScript 库之一,jQuery 不仅使用简单灵活,同时还有许多成熟的插件可供选择,它可以帮助你在项目中加入漂亮的效果.这篇文章挑选了8个优秀的 jQuery 实例教程,这些  ...

  10. Cesium专栏-雷达遮罩动态扫描(附源码下载)

    Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...

随机推荐

  1. Android的诞生

    Android操作系统最初由Andy Rubin开发,刚开始主要支持手机,被Google收购后,对Android进行了改良,使其可以用于平板电脑等其它领域. 1.1.1 Android的发展史Andr ...

  2. P3Depth: Monocular Depth Estimation with a Piecewise Planarity Prior

    1. 论文简介 论文题目:P3Depth: Monocular Depth Estimation with a Piecewise Planarity Prior Paper地址:paper Code ...

  3. 升级csproj文件为vs2017工程格式(SDK样式)

    csproj文件在VS2017后格式变更为SDK样式.framework项目如果需要源链接等等功能,需要进行手动升级. 升级过程 升级需要Project2015To2017Nuget包. > d ...

  4. xpath解析数据的方法

    1 功能描述 2 1.实例化一个etree对象,且需要将被解析的页面源码数据加载到该对象中 3 2.调用etree对象中的XPath表达式实现标签的定位和内容捕获 4 3.环境安装 pip insta ...

  5. [LeetCode]226.翻转二叉树——递归遍历交换孩子

    题目   翻转一棵二叉树. 4 / \ 2 7 / \ / \ 1 3 6 9 //转换为: 4 / \ 7 2 / \ / \ 9 6 3 1 代码 TreeNode* invertTree(Tre ...

  6. Mysql--回顾提要

    一.写在前 知识学了就忘!不用就忘!我太健忘!特此记录!用于复习打卡!Mysql干就完事了! 二.来辣! MyISAM表把自增主键最大id记录到文件,重启也不会丢.InnoDB记录到内存,重启数据库和 ...

  7. 微信小程序技巧-让特定组件首页始终展示修改编译条件即可,不用改json

  8. 让人眼前一亮的应用「GitHub 热点速览」

    大开眼界的一期 GitHub 热门项目,类似 Django 存在的 pynecone,搞定 Windows.Office 激活的 Microsoft-Activation-Scripts,都让我的收藏 ...

  9. Java入门与进阶P-5.3+P-5.4

    数组的元素 有效的下标 最小的下标是0,最大的下标是数组的元素个数-1 可是编译器不会检查看你是否用了有效的下标 但是如果运行的时候出现了无效的下标,可能会导致程序终止 定义数组变量 元素个数必须是整 ...

  10. Pulsar负载均衡原理及优化

    前言 前段时间我们在升级 Pulsar 版本的时候发现升级后最后一个节点始终没有流量. 虽然对业务使用没有任何影响,但负载不均会导致资源的浪费. 和同事沟通后得知之前的升级也会出现这样的情况,最终还是 ...