Android 实现从后台下载apk文件,保存到本地sd卡,使用系统安装apk,完成版本更新功能

LoadAppUtil.java

 import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List; /**
* Depiction:
* Author: kuzan
* Date: 2017/01/14 9:42
*/
public class LoadAppUtil { private static List<String> list = new ArrayList<>();
private static final int TIMEOUT = 10 * 60 * 1000; // 超时 public static final int LOAD_PROCESS = 1;
public static final int LOAD_SUCCEED = 2;
public static final int LOAD_ERROR = 3; /**
* 下载apk
* @param context
* @param packageName 保存apk的名称
* @param url apk后台下载的地址
*/
public static void loadApp(Context context, final String packageName, final String url) { final String path = getLoadAppPath(context, packageName); if (StringUtils.isEmptyString(path) || StringUtils.isEmptyString(url)) {
loadError(packageName);
return;
} // 判断是否在下载
if (list.contains(packageName)) {
return;
} list.add(packageName); new Thread(new Runnable() {
@Override
public void run() {
downloadUpdateFile(packageName, url, path);
}
}).start();
} /**
* 文件下载
* @param packageName 保存apk的名称
* @param down_url apk后台下载的地址
* @param file 保存apk的文件路径
* */
public static void downloadUpdateFile(String packageName, String down_url, String file) { int totalSize = 0; // 文件总大小
InputStream in = null;
FileOutputStream fos = null; FileUtils.deleteFile(file);
FileUtils.createFile(file); URL url;
try {
url = new URL(down_url); HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection(); httpURLConnection.setConnectTimeout(TIMEOUT); httpURLConnection.setReadTimeout(TIMEOUT); // 获取下载文件的size
totalSize = httpURLConnection.getContentLength();
Log.e("LoadAppUtil", "totalSize = " + totalSize); if (httpURLConnection.getResponseCode() == 404) {
loadError(packageName);
return;
} in = httpURLConnection.getInputStream();
fos = new FileOutputStream(file, false);
} catch (IOException e) {
e.printStackTrace();
loadError(packageName);
return;
} int downloadCount = 0; // 已下载大小
int updateProgress = 0; // 更新进度 byte buffer[] = new byte[64];
int readsize = 0; try {
LoadBean bean = new LoadBean(packageName,file,0);
post(LOAD_PROCESS,bean);
while ((readsize = in.read(buffer)) != -1) { fos.write(buffer, 0, readsize); // 计算已下载到的大小
downloadCount += readsize; // 先计算已下载的百分比,然后跟上次比较是否有增加,有则更新通知进度
int now = downloadCount * 100 / totalSize;
// Log.e(TAG, "now = " + now) ;
if (updateProgress < now) {
updateProgress = now;
// 发送下载进度
bean.setProcess(now);
post(LOAD_PROCESS,bean);
}
}
} catch (Exception e) {
e.printStackTrace();
loadError(packageName);
return;
} finally {
try {
fos.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
} // 发送下载完成消息
if(list.contains(packageName)){
list.remove(packageName);
LoadBean bean = new LoadBean(packageName,file,100);
post(LOAD_SUCCEED,bean);
} } private static void loadError(String packageName) {
if (list.contains(packageName)) {
list.remove(packageName);
}
// 发送下载错误消息
LoadBean bean = new LoadBean(packageName,"",0);
post(LOAD_ERROR,bean);
} /**
* 获取保存apk的文件路径
*
* @param context
* @return
*/
public static String getLoadAppPath(Context context, String packageName) {
if (FileUtils.isSdCardExist()) {
return context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator + packageName + ".apk";
}
return "";
} /**
* 判断文件是否存在
* @param path 文件路径
* @return
*/
public static boolean isFileExists(String path) {
if (TextUtils.isEmpty(path)) {
return false;
}
try {
File f=new File(path);
if(!f.exists()) {
return false;
}
}
catch (Exception e) {
return false;
} return true;
} /**
* 通知UI
* */
public static void post(int clickId,LoadBean bean){
RxBus.getDefault().post(RxBusEvent.newBuilder(R.id.load_apk).clickId(clickId).setObj(bean).build());
}
}

调用方法:

LoadAppUtil.loadApp(UpdateActivity.this, newVersionName, UrlConstants.UPLOAD_URL);

信息读取:(使用的消息通知是android RxBus)

 mySubscriptions.add(RxBus.getDefault().toObserverable(RxBusEvent.class).subscribe(new Action1<RxBusEvent>() {
@Override
public void call(final RxBusEvent rxBusEvent) {
if (rxBusEvent.getType() == R.id.load_apk) {
switch (rxBusEvent.getClickId()) {
case LoadAppUtil.LOAD_SUCCEED:
runOnUiThread(new Runnable() {
@Override
public void run() {
// 下载完成
Log.e("LOAD", "LOAD_SUCCEED");
AppUtils.installApp(UpdateActivity.this, (LoadBean) rxBusEvent.getObj().getPath());
isLoadFinish = true;
}
});
break; case LoadAppUtil.LOAD_PROCESS:
runOnUiThread(new Runnable() {
@Override
public void run() {
// 下载进度
isLoadFinish = false;
updateProgress((LoadBean) rxBusEvent.getObj());
}
});
break; case LoadAppUtil.LOAD_ERROR:
runOnUiThread(new Runnable() {
@Override
public void run() {
// 下载出错
Log.e("upload", "err");
isLoadFinish = false;
ToastUtils.ToastMessage(UpdateActivity.this, "下载失败");
}
});
break;
}
}
}
}));

LoadBean.java

