转载请著名原处:

http://blog.csdn.net/lowprofile_coding/article/details/77852131

检查更新是任何app都会用到功能,任何一个app都不可能第一个版本就能把所有的需求都能实现,通过不断的挖掘需求迭代才能使app变的越来越好。检查更新自动下载安装分以下几个步骤:

  • 请求服务器判断是否有最新版本(通过versionCode)
  • 如果有最新版本,就把最新的apk文件下载到本地
  • 下载完成之后给系统发起一个安装的Intent。

打开项目下面app下面build.gradle文件,我们可以看到里面有两个属性versionCode跟versionName,versionCode是一个int类型的值,用他来更新版本,versionName是一个浮点型的值,给用户看的,告诉用户当前的是几点几版本。每次app升级的时候,都要对这两个值进行增加。这里我们就用默认的值好了。

因为检查更新需要请求服务器,所以我们引入之前封装的okhttp库:

compile 'com.ansen.http:okhttpencapsulation:1.0.1'

需要访问网络跟写入sdcard的权限,记得在AndroidManifest.xml钟增加权限。

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

需要重写Application,并且在AndroidManifest.xml文件中给application标签name属性指向重写的MyApplication,在MyApplication中初始化HTTPCaller。

public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();HttpConfig httpConfig = new HttpConfig();httpConfig.setAgent(true);//有代理的情况能不能访问httpConfig.setDebug(true);//是否debug模式 如果是debug模式打印loghttpConfig.setTagName("ansen");//打印log的tagname//可以添加一些公共字段 每个接口都会带上httpConfig.addCommonField("pf", "android");httpConfig.addCommonField("version_code", "" + Utils.getVersionCode(getApplicationContext()));//初始化HTTPCaller类HTTPCaller.getInstance().setHttpConfig(httpConfig);}
}

我们把version_code作为公共参数,通过Utils类的getVersionCode方法获取值。getVersionCode方法需要传入一个context对象,通过Context获取包管理器,调用PackageManager的getPackageInfo方法获取包信息,调用他的公有属性versionCode获取当前版本号。

public static int getVersionCode(Context ctx) {// 获取packagemanager的实例int version = 0;try {PackageManager packageManager = ctx.getPackageManager();//getPackageName()是你当前程序的包名PackageInfo packInfo = packageManager.getPackageInfo(ctx.getPackageName(), 0);version = packInfo.versionCode;} catch (Exception e) {e.printStackTrace();}return version;
}

MainActivity对应的activity_main.xml文件比较简单,上面一个TextView用来显示当前版本号,下面一个检查更新按钮。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="10dp"><TextView
        android:id="@+id/tv_current_version_code"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"android:textSize="16sp"android:text="当前版本"/><Button
        android:id="@+id/btn_check_update"android:layout_marginTop="10dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="检查更新"/>
</LinearLayout>

MainActivity.java(为了方便讲解先看一部分代码),在onCreate中给显示当前版本的TextView赋值,跟检查更新的按钮设置点击监听。点击按钮发送一个get请求服务器。我们知道有没有新版本是通过versionCode的值来判断的,但是我们这里却没有在请求url后面加参数,因为我们在MyApplication中已经把versionCode设置成了公共参数。

public class MainActivity extends AppCompatActivity implements View.OnClickListener{private ProgressDialog progressDialog;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tvCurrentVersionCode= (TextView) findViewById(R.id.tv_current_version_code);tvCurrentVersionCode.setText("当前版本:"+ Utils.getVersionCode(this));findViewById(R.id.btn_check_update).setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.btn_check_update://检查更新HTTPCaller.getInstance().get(CheckUpdate.class,"http://139.196.35.30:8080/OkHttpTest/checkUpdate.do",null,requestDataCallback);break;}}·············
}

get请求回调监听,先判断返回的状态码,如果状态码等于0就是有新版本,有新版本的话下载url也是有值的,把下载url传给showUpdaloadDialog方法。

