Android实现版本更新
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实现版本更新的更多相关文章
- android应用版本更新功能---完整版
源码下载地址:csdn下载地址:http://download.csdn.net/download/csdn576038874/9526085 博客园下载地址:http://files.cnblogs ...
- Android程序版本更新--通知栏更新下载安装(转)
Android应用检查版本更新后,在通知栏下载,更新下载进度,下载完成自动安装,效果图如下: 检查当前版本号 AndroidManifest文件中的versionCode用来标识版本,在服务器放一个新 ...
- Android软件版本更新
转的:适合新手学习,但在实际项目中不可这么做. 以下是我转的内容: ================================================================= ...
- android检测版本更新
原理就是从服务器获取版本号和本得apk的版本号对比更新: //检查更新 Activity activity = this; while(activity.getParent ...
- Android提示版本更新的实现
一.首先,参考了以下文章<Android自动检测版本及自动升级> http://www.linuxidc.com/Linux/2011-10/45718p2.htm: 步骤: .检测当前版 ...
- Android关于版本更新下载安装之踩坑记录(针对7.0以上)
最近刚刚把古老的项目targetSdk版本升级到26,升级之前是19(非常非常古老了).那么升级后一些问题开始出现. Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他 ...
- Android 全局弹出版本更新 Dialog 思考和解决办法
Android 针对版本更新,需要做全局的弹出(需求:版本更新只需要在 App 内全局弹出就可以),思路是使用 AlertDialog ,然后设置 setType 为 TYPE_ALERT_WINDO ...
- Android其它新控件 (转)
原文出处:http://blog.csdn.net/lavor_zl/article/details/51312715 Android其它新控件是指非Android大版本更新时提出的新控件,也非谷歌I ...
- 从 Eclipse 迁移至 Android Studio
从 Eclipse 迁移至 Android Studio 本文内容 Android Studio 基础知识 迁移先决条件 将项目导入 Android Studio 后续步骤 将项目迁移至 Androi ...
随机推荐
- ntfs mount fail after upgrade win10
http://www.cnblogs.com/wangbo2008/p/3782730.html linux下挂载NTFS分区错误修复 今天在linux下打开win的NTFS硬盘总是提示出错了,而 ...
- ASP对数据库的操作方法
ASP与数据库-连接.写入.修改.删除.显示代码属性与方法 PageCount 属性: 决定 Recordset 对象包括多少“页”的数据. 这里的“页”是数据记录的集合,大小等于 Pa ...
- PAT (Advanced Level) 1085. Perfect Sequence (25)
可以用双指针(尺取法),也可以枚举起点,二分终点. #include<cstdio> #include<cstring> #include<cmath> #incl ...
- Mysql(集群)业务水平切割 垂直切割(Amoeba)
Amoeba原理戳这里:Amoeba详细介绍 需要根据企业 数据业务进行切割,垂直切割又称为纵向切割. 垂直切割通说的说就是有多个表,对表进行分离(用户数据.博客文章数据.照片数据.标签数据类型.群 ...
- Cocos2dx 学习笔记整理----在项目中使用图片(三)
这节练习下DragonBones. 手机由于性能所限,需要特注意资源的使用. 游戏项目的话由于资源比较多,一般都会用到DragonBones来做动作,这个又称为龙骨. DragonBones传送点:h ...
- iOS开发之圆角指定
如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可(项目需要使用QuartzCore框架).而若要指定某几个角(小于4)为圆角而别的不变时 ...
- Java 的Object类
1.toString()是Objectde的方法,如果不重写,直接输出对象或者用对象调用toString()输出是会输出包名.类名@对象哈希码的无符号十六进制表示 子类如果重写了这个方法,可以隐式调用 ...
- FreeRTOS基础以及UIP之协程--C语言剑走偏锋
在FreeRTOS中和UIP中,都使用到了一种C语言实现的多任务计数,专业的定义叫做协程(coroutine),顾名思义,这是一种协作的例程, 跟具有操作系统概念的线程不一样,协程是在用户空间利用程序 ...
- LPC1788的内部EEPROM使用
Lpc1788内置有eeprom 使用代码 #ifndef __E2PRONINCHIP_H_ #define __E2PROMINCHIP_H #include "common.h&quo ...
- css3动画-animation
animation驱使一组css style变化到另外一组css style,它可以定义keyframes的集合,指定style的开始和结束状态,它是transition的增强. 配置animatio ...