 public class LoadBean {

     private String packageName;
private String path;
private int process; public LoadBean(String packageName, String path, int process) {
this.packageName = packageName;
this.path = path;
this.process = process;
} public String getPackageName() {
return packageName;
} public void setPackageName(String packageName) {
this.packageName = packageName;
} public String getPath() {
return path;
} public void setPath(String path) {
this.path = path;
} public int getProcess() {
return process;
} public void setProcess(int process) {
this.process = process;
}
}

Android实现版本更新的更多相关文章

  1. android应用版本更新功能---完整版

    源码下载地址:csdn下载地址:http://download.csdn.net/download/csdn576038874/9526085 博客园下载地址:http://files.cnblogs ...

  2. Android程序版本更新--通知栏更新下载安装(转)

    Android应用检查版本更新后,在通知栏下载,更新下载进度,下载完成自动安装,效果图如下: 检查当前版本号 AndroidManifest文件中的versionCode用来标识版本,在服务器放一个新 ...

  3. Android软件版本更新

     转的:适合新手学习,但在实际项目中不可这么做. 以下是我转的内容: ================================================================= ...

  4. android检测版本更新

    原理就是从服务器获取版本号和本得apk的版本号对比更新: //检查更新        Activity activity = this;        while(activity.getParent ...

  5. Android提示版本更新的实现

    一.首先,参考了以下文章<Android自动检测版本及自动升级> http://www.linuxidc.com/Linux/2011-10/45718p2.htm: 步骤: .检测当前版 ...

  6. Android关于版本更新下载安装之踩坑记录(针对7.0以上)

    最近刚刚把古老的项目targetSdk版本升级到26,升级之前是19(非常非常古老了).那么升级后一些问题开始出现. Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他 ...

  7. Android 全局弹出版本更新 Dialog 思考和解决办法

    Android 针对版本更新,需要做全局的弹出(需求:版本更新只需要在 App 内全局弹出就可以),思路是使用 AlertDialog ,然后设置 setType 为 TYPE_ALERT_WINDO ...

  8. Android其它新控件 (转)

    原文出处:http://blog.csdn.net/lavor_zl/article/details/51312715 Android其它新控件是指非Android大版本更新时提出的新控件,也非谷歌I ...

  9. 从 Eclipse 迁移至 Android Studio

    从 Eclipse 迁移至 Android Studio 本文内容 Android Studio 基础知识 迁移先决条件 将项目导入 Android Studio 后续步骤 将项目迁移至 Androi ...

随机推荐

  1. 静态NAT、动态NAT

    静态NAT.动态NAT 实验拓扑: 实验目的:熟悉网络地址转换协议 掌握静态NAT 和动态NAT的配置 分析静态NAT 和动态NAT的区别 使用show命令来检查NAT的运行情况 实验要求:按拓扑图来 ...

  2. (转)收集:Hibernate中常见问题 No row with the given identifier exists问题的原因及解决

    Hibernate中No row with the given identifier exists问题的原因及解决 产生此问题的原因: 有两张表,table1和table2.产生此问题的原因就是tab ...

  3. Linux基本命令之用户系统相关命令

    1.格式说明 [simon@localhost simon]$ [simon@localhost ~]$ 这两种方式表示相同.simon是指定用户,localhost是计算机名字,如果不设置默认为lo ...

  4. java source map

    Chrome 更新后出现了 jquery.min.map 404  (Not Found) 的信息 这个到底是什么东西?查询了一下,得到了以下资料 JQuery 官方解释 摘录一下內容 从 jQuer ...

  5. 关于HTTP_CLIENT_IP,HTTP_X_FORWAR

    HTTP_CLIENT_IP:可通过http头伪造HTTP_X_FORWARDED_FOR:可通过http头伪造REMOTE_ADDR:可能是用户真实IP也可能是代理IP 服务端获取IP地址 http ...

  6. eclipse的插件

    jode_1.0.6(Java Optimize and Decompile Environment ) 非常好用的Eeclipse的反编译插件,随时点击,随时查看源代码,但他的官方下载的都是核心源码 ...

  7. @Resource @Autowired 区别

    spring2.5提供了基于注解(Annotation-based)的配置,我们可以通过注解的方式来完成注入依赖.在Java代码中可以使用 @Resource或者@Autowired注解方式来经行注入 ...

  8. DML、DDL、DCL区别及介绍

    DML(data manipulation language):        它们是SELECT.UPDATE.INSERT.DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作 ...

  9. vs2008安装opencv2.4.6

    最近安装opencv2.4.6,发现犯了一个很愚蠢的错误,在此记录一下. opencv的头文件包含应该位于build文件夹内,而我误将opencv文件夹下的include包含了进去,造成无法找到头文件 ...

  10. Linux环境变量相关文件

    执行顺序为: /etc/profile -> (~/.bash_profile | ~/.bash_login | ~/.profile) -> ~/.bashrc -> /etc/ ...