private RequestDataCallback<CheckUpdate> requestDataCallback=new RequestDataCallback<CheckUpdate>(){@Overridepublic void dataCallback(CheckUpdate obj) {if(obj!=null){if(obj.getErrorCode()==0){//有新版本showUpdaloadDialog(obj.getUrl());}else{//没有新版本Toast.makeText(MainActivity.this,obj.getErrorReason(),Toast.LENGTH_LONG).show();}}}
};

显示是否更新对话框,弹一个对话框让用户去判断要不要更新,总是友好一点。我看国内一些很大公司的app如果用户的手机有wifi的话都是直接后台下载更新包,而不经过用户的同意,我觉得这种做法太不考虑用户的感受了。Android系统的开放性总是用来干一些影响用户体验的事情。这里我们谈一个确认更新对话框。如果用户点击了确认按钮就调用startUpload方法。当前点击取消按钮关闭对话框啥都不干了。

private void showUpdaloadDialog(final String downloadUrl){// 这里的属性可以一直设置,因为每次设置后返回的是一个builder对象AlertDialog.Builder builder = new AlertDialog.Builder(this);// 设置提示框的标题builder.setTitle("版本升级").setIcon(R.mipmap.ic_launcher). // 设置提示框的图标setMessage("发现新版本!请及时更新").// 设置要显示的信息setPositiveButton("确定", new DialogInterface.OnClickListener() {// 设置确定按钮@Overridepublic void onClick(DialogInterface dialog, int which) {startUpload(downloadUrl);//下载最新的版本程序}}).setNegativeButton("取消", null);//设置取消按钮,null是什么都不做,并关闭对话框AlertDialog alertDialog = builder.create();// 显示对话框alertDialog.show();
}

开始更新方法,首先创建一个进度条对话框,设置进度条样式,设置messgage,然后调用Utils类的getSaveFilePath静态方法获取一个sdcard的路径,把下载下来的apk文件就保存在这个路径。然后调用HTTPCaller类的downloadFile方法去下载文件。有三个参数:下载url,文件保存路径,下载进度回调。下载进度回调是一个ProgressUIListener接口,用内部内的方式重写三个方法。onUIProgressStart下载开始时把总文件长度赋值给进度条的总长度,显示进度条。onUIProgressChanged下载进度变化时更新进度条。onUIProgressFinish下载完成销毁进度条,调用openAPK方法。

private void startUpload(String downloadUrl){progressDialog=new ProgressDialog(this);progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);progressDialog.setMessage("正在下载新版本");progressDialog.setCancelable(false);//不能手动取消下载进度对话框final String fileSavePath=Utils.getSaveFilePath(downloadUrl);HTTPCaller.getInstance().downloadFile(downloadUrl,fileSavePath,null,new ProgressUIListener(){@Overridepublic void onUIProgressStart(long totalBytes) {//下载开始progressDialog.setMax((int)totalBytes);progressDialog.show();}//更新进度@Overridepublic void onUIProgressChanged(long numBytes, long totalBytes, float percent, float speed) {progressDialog.setProgress((int)numBytes);}@Overridepublic void onUIProgressFinish() {//下载完成Toast.makeText(MainActivity.this,"下载完成",Toast.LENGTH_LONG).show();progressDialog.dismiss();openAPK(fileSavePath);}});
}

下载完成安装apk,给系统发送一个intent。

private void openAPK(String fileSavePath){Intent intent = new Intent();intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.setAction(Intent.ACTION_VIEW);intent.setDataAndType(Uri.parse("file://"+fileSavePath),"application/vnd.android.package-archive");startActivity(intent);
}

运行源码,效果图如下:

注意事项:

这里我们为什么有新版本?

我们看第一张效果图当前的版本是1,我早就打包了一个versionCode等于2的签名apk放到服务器上了,所以只要我们给的参数versionCode的值小于2都是可以升级的。

覆盖安装签名问题

我们都知道在调试的时候直接运行app装到手机上安装包是临时签名,所以再企业开发中每次打这个版本的最后包的时候都会正式签名一下,保证所有版本的安装包都是一个签名,只有签名一样才能覆盖安装。所以你们拿到源码的时候直接运行app,点击更新,下载完成,点击安装的时候会出现应用未安装的情况。在项目的根目录下我有新建一个jks文件夹,里面包含了签名文件,还有一个已经签好名的1.0版本,如果你想先看效果可以把1.0版本的apk文件通过社交软件什么的发送到手机上,安装升级能覆盖安装的。当然你也可以自己签名。签名文件跟密码都在jks文件夹下。

源码下载

如果你想第一时间看我的后期文章,扫码关注公众号,每周不定期推送Android开发实战教程文章…

      Android开发666 - 安卓开发技术分享扫描二维码加关注

Android检查更新下载安装相关推荐

  1. Windows Android SDK下载安装,配置,异常问题解决教程

    Windows Android SDK下载安装,配置,异常问题解决教程 参考文章: (1)Windows Android SDK下载安装,配置,异常问题解决教程 (2)https://www.cnbl ...

  2. jenkins依赖的android sdk下载安装

    jenkins下android sdk下载安装 一:Android SDK 二:SDK Tools 三:Android SDK Licences 一:Android SDK 下载地址:http://t ...

  3. 最新鲜最详细的Android SDK下载安装及配置教程

    最近Neo突发神经,想要将学过的一些计算机视觉.机器学习中的算法都放到移动设备上去跑跑,因为移动开发是大势所趋嘛,希望能够通过这样一个实践的过程,找到一些新的灵感(该不会是为了赚钱吧-),我自己目前也 ...

  4. Android Studio下载安装教程及开发环境搭建

    Android Stuio是本次Google io的一大亮点啊,一大早起来就赶紧下载来玩玩了... 如果你不幸被墙了,可以去这个帖子下载,我已经上传到百度盘里面了. [Android利器]Androi ...

  5. Android Studio下载安装及配置图文教程

    AndroidStudio下载地址:https://developer.android.com/sdk/installing/studio.html#download 如果你没有FQ或者不会FQ可以从 ...

  6. win10环境下Android SDK下载安装及配置教程

    最近在配置Android环境时,发现网上许多教程都是在win7版本下进行配置的且存在许多问题,按照流程无法正确配置环境,因此我在收集网上资料及亲自配置成功的情况下,写出此文章.如有无法配置成功的话,欢 ...

  7. win10环境下Android SDK下载安装及配置教程----Android SDK安装

    接着上一篇文章,这个章节主要是安装Android SDK和配置Android SDK环境 1.下载并安装Android SDK 下载Android SDK Tools,可以选择去我的百度网盘上下载(链 ...

  8. 【android】超级详细Android Studio下载安装教程(附:JDK1.8安装教程)

    文章目录 一.官网下载 二.安装 三.配置 安装Android的前提是下载安装JDK,如果没有安装JDK,请参照如下步骤安装JDK: JDK_1.8的下载安装和环境变量的配置[详细步骤] 一.官网下载 ...

  9. 最新最详细Android SDK下载安装与配置

    最近要学习一门叫Android应用开发的专业课,需要安装Ecplise以及配置Android运行环境配置.但是对于怎么配置,我是一点也不了解,网上的教程也是五花八门,在参考了许多教程,以及不断地尝试下 ...

  10. 2018年Android SDK下载安装及配置教程

    下载并安装Android SDK 官网(可翻墙选择):http://developer.android.com/sdk/index.html 不可翻墙选择:http://www.androiddevt ...

最新文章

  1. Windows 2008 R2 X64 安装WebsitePanel(WSP虚拟主机管理面板)
  2. js 判断变量是否有值返回bool_基础 |判断 JS 中的变量类型竟然可以如此简单
  3. JSP页面Table的数据绑定
  4. mysql数据库从删库到跑路之mysql多表查询
  5. poj2513 Fence Repair(小根堆)
  6. java非公平锁_Java多线程 -- 公平锁和非公平锁的一些思考
  7. 关于Google插件Postman的使用方法
  8. 【汇编语言】程序设计过程,如何避免数据类型匹配错误?
  9. Python格式化输出方法
  10. Krasovsky_1940_Albers投影介绍及转换
  11. 【元胞自动机】基于matlab元胞自动机人流疏散【含Matlab源码 665期】
  12. 通信基站能耗综合管理系统
  13. 海康NVR设备上传人脸图片到人脸库
  14. DM - Manager工具
  15. 请求的url中带#是什么意思呢?
  16. 计算在1901年1月1日至2000年12月31日间共有多少个星期天落在每月的第一天上
  17. Conway生命游戏
  18. jquery input的value赋值
  19. python中str类型和object类型_pandas str和object类型之间的区别
  20. 4.测试基础(软件测试阶段的划分)

热门文章

  1. 【ESP 保姆级教程】疯狂点灯篇 —— 案例:ESP8266 + LED + 按键 + 阿里云物联网平台 + 阿里云物联网Web应用(详细操作过程,全部源码)
  2. 腾讯云IM-SDK集成(web端)完成IM登录
  3. python如何实现手眼定标_kafka基础和python如何操作kafka
  4. 10秒!看清导数与微分的关系
  5. 西电计算机科学与技术学院王,王书振 - 西安电子科技大学 - 计算机科学与技术学院...
  6. android透明度100%,Android设置字体透明度
  7. python右对齐 数字_python format格式化进阶-左对齐右对齐 取位数
  8. 2068个开源的网站模板
  9. 混沌大学--喜茶模式拷贝指南
  10. FPGA驱动步进电机